diff options
| author | 2020-08-03 15:06:44 +0000 | |
|---|---|---|
| committer | 2020-08-03 15:06:44 +0000 | |
| commit | b64793999546ed8adebaeebd9d8345d18db8927d (patch) | |
| tree | 4357c27b561d73b0e089727c6ed659f2ceff5f47 /gnu/llvm/tools/clang/lib/Serialization | |
| parent | Add support for UTF-8 DISPLAY-HINTs with octet length. For now only (diff) | |
| download | wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.tar.xz wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.zip | |
Remove LLVM 8.0.1 files.
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Serialization')
17 files changed, 0 insertions, 35076 deletions
diff --git a/gnu/llvm/tools/clang/lib/Serialization/ASTCommon.cpp b/gnu/llvm/tools/clang/lib/Serialization/ASTCommon.cpp deleted file mode 100644 index ca826d83d47..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/ASTCommon.cpp +++ /dev/null @@ -1,445 +0,0 @@ -//===--- ASTCommon.cpp - Common stuff for ASTReader/ASTWriter----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines common functions that both ASTReader and ASTWriter use. -// -//===----------------------------------------------------------------------===// - -#include "ASTCommon.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/Basic/IdentifierTable.h" -#include "clang/Serialization/ASTDeserializationListener.h" -#include "llvm/Support/DJB.h" - -using namespace clang; - -// Give ASTDeserializationListener's VTable a home. -ASTDeserializationListener::~ASTDeserializationListener() { } - -serialization::TypeIdx -serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { - unsigned ID = 0; - switch (BT->getKind()) { - case BuiltinType::Void: - ID = PREDEF_TYPE_VOID_ID; - break; - case BuiltinType::Bool: - ID = PREDEF_TYPE_BOOL_ID; - break; - case BuiltinType::Char_U: - ID = PREDEF_TYPE_CHAR_U_ID; - break; - case BuiltinType::UChar: - ID = PREDEF_TYPE_UCHAR_ID; - break; - case BuiltinType::UShort: - ID = PREDEF_TYPE_USHORT_ID; - break; - case BuiltinType::UInt: - ID = PREDEF_TYPE_UINT_ID; - break; - case BuiltinType::ULong: - ID = PREDEF_TYPE_ULONG_ID; - break; - case BuiltinType::ULongLong: - ID = PREDEF_TYPE_ULONGLONG_ID; - break; - case BuiltinType::UInt128: - ID = PREDEF_TYPE_UINT128_ID; - break; - case BuiltinType::Char_S: - ID = PREDEF_TYPE_CHAR_S_ID; - break; - case BuiltinType::SChar: - ID = PREDEF_TYPE_SCHAR_ID; - break; - case BuiltinType::WChar_S: - case BuiltinType::WChar_U: - ID = PREDEF_TYPE_WCHAR_ID; - break; - case BuiltinType::Short: - ID = PREDEF_TYPE_SHORT_ID; - break; - case BuiltinType::Int: - ID = PREDEF_TYPE_INT_ID; - break; - case BuiltinType::Long: - ID = PREDEF_TYPE_LONG_ID; - break; - case BuiltinType::LongLong: - ID = PREDEF_TYPE_LONGLONG_ID; - break; - case BuiltinType::Int128: - ID = PREDEF_TYPE_INT128_ID; - break; - case BuiltinType::Half: - ID = PREDEF_TYPE_HALF_ID; - break; - case BuiltinType::Float: - ID = PREDEF_TYPE_FLOAT_ID; - break; - case BuiltinType::Double: - ID = PREDEF_TYPE_DOUBLE_ID; - break; - case BuiltinType::LongDouble: - ID = PREDEF_TYPE_LONGDOUBLE_ID; - break; - case BuiltinType::ShortAccum: - ID = PREDEF_TYPE_SHORT_ACCUM_ID; - break; - case BuiltinType::Accum: - ID = PREDEF_TYPE_ACCUM_ID; - break; - case BuiltinType::LongAccum: - ID = PREDEF_TYPE_LONG_ACCUM_ID; - break; - case BuiltinType::UShortAccum: - ID = PREDEF_TYPE_USHORT_ACCUM_ID; - break; - case BuiltinType::UAccum: - ID = PREDEF_TYPE_UACCUM_ID; - break; - case BuiltinType::ULongAccum: - ID = PREDEF_TYPE_ULONG_ACCUM_ID; - break; - case BuiltinType::ShortFract: - ID = PREDEF_TYPE_SHORT_FRACT_ID; - break; - case BuiltinType::Fract: - ID = PREDEF_TYPE_FRACT_ID; - break; - case BuiltinType::LongFract: - ID = PREDEF_TYPE_LONG_FRACT_ID; - break; - case BuiltinType::UShortFract: - ID = PREDEF_TYPE_USHORT_FRACT_ID; - break; - case BuiltinType::UFract: - ID = PREDEF_TYPE_UFRACT_ID; - break; - case BuiltinType::ULongFract: - ID = PREDEF_TYPE_ULONG_FRACT_ID; - break; - case BuiltinType::SatShortAccum: - ID = PREDEF_TYPE_SAT_SHORT_ACCUM_ID; - break; - case BuiltinType::SatAccum: - ID = PREDEF_TYPE_SAT_ACCUM_ID; - break; - case BuiltinType::SatLongAccum: - ID = PREDEF_TYPE_SAT_LONG_ACCUM_ID; - break; - case BuiltinType::SatUShortAccum: - ID = PREDEF_TYPE_SAT_USHORT_ACCUM_ID; - break; - case BuiltinType::SatUAccum: - ID = PREDEF_TYPE_SAT_UACCUM_ID; - break; - case BuiltinType::SatULongAccum: - ID = PREDEF_TYPE_SAT_ULONG_ACCUM_ID; - break; - case BuiltinType::SatShortFract: - ID = PREDEF_TYPE_SAT_SHORT_FRACT_ID; - break; - case BuiltinType::SatFract: - ID = PREDEF_TYPE_SAT_FRACT_ID; - break; - case BuiltinType::SatLongFract: - ID = PREDEF_TYPE_SAT_LONG_FRACT_ID; - break; - case BuiltinType::SatUShortFract: - ID = PREDEF_TYPE_SAT_USHORT_FRACT_ID; - break; - case BuiltinType::SatUFract: - ID = PREDEF_TYPE_SAT_UFRACT_ID; - break; - case BuiltinType::SatULongFract: - ID = PREDEF_TYPE_SAT_ULONG_FRACT_ID; - break; - case BuiltinType::Float16: - ID = PREDEF_TYPE_FLOAT16_ID; - break; - case BuiltinType::Float128: - ID = PREDEF_TYPE_FLOAT128_ID; - break; - case BuiltinType::NullPtr: - ID = PREDEF_TYPE_NULLPTR_ID; - break; - case BuiltinType::Char8: - ID = PREDEF_TYPE_CHAR8_ID; - break; - case BuiltinType::Char16: - ID = PREDEF_TYPE_CHAR16_ID; - break; - case BuiltinType::Char32: - ID = PREDEF_TYPE_CHAR32_ID; - break; - case BuiltinType::Overload: - ID = PREDEF_TYPE_OVERLOAD_ID; - break; - case BuiltinType::BoundMember: - ID = PREDEF_TYPE_BOUND_MEMBER; - break; - case BuiltinType::PseudoObject: - ID = PREDEF_TYPE_PSEUDO_OBJECT; - break; - case BuiltinType::Dependent: - ID = PREDEF_TYPE_DEPENDENT_ID; - break; - case BuiltinType::UnknownAny: - ID = PREDEF_TYPE_UNKNOWN_ANY; - break; - case BuiltinType::ARCUnbridgedCast: - ID = PREDEF_TYPE_ARC_UNBRIDGED_CAST; - break; - case BuiltinType::ObjCId: - ID = PREDEF_TYPE_OBJC_ID; - break; - case BuiltinType::ObjCClass: - ID = PREDEF_TYPE_OBJC_CLASS; - break; - case BuiltinType::ObjCSel: - ID = PREDEF_TYPE_OBJC_SEL; - break; -#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ - case BuiltinType::Id: \ - ID = PREDEF_TYPE_##Id##_ID; \ - break; -#include "clang/Basic/OpenCLImageTypes.def" -#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ - case BuiltinType::Id: \ - ID = PREDEF_TYPE_##Id##_ID; \ - break; -#include "clang/Basic/OpenCLExtensionTypes.def" - case BuiltinType::OCLSampler: - ID = PREDEF_TYPE_SAMPLER_ID; - break; - case BuiltinType::OCLEvent: - ID = PREDEF_TYPE_EVENT_ID; - break; - case BuiltinType::OCLClkEvent: - ID = PREDEF_TYPE_CLK_EVENT_ID; - break; - case BuiltinType::OCLQueue: - ID = PREDEF_TYPE_QUEUE_ID; - break; - case BuiltinType::OCLReserveID: - ID = PREDEF_TYPE_RESERVE_ID_ID; - break; - case BuiltinType::BuiltinFn: - ID = PREDEF_TYPE_BUILTIN_FN; - break; - case BuiltinType::OMPArraySection: - ID = PREDEF_TYPE_OMP_ARRAY_SECTION; - break; - } - - return TypeIdx(ID); -} - -unsigned serialization::ComputeHash(Selector Sel) { - unsigned N = Sel.getNumArgs(); - if (N == 0) - ++N; - unsigned R = 5381; - for (unsigned I = 0; I != N; ++I) - if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I)) - R = llvm::djbHash(II->getName(), R); - return R; -} - -const DeclContext * -serialization::getDefinitiveDeclContext(const DeclContext *DC) { - switch (DC->getDeclKind()) { - // These entities may have multiple definitions. - case Decl::TranslationUnit: - case Decl::ExternCContext: - case Decl::Namespace: - case Decl::LinkageSpec: - case Decl::Export: - return nullptr; - - // C/C++ tag types can only be defined in one place. - case Decl::Enum: - case Decl::Record: - if (const TagDecl *Def = cast<TagDecl>(DC)->getDefinition()) - return Def; - return nullptr; - - // FIXME: These can be defined in one place... except special member - // functions and out-of-line definitions. - case Decl::CXXRecord: - case Decl::ClassTemplateSpecialization: - case Decl::ClassTemplatePartialSpecialization: - return nullptr; - - // Each function, method, and block declaration is its own DeclContext. - case Decl::Function: - case Decl::CXXMethod: - case Decl::CXXConstructor: - case Decl::CXXDestructor: - case Decl::CXXConversion: - case Decl::ObjCMethod: - case Decl::Block: - case Decl::Captured: - // Objective C categories, category implementations, and class - // implementations can only be defined in one place. - case Decl::ObjCCategory: - case Decl::ObjCCategoryImpl: - case Decl::ObjCImplementation: - return DC; - - case Decl::ObjCProtocol: - if (const ObjCProtocolDecl *Def - = cast<ObjCProtocolDecl>(DC)->getDefinition()) - return Def; - return nullptr; - - // FIXME: These are defined in one place, but properties in class extensions - // end up being back-patched into the main interface. See - // Sema::HandlePropertyInClassExtension for the offending code. - case Decl::ObjCInterface: - return nullptr; - - default: - llvm_unreachable("Unhandled DeclContext in AST reader"); - } - - llvm_unreachable("Unhandled decl kind"); -} - -bool serialization::isRedeclarableDeclKind(unsigned Kind) { - switch (static_cast<Decl::Kind>(Kind)) { - case Decl::TranslationUnit: - case Decl::ExternCContext: - // Special case of a "merged" declaration. - return true; - - case Decl::Namespace: - case Decl::NamespaceAlias: - case Decl::Typedef: - case Decl::TypeAlias: - case Decl::Enum: - case Decl::Record: - case Decl::CXXRecord: - case Decl::ClassTemplateSpecialization: - case Decl::ClassTemplatePartialSpecialization: - case Decl::VarTemplateSpecialization: - case Decl::VarTemplatePartialSpecialization: - case Decl::Function: - case Decl::CXXDeductionGuide: - case Decl::CXXMethod: - case Decl::CXXConstructor: - case Decl::CXXDestructor: - case Decl::CXXConversion: - case Decl::UsingShadow: - case Decl::ConstructorUsingShadow: - case Decl::Var: - case Decl::FunctionTemplate: - case Decl::ClassTemplate: - case Decl::VarTemplate: - case Decl::TypeAliasTemplate: - case Decl::ObjCProtocol: - case Decl::ObjCInterface: - case Decl::Empty: - return true; - - // Never redeclarable. - case Decl::UsingDirective: - case Decl::Label: - case Decl::UnresolvedUsingTypename: - case Decl::TemplateTypeParm: - case Decl::EnumConstant: - case Decl::UnresolvedUsingValue: - case Decl::IndirectField: - case Decl::Field: - case Decl::MSProperty: - case Decl::ObjCIvar: - case Decl::ObjCAtDefsField: - case Decl::NonTypeTemplateParm: - case Decl::TemplateTemplateParm: - case Decl::Using: - case Decl::UsingPack: - case Decl::ObjCMethod: - case Decl::ObjCCategory: - case Decl::ObjCCategoryImpl: - case Decl::ObjCImplementation: - case Decl::ObjCProperty: - case Decl::ObjCCompatibleAlias: - case Decl::LinkageSpec: - case Decl::Export: - case Decl::ObjCPropertyImpl: - case Decl::PragmaComment: - case Decl::PragmaDetectMismatch: - case Decl::FileScopeAsm: - case Decl::AccessSpec: - case Decl::Friend: - case Decl::FriendTemplate: - case Decl::StaticAssert: - case Decl::Block: - case Decl::Captured: - case Decl::ClassScopeFunctionSpecialization: - case Decl::Import: - case Decl::OMPThreadPrivate: - case Decl::OMPRequires: - case Decl::OMPCapturedExpr: - case Decl::OMPDeclareReduction: - case Decl::BuiltinTemplate: - case Decl::Decomposition: - case Decl::Binding: - return false; - - // These indirectly derive from Redeclarable<T> but are not actually - // redeclarable. - case Decl::ImplicitParam: - case Decl::ParmVar: - case Decl::ObjCTypeParam: - return false; - } - - llvm_unreachable("Unhandled declaration kind"); -} - -bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) { - // Friend declarations in dependent contexts aren't anonymous in the usual - // sense, but they cannot be found by name lookup in their semantic context - // (or indeed in any context), so we treat them as anonymous. - // - // This doesn't apply to friend tag decls; Sema makes those available to name - // lookup in the surrounding context. - if (D->getFriendObjectKind() && - D->getLexicalDeclContext()->isDependentContext() && !isa<TagDecl>(D)) { - // For function templates and class templates, the template is numbered and - // not its pattern. - if (auto *FD = dyn_cast<FunctionDecl>(D)) - return !FD->getDescribedFunctionTemplate(); - if (auto *RD = dyn_cast<CXXRecordDecl>(D)) - return !RD->getDescribedClassTemplate(); - return true; - } - - // At block scope, we number everything that we need to deduplicate, since we - // can't just use name matching to keep things lined up. - // FIXME: This is only necessary for an inline function or a template or - // similar. - if (D->getLexicalDeclContext()->isFunctionOrMethod()) { - if (auto *VD = dyn_cast<VarDecl>(D)) - return VD->isStaticLocal(); - // FIXME: What about CapturedDecls (and declarations nested within them)? - return isa<TagDecl>(D) || isa<BlockDecl>(D); - } - - // Otherwise, we only care about anonymous class members / block-scope decls. - // FIXME: We need to handle lambdas and blocks within inline / templated - // variables too. - if (D->getDeclName() || !isa<CXXRecordDecl>(D->getLexicalDeclContext())) - return false; - return isa<TagDecl>(D) || isa<FieldDecl>(D); -} diff --git a/gnu/llvm/tools/clang/lib/Serialization/ASTCommon.h b/gnu/llvm/tools/clang/lib/Serialization/ASTCommon.h deleted file mode 100644 index 12e26c1fc2b..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/ASTCommon.h +++ /dev/null @@ -1,116 +0,0 @@ -//===- ASTCommon.h - Common stuff for ASTReader/ASTWriter -*- C++ -*-=========// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines common functions that both ASTReader and ASTWriter use. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_SERIALIZATION_ASTCOMMON_H -#define LLVM_CLANG_LIB_SERIALIZATION_ASTCOMMON_H - -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclFriend.h" -#include "clang/Serialization/ASTBitCodes.h" - -namespace clang { - -namespace serialization { - -enum DeclUpdateKind { - UPD_CXX_ADDED_IMPLICIT_MEMBER, - UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, - UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, - UPD_CXX_ADDED_FUNCTION_DEFINITION, - UPD_CXX_ADDED_VAR_DEFINITION, - UPD_CXX_POINT_OF_INSTANTIATION, - UPD_CXX_INSTANTIATED_CLASS_DEFINITION, - UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT, - UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER, - UPD_CXX_RESOLVED_DTOR_DELETE, - UPD_CXX_RESOLVED_EXCEPTION_SPEC, - UPD_CXX_DEDUCED_RETURN_TYPE, - UPD_DECL_MARKED_USED, - UPD_MANGLING_NUMBER, - UPD_STATIC_LOCAL_NUMBER, - UPD_DECL_MARKED_OPENMP_THREADPRIVATE, - UPD_DECL_MARKED_OPENMP_DECLARETARGET, - UPD_DECL_EXPORTED, - UPD_ADDED_ATTR_TO_RECORD -}; - -TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT); - -template <typename IdxForTypeTy> -TypeID MakeTypeID(ASTContext &Context, QualType T, IdxForTypeTy IdxForType) { - if (T.isNull()) - return PREDEF_TYPE_NULL_ID; - - unsigned FastQuals = T.getLocalFastQualifiers(); - T.removeLocalFastQualifiers(); - - if (T.hasLocalNonFastQualifiers()) - return IdxForType(T).asTypeID(FastQuals); - - assert(!T.hasLocalQualifiers()); - - if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) - return TypeIdxFromBuiltin(BT).asTypeID(FastQuals); - - if (T == Context.AutoDeductTy) - return TypeIdx(PREDEF_TYPE_AUTO_DEDUCT).asTypeID(FastQuals); - if (T == Context.AutoRRefDeductTy) - return TypeIdx(PREDEF_TYPE_AUTO_RREF_DEDUCT).asTypeID(FastQuals); - - return IdxForType(T).asTypeID(FastQuals); -} - -unsigned ComputeHash(Selector Sel); - -/// Retrieve the "definitive" declaration that provides all of the -/// visible entries for the given declaration context, if there is one. -/// -/// The "definitive" declaration is the only place where we need to look to -/// find information about the declarations within the given declaration -/// context. For example, C++ and Objective-C classes, C structs/unions, and -/// Objective-C protocols, categories, and extensions are all defined in a -/// single place in the source code, so they have definitive declarations -/// associated with them. C++ namespaces, on the other hand, can have -/// multiple definitions. -const DeclContext *getDefinitiveDeclContext(const DeclContext *DC); - -/// Determine whether the given declaration kind is redeclarable. -bool isRedeclarableDeclKind(unsigned Kind); - -/// Determine whether the given declaration needs an anonymous -/// declaration number. -bool needsAnonymousDeclarationNumber(const NamedDecl *D); - -/// Visit each declaration within \c DC that needs an anonymous -/// declaration number and call \p Visit with the declaration and its number. -template<typename Fn> void numberAnonymousDeclsWithin(const DeclContext *DC, - Fn Visit) { - unsigned Index = 0; - for (Decl *LexicalD : DC->decls()) { - // For a friend decl, we care about the declaration within it, if any. - if (auto *FD = dyn_cast<FriendDecl>(LexicalD)) - LexicalD = FD->getFriendDecl(); - - auto *ND = dyn_cast_or_null<NamedDecl>(LexicalD); - if (!ND || !needsAnonymousDeclarationNumber(ND)) - continue; - - Visit(ND, Index++); - } -} - -} // namespace serialization - -} // namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/gnu/llvm/tools/clang/lib/Serialization/ASTReader.cpp deleted file mode 100644 index e0b2b24a0d3..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/ASTReader.cpp +++ /dev/null @@ -1,12563 +0,0 @@ -//===- ASTReader.cpp - AST File Reader ------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the ASTReader class, which reads AST files. -// -//===----------------------------------------------------------------------===// - -#include "clang/Serialization/ASTReader.h" -#include "ASTCommon.h" -#include "ASTReaderInternals.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/ASTMutationListener.h" -#include "clang/AST/ASTUnresolvedSet.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclBase.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclFriend.h" -#include "clang/AST/DeclGroup.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/DeclarationName.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/ExternalASTSource.h" -#include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/ODRHash.h" -#include "clang/AST/RawCommentList.h" -#include "clang/AST/TemplateBase.h" -#include "clang/AST/TemplateName.h" -#include "clang/AST/Type.h" -#include "clang/AST/TypeLoc.h" -#include "clang/AST/TypeLocVisitor.h" -#include "clang/AST/UnresolvedSet.h" -#include "clang/Basic/CommentOptions.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/DiagnosticOptions.h" -#include "clang/Basic/ExceptionSpecificationType.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/FileSystemOptions.h" -#include "clang/Basic/IdentifierTable.h" -#include "clang/Basic/LLVM.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/MemoryBufferCache.h" -#include "clang/Basic/Module.h" -#include "clang/Basic/ObjCRuntime.h" -#include "clang/Basic/OperatorKinds.h" -#include "clang/Basic/PragmaKinds.h" -#include "clang/Basic/Sanitizers.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/SourceManagerInternals.h" -#include "clang/Basic/Specifiers.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/TargetOptions.h" -#include "clang/Basic/TokenKinds.h" -#include "clang/Basic/Version.h" -#include "clang/Lex/HeaderSearch.h" -#include "clang/Lex/HeaderSearchOptions.h" -#include "clang/Lex/MacroInfo.h" -#include "clang/Lex/ModuleMap.h" -#include "clang/Lex/PreprocessingRecord.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Lex/PreprocessorOptions.h" -#include "clang/Lex/Token.h" -#include "clang/Sema/ObjCMethodList.h" -#include "clang/Sema/Scope.h" -#include "clang/Sema/Sema.h" -#include "clang/Sema/Weak.h" -#include "clang/Serialization/ASTBitCodes.h" -#include "clang/Serialization/ASTDeserializationListener.h" -#include "clang/Serialization/ContinuousRangeMap.h" -#include "clang/Serialization/GlobalModuleIndex.h" -#include "clang/Serialization/Module.h" -#include "clang/Serialization/ModuleFileExtension.h" -#include "clang/Serialization/ModuleManager.h" -#include "clang/Serialization/PCHContainerOperations.h" -#include "clang/Serialization/SerializationDiagnostic.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/APSInt.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/Hashing.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/Bitcode/BitstreamReader.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Compression.h" -#include "llvm/Support/DJB.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/SaveAndRestore.h" -#include "llvm/Support/Timer.h" -#include "llvm/Support/VersionTuple.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <cstdio> -#include <ctime> -#include <iterator> -#include <limits> -#include <map> -#include <memory> -#include <string> -#include <system_error> -#include <tuple> -#include <utility> -#include <vector> - -using namespace clang; -using namespace clang::serialization; -using namespace clang::serialization::reader; -using llvm::BitstreamCursor; - -//===----------------------------------------------------------------------===// -// ChainedASTReaderListener implementation -//===----------------------------------------------------------------------===// - -bool -ChainedASTReaderListener::ReadFullVersionInformation(StringRef FullVersion) { - return First->ReadFullVersionInformation(FullVersion) || - Second->ReadFullVersionInformation(FullVersion); -} - -void ChainedASTReaderListener::ReadModuleName(StringRef ModuleName) { - First->ReadModuleName(ModuleName); - Second->ReadModuleName(ModuleName); -} - -void ChainedASTReaderListener::ReadModuleMapFile(StringRef ModuleMapPath) { - First->ReadModuleMapFile(ModuleMapPath); - Second->ReadModuleMapFile(ModuleMapPath); -} - -bool -ChainedASTReaderListener::ReadLanguageOptions(const LangOptions &LangOpts, - bool Complain, - bool AllowCompatibleDifferences) { - return First->ReadLanguageOptions(LangOpts, Complain, - AllowCompatibleDifferences) || - Second->ReadLanguageOptions(LangOpts, Complain, - AllowCompatibleDifferences); -} - -bool ChainedASTReaderListener::ReadTargetOptions( - const TargetOptions &TargetOpts, bool Complain, - bool AllowCompatibleDifferences) { - return First->ReadTargetOptions(TargetOpts, Complain, - AllowCompatibleDifferences) || - Second->ReadTargetOptions(TargetOpts, Complain, - AllowCompatibleDifferences); -} - -bool ChainedASTReaderListener::ReadDiagnosticOptions( - IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) { - return First->ReadDiagnosticOptions(DiagOpts, Complain) || - Second->ReadDiagnosticOptions(DiagOpts, Complain); -} - -bool -ChainedASTReaderListener::ReadFileSystemOptions(const FileSystemOptions &FSOpts, - bool Complain) { - return First->ReadFileSystemOptions(FSOpts, Complain) || - Second->ReadFileSystemOptions(FSOpts, Complain); -} - -bool ChainedASTReaderListener::ReadHeaderSearchOptions( - const HeaderSearchOptions &HSOpts, StringRef SpecificModuleCachePath, - bool Complain) { - return First->ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath, - Complain) || - Second->ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath, - Complain); -} - -bool ChainedASTReaderListener::ReadPreprocessorOptions( - const PreprocessorOptions &PPOpts, bool Complain, - std::string &SuggestedPredefines) { - return First->ReadPreprocessorOptions(PPOpts, Complain, - SuggestedPredefines) || - Second->ReadPreprocessorOptions(PPOpts, Complain, SuggestedPredefines); -} - -void ChainedASTReaderListener::ReadCounter(const serialization::ModuleFile &M, - unsigned Value) { - First->ReadCounter(M, Value); - Second->ReadCounter(M, Value); -} - -bool ChainedASTReaderListener::needsInputFileVisitation() { - return First->needsInputFileVisitation() || - Second->needsInputFileVisitation(); -} - -bool ChainedASTReaderListener::needsSystemInputFileVisitation() { - return First->needsSystemInputFileVisitation() || - Second->needsSystemInputFileVisitation(); -} - -void ChainedASTReaderListener::visitModuleFile(StringRef Filename, - ModuleKind Kind) { - First->visitModuleFile(Filename, Kind); - Second->visitModuleFile(Filename, Kind); -} - -bool ChainedASTReaderListener::visitInputFile(StringRef Filename, - bool isSystem, - bool isOverridden, - bool isExplicitModule) { - bool Continue = false; - if (First->needsInputFileVisitation() && - (!isSystem || First->needsSystemInputFileVisitation())) - Continue |= First->visitInputFile(Filename, isSystem, isOverridden, - isExplicitModule); - if (Second->needsInputFileVisitation() && - (!isSystem || Second->needsSystemInputFileVisitation())) - Continue |= Second->visitInputFile(Filename, isSystem, isOverridden, - isExplicitModule); - return Continue; -} - -void ChainedASTReaderListener::readModuleFileExtension( - const ModuleFileExtensionMetadata &Metadata) { - First->readModuleFileExtension(Metadata); - Second->readModuleFileExtension(Metadata); -} - -//===----------------------------------------------------------------------===// -// PCH validator implementation -//===----------------------------------------------------------------------===// - -ASTReaderListener::~ASTReaderListener() = default; - -/// Compare the given set of language options against an existing set of -/// language options. -/// -/// \param Diags If non-NULL, diagnostics will be emitted via this engine. -/// \param AllowCompatibleDifferences If true, differences between compatible -/// language options will be permitted. -/// -/// \returns true if the languagae options mis-match, false otherwise. -static bool checkLanguageOptions(const LangOptions &LangOpts, - const LangOptions &ExistingLangOpts, - DiagnosticsEngine *Diags, - bool AllowCompatibleDifferences = true) { -#define LANGOPT(Name, Bits, Default, Description) \ - if (ExistingLangOpts.Name != LangOpts.Name) { \ - if (Diags) \ - Diags->Report(diag::err_pch_langopt_mismatch) \ - << Description << LangOpts.Name << ExistingLangOpts.Name; \ - return true; \ - } - -#define VALUE_LANGOPT(Name, Bits, Default, Description) \ - if (ExistingLangOpts.Name != LangOpts.Name) { \ - if (Diags) \ - Diags->Report(diag::err_pch_langopt_value_mismatch) \ - << Description; \ - return true; \ - } - -#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ - if (ExistingLangOpts.get##Name() != LangOpts.get##Name()) { \ - if (Diags) \ - Diags->Report(diag::err_pch_langopt_value_mismatch) \ - << Description; \ - return true; \ - } - -#define COMPATIBLE_LANGOPT(Name, Bits, Default, Description) \ - if (!AllowCompatibleDifferences) \ - LANGOPT(Name, Bits, Default, Description) - -#define COMPATIBLE_ENUM_LANGOPT(Name, Bits, Default, Description) \ - if (!AllowCompatibleDifferences) \ - ENUM_LANGOPT(Name, Bits, Default, Description) - -#define COMPATIBLE_VALUE_LANGOPT(Name, Bits, Default, Description) \ - if (!AllowCompatibleDifferences) \ - VALUE_LANGOPT(Name, Bits, Default, Description) - -#define BENIGN_LANGOPT(Name, Bits, Default, Description) -#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) -#define BENIGN_VALUE_LANGOPT(Name, Type, Bits, Default, Description) -#include "clang/Basic/LangOptions.def" - - if (ExistingLangOpts.ModuleFeatures != LangOpts.ModuleFeatures) { - if (Diags) - Diags->Report(diag::err_pch_langopt_value_mismatch) << "module features"; - return true; - } - - if (ExistingLangOpts.ObjCRuntime != LangOpts.ObjCRuntime) { - if (Diags) - Diags->Report(diag::err_pch_langopt_value_mismatch) - << "target Objective-C runtime"; - return true; - } - - if (ExistingLangOpts.CommentOpts.BlockCommandNames != - LangOpts.CommentOpts.BlockCommandNames) { - if (Diags) - Diags->Report(diag::err_pch_langopt_value_mismatch) - << "block command names"; - return true; - } - - // Sanitizer feature mismatches are treated as compatible differences. If - // compatible differences aren't allowed, we still only want to check for - // mismatches of non-modular sanitizers (the only ones which can affect AST - // generation). - if (!AllowCompatibleDifferences) { - SanitizerMask ModularSanitizers = getPPTransparentSanitizers(); - SanitizerSet ExistingSanitizers = ExistingLangOpts.Sanitize; - SanitizerSet ImportedSanitizers = LangOpts.Sanitize; - ExistingSanitizers.clear(ModularSanitizers); - ImportedSanitizers.clear(ModularSanitizers); - if (ExistingSanitizers.Mask != ImportedSanitizers.Mask) { - const std::string Flag = "-fsanitize="; - if (Diags) { -#define SANITIZER(NAME, ID) \ - { \ - bool InExistingModule = ExistingSanitizers.has(SanitizerKind::ID); \ - bool InImportedModule = ImportedSanitizers.has(SanitizerKind::ID); \ - if (InExistingModule != InImportedModule) \ - Diags->Report(diag::err_pch_targetopt_feature_mismatch) \ - << InExistingModule << (Flag + NAME); \ - } -#include "clang/Basic/Sanitizers.def" - } - return true; - } - } - - return false; -} - -/// Compare the given set of target options against an existing set of -/// target options. -/// -/// \param Diags If non-NULL, diagnostics will be emitted via this engine. -/// -/// \returns true if the target options mis-match, false otherwise. -static bool checkTargetOptions(const TargetOptions &TargetOpts, - const TargetOptions &ExistingTargetOpts, - DiagnosticsEngine *Diags, - bool AllowCompatibleDifferences = true) { -#define CHECK_TARGET_OPT(Field, Name) \ - if (TargetOpts.Field != ExistingTargetOpts.Field) { \ - if (Diags) \ - Diags->Report(diag::err_pch_targetopt_mismatch) \ - << Name << TargetOpts.Field << ExistingTargetOpts.Field; \ - return true; \ - } - - // The triple and ABI must match exactly. - CHECK_TARGET_OPT(Triple, "target"); - CHECK_TARGET_OPT(ABI, "target ABI"); - - // We can tolerate different CPUs in many cases, notably when one CPU - // supports a strict superset of another. When allowing compatible - // differences skip this check. - if (!AllowCompatibleDifferences) - CHECK_TARGET_OPT(CPU, "target CPU"); - -#undef CHECK_TARGET_OPT - - // Compare feature sets. - SmallVector<StringRef, 4> ExistingFeatures( - ExistingTargetOpts.FeaturesAsWritten.begin(), - ExistingTargetOpts.FeaturesAsWritten.end()); - SmallVector<StringRef, 4> ReadFeatures(TargetOpts.FeaturesAsWritten.begin(), - TargetOpts.FeaturesAsWritten.end()); - llvm::sort(ExistingFeatures); - llvm::sort(ReadFeatures); - - // We compute the set difference in both directions explicitly so that we can - // diagnose the differences differently. - SmallVector<StringRef, 4> UnmatchedExistingFeatures, UnmatchedReadFeatures; - std::set_difference( - ExistingFeatures.begin(), ExistingFeatures.end(), ReadFeatures.begin(), - ReadFeatures.end(), std::back_inserter(UnmatchedExistingFeatures)); - std::set_difference(ReadFeatures.begin(), ReadFeatures.end(), - ExistingFeatures.begin(), ExistingFeatures.end(), - std::back_inserter(UnmatchedReadFeatures)); - - // If we are allowing compatible differences and the read feature set is - // a strict subset of the existing feature set, there is nothing to diagnose. - if (AllowCompatibleDifferences && UnmatchedReadFeatures.empty()) - return false; - - if (Diags) { - for (StringRef Feature : UnmatchedReadFeatures) - Diags->Report(diag::err_pch_targetopt_feature_mismatch) - << /* is-existing-feature */ false << Feature; - for (StringRef Feature : UnmatchedExistingFeatures) - Diags->Report(diag::err_pch_targetopt_feature_mismatch) - << /* is-existing-feature */ true << Feature; - } - - return !UnmatchedReadFeatures.empty() || !UnmatchedExistingFeatures.empty(); -} - -bool -PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts, - bool Complain, - bool AllowCompatibleDifferences) { - const LangOptions &ExistingLangOpts = PP.getLangOpts(); - return checkLanguageOptions(LangOpts, ExistingLangOpts, - Complain ? &Reader.Diags : nullptr, - AllowCompatibleDifferences); -} - -bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts, - bool Complain, - bool AllowCompatibleDifferences) { - const TargetOptions &ExistingTargetOpts = PP.getTargetInfo().getTargetOpts(); - return checkTargetOptions(TargetOpts, ExistingTargetOpts, - Complain ? &Reader.Diags : nullptr, - AllowCompatibleDifferences); -} - -namespace { - -using MacroDefinitionsMap = - llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/>>; -using DeclsMap = llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8>>; - -} // namespace - -static bool checkDiagnosticGroupMappings(DiagnosticsEngine &StoredDiags, - DiagnosticsEngine &Diags, - bool Complain) { - using Level = DiagnosticsEngine::Level; - - // Check current mappings for new -Werror mappings, and the stored mappings - // for cases that were explicitly mapped to *not* be errors that are now - // errors because of options like -Werror. - DiagnosticsEngine *MappingSources[] = { &Diags, &StoredDiags }; - - for (DiagnosticsEngine *MappingSource : MappingSources) { - for (auto DiagIDMappingPair : MappingSource->getDiagnosticMappings()) { - diag::kind DiagID = DiagIDMappingPair.first; - Level CurLevel = Diags.getDiagnosticLevel(DiagID, SourceLocation()); - if (CurLevel < DiagnosticsEngine::Error) - continue; // not significant - Level StoredLevel = - StoredDiags.getDiagnosticLevel(DiagID, SourceLocation()); - if (StoredLevel < DiagnosticsEngine::Error) { - if (Complain) - Diags.Report(diag::err_pch_diagopt_mismatch) << "-Werror=" + - Diags.getDiagnosticIDs()->getWarningOptionForDiag(DiagID).str(); - return true; - } - } - } - - return false; -} - -static bool isExtHandlingFromDiagsError(DiagnosticsEngine &Diags) { - diag::Severity Ext = Diags.getExtensionHandlingBehavior(); - if (Ext == diag::Severity::Warning && Diags.getWarningsAsErrors()) - return true; - return Ext >= diag::Severity::Error; -} - -static bool checkDiagnosticMappings(DiagnosticsEngine &StoredDiags, - DiagnosticsEngine &Diags, - bool IsSystem, bool Complain) { - // Top-level options - if (IsSystem) { - if (Diags.getSuppressSystemWarnings()) - return false; - // If -Wsystem-headers was not enabled before, be conservative - if (StoredDiags.getSuppressSystemWarnings()) { - if (Complain) - Diags.Report(diag::err_pch_diagopt_mismatch) << "-Wsystem-headers"; - return true; - } - } - - if (Diags.getWarningsAsErrors() && !StoredDiags.getWarningsAsErrors()) { - if (Complain) - Diags.Report(diag::err_pch_diagopt_mismatch) << "-Werror"; - return true; - } - - if (Diags.getWarningsAsErrors() && Diags.getEnableAllWarnings() && - !StoredDiags.getEnableAllWarnings()) { - if (Complain) - Diags.Report(diag::err_pch_diagopt_mismatch) << "-Weverything -Werror"; - return true; - } - - if (isExtHandlingFromDiagsError(Diags) && - !isExtHandlingFromDiagsError(StoredDiags)) { - if (Complain) - Diags.Report(diag::err_pch_diagopt_mismatch) << "-pedantic-errors"; - return true; - } - - return checkDiagnosticGroupMappings(StoredDiags, Diags, Complain); -} - -/// Return the top import module if it is implicit, nullptr otherwise. -static Module *getTopImportImplicitModule(ModuleManager &ModuleMgr, - Preprocessor &PP) { - // If the original import came from a file explicitly generated by the user, - // don't check the diagnostic mappings. - // FIXME: currently this is approximated by checking whether this is not a - // module import of an implicitly-loaded module file. - // Note: ModuleMgr.rbegin() may not be the current module, but it must be in - // the transitive closure of its imports, since unrelated modules cannot be - // imported until after this module finishes validation. - ModuleFile *TopImport = &*ModuleMgr.rbegin(); - while (!TopImport->ImportedBy.empty()) - TopImport = TopImport->ImportedBy[0]; - if (TopImport->Kind != MK_ImplicitModule) - return nullptr; - - StringRef ModuleName = TopImport->ModuleName; - assert(!ModuleName.empty() && "diagnostic options read before module name"); - - Module *M = PP.getHeaderSearchInfo().lookupModule(ModuleName); - assert(M && "missing module"); - return M; -} - -bool PCHValidator::ReadDiagnosticOptions( - IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) { - DiagnosticsEngine &ExistingDiags = PP.getDiagnostics(); - IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(ExistingDiags.getDiagnosticIDs()); - IntrusiveRefCntPtr<DiagnosticsEngine> Diags( - new DiagnosticsEngine(DiagIDs, DiagOpts.get())); - // This should never fail, because we would have processed these options - // before writing them to an ASTFile. - ProcessWarningOptions(*Diags, *DiagOpts, /*Report*/false); - - ModuleManager &ModuleMgr = Reader.getModuleManager(); - assert(ModuleMgr.size() >= 1 && "what ASTFile is this then"); - - Module *TopM = getTopImportImplicitModule(ModuleMgr, PP); - if (!TopM) - return false; - - // FIXME: if the diagnostics are incompatible, save a DiagnosticOptions that - // contains the union of their flags. - return checkDiagnosticMappings(*Diags, ExistingDiags, TopM->IsSystem, - Complain); -} - -/// Collect the macro definitions provided by the given preprocessor -/// options. -static void -collectMacroDefinitions(const PreprocessorOptions &PPOpts, - MacroDefinitionsMap &Macros, - SmallVectorImpl<StringRef> *MacroNames = nullptr) { - for (unsigned I = 0, N = PPOpts.Macros.size(); I != N; ++I) { - StringRef Macro = PPOpts.Macros[I].first; - bool IsUndef = PPOpts.Macros[I].second; - - std::pair<StringRef, StringRef> MacroPair = Macro.split('='); - StringRef MacroName = MacroPair.first; - StringRef MacroBody = MacroPair.second; - - // For an #undef'd macro, we only care about the name. - if (IsUndef) { - if (MacroNames && !Macros.count(MacroName)) - MacroNames->push_back(MacroName); - - Macros[MacroName] = std::make_pair("", true); - continue; - } - - // For a #define'd macro, figure out the actual definition. - if (MacroName.size() == Macro.size()) - MacroBody = "1"; - else { - // Note: GCC drops anything following an end-of-line character. - StringRef::size_type End = MacroBody.find_first_of("\n\r"); - MacroBody = MacroBody.substr(0, End); - } - - if (MacroNames && !Macros.count(MacroName)) - MacroNames->push_back(MacroName); - Macros[MacroName] = std::make_pair(MacroBody, false); - } -} - -/// Check the preprocessor options deserialized from the control block -/// against the preprocessor options in an existing preprocessor. -/// -/// \param Diags If non-null, produce diagnostics for any mismatches incurred. -/// \param Validate If true, validate preprocessor options. If false, allow -/// macros defined by \p ExistingPPOpts to override those defined by -/// \p PPOpts in SuggestedPredefines. -static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts, - const PreprocessorOptions &ExistingPPOpts, - DiagnosticsEngine *Diags, - FileManager &FileMgr, - std::string &SuggestedPredefines, - const LangOptions &LangOpts, - bool Validate = true) { - // Check macro definitions. - MacroDefinitionsMap ASTFileMacros; - collectMacroDefinitions(PPOpts, ASTFileMacros); - MacroDefinitionsMap ExistingMacros; - SmallVector<StringRef, 4> ExistingMacroNames; - collectMacroDefinitions(ExistingPPOpts, ExistingMacros, &ExistingMacroNames); - - for (unsigned I = 0, N = ExistingMacroNames.size(); I != N; ++I) { - // Dig out the macro definition in the existing preprocessor options. - StringRef MacroName = ExistingMacroNames[I]; - std::pair<StringRef, bool> Existing = ExistingMacros[MacroName]; - - // Check whether we know anything about this macro name or not. - llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/>>::iterator Known = - ASTFileMacros.find(MacroName); - if (!Validate || Known == ASTFileMacros.end()) { - // FIXME: Check whether this identifier was referenced anywhere in the - // AST file. If so, we should reject the AST file. Unfortunately, this - // information isn't in the control block. What shall we do about it? - - if (Existing.second) { - SuggestedPredefines += "#undef "; - SuggestedPredefines += MacroName.str(); - SuggestedPredefines += '\n'; - } else { - SuggestedPredefines += "#define "; - SuggestedPredefines += MacroName.str(); - SuggestedPredefines += ' '; - SuggestedPredefines += Existing.first.str(); - SuggestedPredefines += '\n'; - } - continue; - } - - // If the macro was defined in one but undef'd in the other, we have a - // conflict. - if (Existing.second != Known->second.second) { - if (Diags) { - Diags->Report(diag::err_pch_macro_def_undef) - << MacroName << Known->second.second; - } - return true; - } - - // If the macro was #undef'd in both, or if the macro bodies are identical, - // it's fine. - if (Existing.second || Existing.first == Known->second.first) - continue; - - // The macro bodies differ; complain. - if (Diags) { - Diags->Report(diag::err_pch_macro_def_conflict) - << MacroName << Known->second.first << Existing.first; - } - return true; - } - - // Check whether we're using predefines. - if (PPOpts.UsePredefines != ExistingPPOpts.UsePredefines && Validate) { - if (Diags) { - Diags->Report(diag::err_pch_undef) << ExistingPPOpts.UsePredefines; - } - return true; - } - - // Detailed record is important since it is used for the module cache hash. - if (LangOpts.Modules && - PPOpts.DetailedRecord != ExistingPPOpts.DetailedRecord && Validate) { - if (Diags) { - Diags->Report(diag::err_pch_pp_detailed_record) << PPOpts.DetailedRecord; - } - return true; - } - - // Compute the #include and #include_macros lines we need. - for (unsigned I = 0, N = ExistingPPOpts.Includes.size(); I != N; ++I) { - StringRef File = ExistingPPOpts.Includes[I]; - - if (!ExistingPPOpts.ImplicitPCHInclude.empty() && - !ExistingPPOpts.PCHThroughHeader.empty()) { - // In case the through header is an include, we must add all the includes - // to the predefines so the start point can be determined. - SuggestedPredefines += "#include \""; - SuggestedPredefines += File; - SuggestedPredefines += "\"\n"; - continue; - } - - if (File == ExistingPPOpts.ImplicitPCHInclude) - continue; - - if (std::find(PPOpts.Includes.begin(), PPOpts.Includes.end(), File) - != PPOpts.Includes.end()) - continue; - - SuggestedPredefines += "#include \""; - SuggestedPredefines += File; - SuggestedPredefines += "\"\n"; - } - - for (unsigned I = 0, N = ExistingPPOpts.MacroIncludes.size(); I != N; ++I) { - StringRef File = ExistingPPOpts.MacroIncludes[I]; - if (std::find(PPOpts.MacroIncludes.begin(), PPOpts.MacroIncludes.end(), - File) - != PPOpts.MacroIncludes.end()) - continue; - - SuggestedPredefines += "#__include_macros \""; - SuggestedPredefines += File; - SuggestedPredefines += "\"\n##\n"; - } - - return false; -} - -bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, - bool Complain, - std::string &SuggestedPredefines) { - const PreprocessorOptions &ExistingPPOpts = PP.getPreprocessorOpts(); - - return checkPreprocessorOptions(PPOpts, ExistingPPOpts, - Complain? &Reader.Diags : nullptr, - PP.getFileManager(), - SuggestedPredefines, - PP.getLangOpts()); -} - -bool SimpleASTReaderListener::ReadPreprocessorOptions( - const PreprocessorOptions &PPOpts, - bool Complain, - std::string &SuggestedPredefines) { - return checkPreprocessorOptions(PPOpts, - PP.getPreprocessorOpts(), - nullptr, - PP.getFileManager(), - SuggestedPredefines, - PP.getLangOpts(), - false); -} - -/// Check the header search options deserialized from the control block -/// against the header search options in an existing preprocessor. -/// -/// \param Diags If non-null, produce diagnostics for any mismatches incurred. -static bool checkHeaderSearchOptions(const HeaderSearchOptions &HSOpts, - StringRef SpecificModuleCachePath, - StringRef ExistingModuleCachePath, - DiagnosticsEngine *Diags, - const LangOptions &LangOpts) { - if (LangOpts.Modules) { - if (SpecificModuleCachePath != ExistingModuleCachePath) { - if (Diags) - Diags->Report(diag::err_pch_modulecache_mismatch) - << SpecificModuleCachePath << ExistingModuleCachePath; - return true; - } - } - - return false; -} - -bool PCHValidator::ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, - StringRef SpecificModuleCachePath, - bool Complain) { - return checkHeaderSearchOptions(HSOpts, SpecificModuleCachePath, - PP.getHeaderSearchInfo().getModuleCachePath(), - Complain ? &Reader.Diags : nullptr, - PP.getLangOpts()); -} - -void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) { - PP.setCounterValue(Value); -} - -//===----------------------------------------------------------------------===// -// AST reader implementation -//===----------------------------------------------------------------------===// - -void ASTReader::setDeserializationListener(ASTDeserializationListener *Listener, - bool TakeOwnership) { - DeserializationListener = Listener; - OwnsDeserializationListener = TakeOwnership; -} - -unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) { - return serialization::ComputeHash(Sel); -} - -std::pair<unsigned, unsigned> -ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) { - using namespace llvm::support; - - unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d); - unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d); - return std::make_pair(KeyLen, DataLen); -} - -ASTSelectorLookupTrait::internal_key_type -ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) { - using namespace llvm::support; - - SelectorTable &SelTable = Reader.getContext().Selectors; - unsigned N = endian::readNext<uint16_t, little, unaligned>(d); - IdentifierInfo *FirstII = Reader.getLocalIdentifier( - F, endian::readNext<uint32_t, little, unaligned>(d)); - if (N == 0) - return SelTable.getNullarySelector(FirstII); - else if (N == 1) - return SelTable.getUnarySelector(FirstII); - - SmallVector<IdentifierInfo *, 16> Args; - Args.push_back(FirstII); - for (unsigned I = 1; I != N; ++I) - Args.push_back(Reader.getLocalIdentifier( - F, endian::readNext<uint32_t, little, unaligned>(d))); - - return SelTable.getSelector(N, Args.data()); -} - -ASTSelectorLookupTrait::data_type -ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, - unsigned DataLen) { - using namespace llvm::support; - - data_type Result; - - Result.ID = Reader.getGlobalSelectorID( - F, endian::readNext<uint32_t, little, unaligned>(d)); - unsigned FullInstanceBits = endian::readNext<uint16_t, little, unaligned>(d); - unsigned FullFactoryBits = endian::readNext<uint16_t, little, unaligned>(d); - Result.InstanceBits = FullInstanceBits & 0x3; - Result.InstanceHasMoreThanOneDecl = (FullInstanceBits >> 2) & 0x1; - Result.FactoryBits = FullFactoryBits & 0x3; - Result.FactoryHasMoreThanOneDecl = (FullFactoryBits >> 2) & 0x1; - unsigned NumInstanceMethods = FullInstanceBits >> 3; - unsigned NumFactoryMethods = FullFactoryBits >> 3; - - // Load instance methods - for (unsigned I = 0; I != NumInstanceMethods; ++I) { - if (ObjCMethodDecl *Method = Reader.GetLocalDeclAs<ObjCMethodDecl>( - F, endian::readNext<uint32_t, little, unaligned>(d))) - Result.Instance.push_back(Method); - } - - // Load factory methods - for (unsigned I = 0; I != NumFactoryMethods; ++I) { - if (ObjCMethodDecl *Method = Reader.GetLocalDeclAs<ObjCMethodDecl>( - F, endian::readNext<uint32_t, little, unaligned>(d))) - Result.Factory.push_back(Method); - } - - return Result; -} - -unsigned ASTIdentifierLookupTraitBase::ComputeHash(const internal_key_type& a) { - return llvm::djbHash(a); -} - -std::pair<unsigned, unsigned> -ASTIdentifierLookupTraitBase::ReadKeyDataLength(const unsigned char*& d) { - using namespace llvm::support; - - unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d); - unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d); - return std::make_pair(KeyLen, DataLen); -} - -ASTIdentifierLookupTraitBase::internal_key_type -ASTIdentifierLookupTraitBase::ReadKey(const unsigned char* d, unsigned n) { - assert(n >= 2 && d[n-1] == '\0'); - return StringRef((const char*) d, n-1); -} - -/// Whether the given identifier is "interesting". -static bool isInterestingIdentifier(ASTReader &Reader, IdentifierInfo &II, - bool IsModule) { - return II.hadMacroDefinition() || - II.isPoisoned() || - (IsModule ? II.hasRevertedBuiltin() : II.getObjCOrBuiltinID()) || - II.hasRevertedTokenIDToIdentifier() || - (!(IsModule && Reader.getPreprocessor().getLangOpts().CPlusPlus) && - II.getFETokenInfo()); -} - -static bool readBit(unsigned &Bits) { - bool Value = Bits & 0x1; - Bits >>= 1; - return Value; -} - -IdentID ASTIdentifierLookupTrait::ReadIdentifierID(const unsigned char *d) { - using namespace llvm::support; - - unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d); - return Reader.getGlobalIdentifierID(F, RawID >> 1); -} - -static void markIdentifierFromAST(ASTReader &Reader, IdentifierInfo &II) { - if (!II.isFromAST()) { - II.setIsFromAST(); - bool IsModule = Reader.getPreprocessor().getCurrentModule() != nullptr; - if (isInterestingIdentifier(Reader, II, IsModule)) - II.setChangedSinceDeserialization(); - } -} - -IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, - const unsigned char* d, - unsigned DataLen) { - using namespace llvm::support; - - unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d); - bool IsInteresting = RawID & 0x01; - - // Wipe out the "is interesting" bit. - RawID = RawID >> 1; - - // Build the IdentifierInfo and link the identifier ID with it. - IdentifierInfo *II = KnownII; - if (!II) { - II = &Reader.getIdentifierTable().getOwn(k); - KnownII = II; - } - markIdentifierFromAST(Reader, *II); - Reader.markIdentifierUpToDate(II); - - IdentID ID = Reader.getGlobalIdentifierID(F, RawID); - if (!IsInteresting) { - // For uninteresting identifiers, there's nothing else to do. Just notify - // the reader that we've finished loading this identifier. - Reader.SetIdentifierInfo(ID, II); - return II; - } - - unsigned ObjCOrBuiltinID = endian::readNext<uint16_t, little, unaligned>(d); - unsigned Bits = endian::readNext<uint16_t, little, unaligned>(d); - bool CPlusPlusOperatorKeyword = readBit(Bits); - bool HasRevertedTokenIDToIdentifier = readBit(Bits); - bool HasRevertedBuiltin = readBit(Bits); - bool Poisoned = readBit(Bits); - bool ExtensionToken = readBit(Bits); - bool HadMacroDefinition = readBit(Bits); - - assert(Bits == 0 && "Extra bits in the identifier?"); - DataLen -= 8; - - // Set or check the various bits in the IdentifierInfo structure. - // Token IDs are read-only. - if (HasRevertedTokenIDToIdentifier && II->getTokenID() != tok::identifier) - II->revertTokenIDToIdentifier(); - if (!F.isModule()) - II->setObjCOrBuiltinID(ObjCOrBuiltinID); - else if (HasRevertedBuiltin && II->getBuiltinID()) { - II->revertBuiltin(); - assert((II->hasRevertedBuiltin() || - II->getObjCOrBuiltinID() == ObjCOrBuiltinID) && - "Incorrect ObjC keyword or builtin ID"); - } - assert(II->isExtensionToken() == ExtensionToken && - "Incorrect extension token flag"); - (void)ExtensionToken; - if (Poisoned) - II->setIsPoisoned(true); - assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword && - "Incorrect C++ operator keyword flag"); - (void)CPlusPlusOperatorKeyword; - - // If this identifier is a macro, deserialize the macro - // definition. - if (HadMacroDefinition) { - uint32_t MacroDirectivesOffset = - endian::readNext<uint32_t, little, unaligned>(d); - DataLen -= 4; - - Reader.addPendingMacro(II, &F, MacroDirectivesOffset); - } - - Reader.SetIdentifierInfo(ID, II); - - // Read all of the declarations visible at global scope with this - // name. - if (DataLen > 0) { - SmallVector<uint32_t, 4> DeclIDs; - for (; DataLen > 0; DataLen -= 4) - DeclIDs.push_back(Reader.getGlobalDeclID( - F, endian::readNext<uint32_t, little, unaligned>(d))); - Reader.SetGloballyVisibleDecls(II, DeclIDs); - } - - return II; -} - -DeclarationNameKey::DeclarationNameKey(DeclarationName Name) - : Kind(Name.getNameKind()) { - switch (Kind) { - case DeclarationName::Identifier: - Data = (uint64_t)Name.getAsIdentifierInfo(); - break; - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - Data = (uint64_t)Name.getObjCSelector().getAsOpaquePtr(); - break; - case DeclarationName::CXXOperatorName: - Data = Name.getCXXOverloadedOperator(); - break; - case DeclarationName::CXXLiteralOperatorName: - Data = (uint64_t)Name.getCXXLiteralIdentifier(); - break; - case DeclarationName::CXXDeductionGuideName: - Data = (uint64_t)Name.getCXXDeductionGuideTemplate() - ->getDeclName().getAsIdentifierInfo(); - break; - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - case DeclarationName::CXXUsingDirective: - Data = 0; - break; - } -} - -unsigned DeclarationNameKey::getHash() const { - llvm::FoldingSetNodeID ID; - ID.AddInteger(Kind); - - switch (Kind) { - case DeclarationName::Identifier: - case DeclarationName::CXXLiteralOperatorName: - case DeclarationName::CXXDeductionGuideName: - ID.AddString(((IdentifierInfo*)Data)->getName()); - break; - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - ID.AddInteger(serialization::ComputeHash(Selector(Data))); - break; - case DeclarationName::CXXOperatorName: - ID.AddInteger((OverloadedOperatorKind)Data); - break; - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - case DeclarationName::CXXUsingDirective: - break; - } - - return ID.ComputeHash(); -} - -ModuleFile * -ASTDeclContextNameLookupTrait::ReadFileRef(const unsigned char *&d) { - using namespace llvm::support; - - uint32_t ModuleFileID = endian::readNext<uint32_t, little, unaligned>(d); - return Reader.getLocalModuleFile(F, ModuleFileID); -} - -std::pair<unsigned, unsigned> -ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char *&d) { - using namespace llvm::support; - - unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d); - unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d); - return std::make_pair(KeyLen, DataLen); -} - -ASTDeclContextNameLookupTrait::internal_key_type -ASTDeclContextNameLookupTrait::ReadKey(const unsigned char *d, unsigned) { - using namespace llvm::support; - - auto Kind = (DeclarationName::NameKind)*d++; - uint64_t Data; - switch (Kind) { - case DeclarationName::Identifier: - case DeclarationName::CXXLiteralOperatorName: - case DeclarationName::CXXDeductionGuideName: - Data = (uint64_t)Reader.getLocalIdentifier( - F, endian::readNext<uint32_t, little, unaligned>(d)); - break; - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - Data = - (uint64_t)Reader.getLocalSelector( - F, endian::readNext<uint32_t, little, unaligned>( - d)).getAsOpaquePtr(); - break; - case DeclarationName::CXXOperatorName: - Data = *d++; // OverloadedOperatorKind - break; - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - case DeclarationName::CXXUsingDirective: - Data = 0; - break; - } - - return DeclarationNameKey(Kind, Data); -} - -void ASTDeclContextNameLookupTrait::ReadDataInto(internal_key_type, - const unsigned char *d, - unsigned DataLen, - data_type_builder &Val) { - using namespace llvm::support; - - for (unsigned NumDecls = DataLen / 4; NumDecls; --NumDecls) { - uint32_t LocalID = endian::readNext<uint32_t, little, unaligned>(d); - Val.insert(Reader.getGlobalDeclID(F, LocalID)); - } -} - -bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M, - BitstreamCursor &Cursor, - uint64_t Offset, - DeclContext *DC) { - assert(Offset != 0); - - SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(Offset); - - RecordData Record; - StringRef Blob; - unsigned Code = Cursor.ReadCode(); - unsigned RecCode = Cursor.readRecord(Code, Record, &Blob); - if (RecCode != DECL_CONTEXT_LEXICAL) { - Error("Expected lexical block"); - return true; - } - - assert(!isa<TranslationUnitDecl>(DC) && - "expected a TU_UPDATE_LEXICAL record for TU"); - // If we are handling a C++ class template instantiation, we can see multiple - // lexical updates for the same record. It's important that we select only one - // of them, so that field numbering works properly. Just pick the first one we - // see. - auto &Lex = LexicalDecls[DC]; - if (!Lex.first) { - Lex = std::make_pair( - &M, llvm::makeArrayRef( - reinterpret_cast<const llvm::support::unaligned_uint32_t *>( - Blob.data()), - Blob.size() / 4)); - } - DC->setHasExternalLexicalStorage(true); - return false; -} - -bool ASTReader::ReadVisibleDeclContextStorage(ModuleFile &M, - BitstreamCursor &Cursor, - uint64_t Offset, - DeclID ID) { - assert(Offset != 0); - - SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(Offset); - - RecordData Record; - StringRef Blob; - unsigned Code = Cursor.ReadCode(); - unsigned RecCode = Cursor.readRecord(Code, Record, &Blob); - if (RecCode != DECL_CONTEXT_VISIBLE) { - Error("Expected visible lookup table block"); - return true; - } - - // We can't safely determine the primary context yet, so delay attaching the - // lookup table until we're done with recursive deserialization. - auto *Data = (const unsigned char*)Blob.data(); - PendingVisibleUpdates[ID].push_back(PendingVisibleUpdate{&M, Data}); - return false; -} - -void ASTReader::Error(StringRef Msg) const { - Error(diag::err_fe_pch_malformed, Msg); - if (PP.getLangOpts().Modules && !Diags.isDiagnosticInFlight() && - !PP.getHeaderSearchInfo().getModuleCachePath().empty()) { - Diag(diag::note_module_cache_path) - << PP.getHeaderSearchInfo().getModuleCachePath(); - } -} - -void ASTReader::Error(unsigned DiagID, - StringRef Arg1, StringRef Arg2) const { - if (Diags.isDiagnosticInFlight()) - Diags.SetDelayedDiagnostic(DiagID, Arg1, Arg2); - else - Diag(DiagID) << Arg1 << Arg2; -} - -//===----------------------------------------------------------------------===// -// Source Manager Deserialization -//===----------------------------------------------------------------------===// - -/// Read the line table in the source manager block. -/// \returns true if there was an error. -bool ASTReader::ParseLineTable(ModuleFile &F, - const RecordData &Record) { - unsigned Idx = 0; - LineTableInfo &LineTable = SourceMgr.getLineTable(); - - // Parse the file names - std::map<int, int> FileIDs; - FileIDs[-1] = -1; // For unspecified filenames. - for (unsigned I = 0; Record[Idx]; ++I) { - // Extract the file name - auto Filename = ReadPath(F, Record, Idx); - FileIDs[I] = LineTable.getLineTableFilenameID(Filename); - } - ++Idx; - - // Parse the line entries - std::vector<LineEntry> Entries; - while (Idx < Record.size()) { - int FID = Record[Idx++]; - assert(FID >= 0 && "Serialized line entries for non-local file."); - // Remap FileID from 1-based old view. - FID += F.SLocEntryBaseID - 1; - - // Extract the line entries - unsigned NumEntries = Record[Idx++]; - assert(NumEntries && "no line entries for file ID"); - Entries.clear(); - Entries.reserve(NumEntries); - for (unsigned I = 0; I != NumEntries; ++I) { - unsigned FileOffset = Record[Idx++]; - unsigned LineNo = Record[Idx++]; - int FilenameID = FileIDs[Record[Idx++]]; - SrcMgr::CharacteristicKind FileKind - = (SrcMgr::CharacteristicKind)Record[Idx++]; - unsigned IncludeOffset = Record[Idx++]; - Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID, - FileKind, IncludeOffset)); - } - LineTable.AddEntry(FileID::get(FID), Entries); - } - - return false; -} - -/// Read a source manager block -bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) { - using namespace SrcMgr; - - BitstreamCursor &SLocEntryCursor = F.SLocEntryCursor; - - // Set the source-location entry cursor to the current position in - // the stream. This cursor will be used to read the contents of the - // source manager block initially, and then lazily read - // source-location entries as needed. - SLocEntryCursor = F.Stream; - - // The stream itself is going to skip over the source manager block. - if (F.Stream.SkipBlock()) { - Error("malformed block record in AST file"); - return true; - } - - // Enter the source manager block. - if (SLocEntryCursor.EnterSubBlock(SOURCE_MANAGER_BLOCK_ID)) { - Error("malformed source manager block record in AST file"); - return true; - } - - RecordData Record; - while (true) { - llvm::BitstreamEntry E = SLocEntryCursor.advanceSkippingSubblocks(); - - switch (E.Kind) { - case llvm::BitstreamEntry::SubBlock: // Handled for us already. - case llvm::BitstreamEntry::Error: - Error("malformed block record in AST file"); - return true; - case llvm::BitstreamEntry::EndBlock: - return false; - case llvm::BitstreamEntry::Record: - // The interesting case. - break; - } - - // Read a record. - Record.clear(); - StringRef Blob; - switch (SLocEntryCursor.readRecord(E.ID, Record, &Blob)) { - default: // Default behavior: ignore. - break; - - case SM_SLOC_FILE_ENTRY: - case SM_SLOC_BUFFER_ENTRY: - case SM_SLOC_EXPANSION_ENTRY: - // Once we hit one of the source location entries, we're done. - return false; - } - } -} - -/// If a header file is not found at the path that we expect it to be -/// and the PCH file was moved from its original location, try to resolve the -/// file by assuming that header+PCH were moved together and the header is in -/// the same place relative to the PCH. -static std::string -resolveFileRelativeToOriginalDir(const std::string &Filename, - const std::string &OriginalDir, - const std::string &CurrDir) { - assert(OriginalDir != CurrDir && - "No point trying to resolve the file if the PCH dir didn't change"); - - using namespace llvm::sys; - - SmallString<128> filePath(Filename); - fs::make_absolute(filePath); - assert(path::is_absolute(OriginalDir)); - SmallString<128> currPCHPath(CurrDir); - - path::const_iterator fileDirI = path::begin(path::parent_path(filePath)), - fileDirE = path::end(path::parent_path(filePath)); - path::const_iterator origDirI = path::begin(OriginalDir), - origDirE = path::end(OriginalDir); - // Skip the common path components from filePath and OriginalDir. - while (fileDirI != fileDirE && origDirI != origDirE && - *fileDirI == *origDirI) { - ++fileDirI; - ++origDirI; - } - for (; origDirI != origDirE; ++origDirI) - path::append(currPCHPath, ".."); - path::append(currPCHPath, fileDirI, fileDirE); - path::append(currPCHPath, path::filename(Filename)); - return currPCHPath.str(); -} - -bool ASTReader::ReadSLocEntry(int ID) { - if (ID == 0) - return false; - - if (unsigned(-ID) - 2 >= getTotalNumSLocs() || ID > 0) { - Error("source location entry ID out-of-range for AST file"); - return true; - } - - // Local helper to read the (possibly-compressed) buffer data following the - // entry record. - auto ReadBuffer = [this]( - BitstreamCursor &SLocEntryCursor, - StringRef Name) -> std::unique_ptr<llvm::MemoryBuffer> { - RecordData Record; - StringRef Blob; - unsigned Code = SLocEntryCursor.ReadCode(); - unsigned RecCode = SLocEntryCursor.readRecord(Code, Record, &Blob); - - if (RecCode == SM_SLOC_BUFFER_BLOB_COMPRESSED) { - if (!llvm::zlib::isAvailable()) { - Error("zlib is not available"); - return nullptr; - } - SmallString<0> Uncompressed; - if (llvm::Error E = - llvm::zlib::uncompress(Blob, Uncompressed, Record[0])) { - Error("could not decompress embedded file contents: " + - llvm::toString(std::move(E))); - return nullptr; - } - return llvm::MemoryBuffer::getMemBufferCopy(Uncompressed, Name); - } else if (RecCode == SM_SLOC_BUFFER_BLOB) { - return llvm::MemoryBuffer::getMemBuffer(Blob.drop_back(1), Name, true); - } else { - Error("AST record has invalid code"); - return nullptr; - } - }; - - ModuleFile *F = GlobalSLocEntryMap.find(-ID)->second; - F->SLocEntryCursor.JumpToBit(F->SLocEntryOffsets[ID - F->SLocEntryBaseID]); - BitstreamCursor &SLocEntryCursor = F->SLocEntryCursor; - unsigned BaseOffset = F->SLocEntryBaseOffset; - - ++NumSLocEntriesRead; - llvm::BitstreamEntry Entry = SLocEntryCursor.advance(); - if (Entry.Kind != llvm::BitstreamEntry::Record) { - Error("incorrectly-formatted source location entry in AST file"); - return true; - } - - RecordData Record; - StringRef Blob; - switch (SLocEntryCursor.readRecord(Entry.ID, Record, &Blob)) { - default: - Error("incorrectly-formatted source location entry in AST file"); - return true; - - case SM_SLOC_FILE_ENTRY: { - // We will detect whether a file changed and return 'Failure' for it, but - // we will also try to fail gracefully by setting up the SLocEntry. - unsigned InputID = Record[4]; - InputFile IF = getInputFile(*F, InputID); - const FileEntry *File = IF.getFile(); - bool OverriddenBuffer = IF.isOverridden(); - - // Note that we only check if a File was returned. If it was out-of-date - // we have complained but we will continue creating a FileID to recover - // gracefully. - if (!File) - return true; - - SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]); - if (IncludeLoc.isInvalid() && F->Kind != MK_MainFile) { - // This is the module's main file. - IncludeLoc = getImportLocation(F); - } - SrcMgr::CharacteristicKind - FileCharacter = (SrcMgr::CharacteristicKind)Record[2]; - FileID FID = SourceMgr.createFileID(File, IncludeLoc, FileCharacter, - ID, BaseOffset + Record[0]); - SrcMgr::FileInfo &FileInfo = - const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile()); - FileInfo.NumCreatedFIDs = Record[5]; - if (Record[3]) - FileInfo.setHasLineDirectives(); - - const DeclID *FirstDecl = F->FileSortedDecls + Record[6]; - unsigned NumFileDecls = Record[7]; - if (NumFileDecls && ContextObj) { - assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?"); - FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl, - NumFileDecls)); - } - - const SrcMgr::ContentCache *ContentCache - = SourceMgr.getOrCreateContentCache(File, isSystem(FileCharacter)); - if (OverriddenBuffer && !ContentCache->BufferOverridden && - ContentCache->ContentsEntry == ContentCache->OrigEntry && - !ContentCache->getRawBuffer()) { - auto Buffer = ReadBuffer(SLocEntryCursor, File->getName()); - if (!Buffer) - return true; - SourceMgr.overrideFileContents(File, std::move(Buffer)); - } - - break; - } - - case SM_SLOC_BUFFER_ENTRY: { - const char *Name = Blob.data(); - unsigned Offset = Record[0]; - SrcMgr::CharacteristicKind - FileCharacter = (SrcMgr::CharacteristicKind)Record[2]; - SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]); - if (IncludeLoc.isInvalid() && F->isModule()) { - IncludeLoc = getImportLocation(F); - } - - auto Buffer = ReadBuffer(SLocEntryCursor, Name); - if (!Buffer) - return true; - SourceMgr.createFileID(std::move(Buffer), FileCharacter, ID, - BaseOffset + Offset, IncludeLoc); - break; - } - - case SM_SLOC_EXPANSION_ENTRY: { - SourceLocation SpellingLoc = ReadSourceLocation(*F, Record[1]); - SourceMgr.createExpansionLoc(SpellingLoc, - ReadSourceLocation(*F, Record[2]), - ReadSourceLocation(*F, Record[3]), - Record[5], - Record[4], - ID, - BaseOffset + Record[0]); - break; - } - } - - return false; -} - -std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) { - if (ID == 0) - return std::make_pair(SourceLocation(), ""); - - if (unsigned(-ID) - 2 >= getTotalNumSLocs() || ID > 0) { - Error("source location entry ID out-of-range for AST file"); - return std::make_pair(SourceLocation(), ""); - } - - // Find which module file this entry lands in. - ModuleFile *M = GlobalSLocEntryMap.find(-ID)->second; - if (!M->isModule()) - return std::make_pair(SourceLocation(), ""); - - // FIXME: Can we map this down to a particular submodule? That would be - // ideal. - return std::make_pair(M->ImportLoc, StringRef(M->ModuleName)); -} - -/// Find the location where the module F is imported. -SourceLocation ASTReader::getImportLocation(ModuleFile *F) { - if (F->ImportLoc.isValid()) - return F->ImportLoc; - - // Otherwise we have a PCH. It's considered to be "imported" at the first - // location of its includer. - if (F->ImportedBy.empty() || !F->ImportedBy[0]) { - // Main file is the importer. - assert(SourceMgr.getMainFileID().isValid() && "missing main file"); - return SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); - } - return F->ImportedBy[0]->FirstLoc; -} - -/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the -/// specified cursor. Read the abbreviations that are at the top of the block -/// and then leave the cursor pointing into the block. -bool ASTReader::ReadBlockAbbrevs(BitstreamCursor &Cursor, unsigned BlockID) { - if (Cursor.EnterSubBlock(BlockID)) - return true; - - while (true) { - uint64_t Offset = Cursor.GetCurrentBitNo(); - unsigned Code = Cursor.ReadCode(); - - // We expect all abbrevs to be at the start of the block. - if (Code != llvm::bitc::DEFINE_ABBREV) { - Cursor.JumpToBit(Offset); - return false; - } - Cursor.ReadAbbrevRecord(); - } -} - -Token ASTReader::ReadToken(ModuleFile &F, const RecordDataImpl &Record, - unsigned &Idx) { - Token Tok; - Tok.startToken(); - Tok.setLocation(ReadSourceLocation(F, Record, Idx)); - Tok.setLength(Record[Idx++]); - if (IdentifierInfo *II = getLocalIdentifier(F, Record[Idx++])) - Tok.setIdentifierInfo(II); - Tok.setKind((tok::TokenKind)Record[Idx++]); - Tok.setFlag((Token::TokenFlags)Record[Idx++]); - return Tok; -} - -MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) { - BitstreamCursor &Stream = F.MacroCursor; - - // Keep track of where we are in the stream, then jump back there - // after reading this macro. - SavedStreamPosition SavedPosition(Stream); - - Stream.JumpToBit(Offset); - RecordData Record; - SmallVector<IdentifierInfo*, 16> MacroParams; - MacroInfo *Macro = nullptr; - - while (true) { - // Advance to the next record, but if we get to the end of the block, don't - // pop it (removing all the abbreviations from the cursor) since we want to - // be able to reseek within the block and read entries. - unsigned Flags = BitstreamCursor::AF_DontPopBlockAtEnd; - llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(Flags); - - switch (Entry.Kind) { - case llvm::BitstreamEntry::SubBlock: // Handled for us already. - case llvm::BitstreamEntry::Error: - Error("malformed block record in AST file"); - return Macro; - case llvm::BitstreamEntry::EndBlock: - return Macro; - case llvm::BitstreamEntry::Record: - // The interesting case. - break; - } - - // Read a record. - Record.clear(); - PreprocessorRecordTypes RecType = - (PreprocessorRecordTypes)Stream.readRecord(Entry.ID, Record); - switch (RecType) { - case PP_MODULE_MACRO: - case PP_MACRO_DIRECTIVE_HISTORY: - return Macro; - - case PP_MACRO_OBJECT_LIKE: - case PP_MACRO_FUNCTION_LIKE: { - // If we already have a macro, that means that we've hit the end - // of the definition of the macro we were looking for. We're - // done. - if (Macro) - return Macro; - - unsigned NextIndex = 1; // Skip identifier ID. - SourceLocation Loc = ReadSourceLocation(F, Record, NextIndex); - MacroInfo *MI = PP.AllocateMacroInfo(Loc); - MI->setDefinitionEndLoc(ReadSourceLocation(F, Record, NextIndex)); - MI->setIsUsed(Record[NextIndex++]); - MI->setUsedForHeaderGuard(Record[NextIndex++]); - - if (RecType == PP_MACRO_FUNCTION_LIKE) { - // Decode function-like macro info. - bool isC99VarArgs = Record[NextIndex++]; - bool isGNUVarArgs = Record[NextIndex++]; - bool hasCommaPasting = Record[NextIndex++]; - MacroParams.clear(); - unsigned NumArgs = Record[NextIndex++]; - for (unsigned i = 0; i != NumArgs; ++i) - MacroParams.push_back(getLocalIdentifier(F, Record[NextIndex++])); - - // Install function-like macro info. - MI->setIsFunctionLike(); - if (isC99VarArgs) MI->setIsC99Varargs(); - if (isGNUVarArgs) MI->setIsGNUVarargs(); - if (hasCommaPasting) MI->setHasCommaPasting(); - MI->setParameterList(MacroParams, PP.getPreprocessorAllocator()); - } - - // Remember that we saw this macro last so that we add the tokens that - // form its body to it. - Macro = MI; - - if (NextIndex + 1 == Record.size() && PP.getPreprocessingRecord() && - Record[NextIndex]) { - // We have a macro definition. Register the association - PreprocessedEntityID - GlobalID = getGlobalPreprocessedEntityID(F, Record[NextIndex]); - PreprocessingRecord &PPRec = *PP.getPreprocessingRecord(); - PreprocessingRecord::PPEntityID PPID = - PPRec.getPPEntityID(GlobalID - 1, /*isLoaded=*/true); - MacroDefinitionRecord *PPDef = cast_or_null<MacroDefinitionRecord>( - PPRec.getPreprocessedEntity(PPID)); - if (PPDef) - PPRec.RegisterMacroDefinition(Macro, PPDef); - } - - ++NumMacrosRead; - break; - } - - case PP_TOKEN: { - // If we see a TOKEN before a PP_MACRO_*, then the file is - // erroneous, just pretend we didn't see this. - if (!Macro) break; - - unsigned Idx = 0; - Token Tok = ReadToken(F, Record, Idx); - Macro->AddTokenToBody(Tok); - break; - } - } - } -} - -PreprocessedEntityID -ASTReader::getGlobalPreprocessedEntityID(ModuleFile &M, - unsigned LocalID) const { - if (!M.ModuleOffsetMap.empty()) - ReadModuleOffsetMap(M); - - ContinuousRangeMap<uint32_t, int, 2>::const_iterator - I = M.PreprocessedEntityRemap.find(LocalID - NUM_PREDEF_PP_ENTITY_IDS); - assert(I != M.PreprocessedEntityRemap.end() - && "Invalid index into preprocessed entity index remap"); - - return LocalID + I->second; -} - -unsigned HeaderFileInfoTrait::ComputeHash(internal_key_ref ikey) { - return llvm::hash_combine(ikey.Size, ikey.ModTime); -} - -HeaderFileInfoTrait::internal_key_type -HeaderFileInfoTrait::GetInternalKey(const FileEntry *FE) { - internal_key_type ikey = {FE->getSize(), - M.HasTimestamps ? FE->getModificationTime() : 0, - FE->getName(), /*Imported*/ false}; - return ikey; -} - -bool HeaderFileInfoTrait::EqualKey(internal_key_ref a, internal_key_ref b) { - if (a.Size != b.Size || (a.ModTime && b.ModTime && a.ModTime != b.ModTime)) - return false; - - if (llvm::sys::path::is_absolute(a.Filename) && a.Filename == b.Filename) - return true; - - // Determine whether the actual files are equivalent. - FileManager &FileMgr = Reader.getFileManager(); - auto GetFile = [&](const internal_key_type &Key) -> const FileEntry* { - if (!Key.Imported) - return FileMgr.getFile(Key.Filename); - - std::string Resolved = Key.Filename; - Reader.ResolveImportedPath(M, Resolved); - return FileMgr.getFile(Resolved); - }; - - const FileEntry *FEA = GetFile(a); - const FileEntry *FEB = GetFile(b); - return FEA && FEA == FEB; -} - -std::pair<unsigned, unsigned> -HeaderFileInfoTrait::ReadKeyDataLength(const unsigned char*& d) { - using namespace llvm::support; - - unsigned KeyLen = (unsigned) endian::readNext<uint16_t, little, unaligned>(d); - unsigned DataLen = (unsigned) *d++; - return std::make_pair(KeyLen, DataLen); -} - -HeaderFileInfoTrait::internal_key_type -HeaderFileInfoTrait::ReadKey(const unsigned char *d, unsigned) { - using namespace llvm::support; - - internal_key_type ikey; - ikey.Size = off_t(endian::readNext<uint64_t, little, unaligned>(d)); - ikey.ModTime = time_t(endian::readNext<uint64_t, little, unaligned>(d)); - ikey.Filename = (const char *)d; - ikey.Imported = true; - return ikey; -} - -HeaderFileInfoTrait::data_type -HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, - unsigned DataLen) { - using namespace llvm::support; - - const unsigned char *End = d + DataLen; - HeaderFileInfo HFI; - unsigned Flags = *d++; - // FIXME: Refactor with mergeHeaderFileInfo in HeaderSearch.cpp. - HFI.isImport |= (Flags >> 5) & 0x01; - HFI.isPragmaOnce |= (Flags >> 4) & 0x01; - HFI.DirInfo = (Flags >> 1) & 0x07; - HFI.IndexHeaderMapHeader = Flags & 0x01; - // FIXME: Find a better way to handle this. Maybe just store a - // "has been included" flag? - HFI.NumIncludes = std::max(endian::readNext<uint16_t, little, unaligned>(d), - HFI.NumIncludes); - HFI.ControllingMacroID = Reader.getGlobalIdentifierID( - M, endian::readNext<uint32_t, little, unaligned>(d)); - if (unsigned FrameworkOffset = - endian::readNext<uint32_t, little, unaligned>(d)) { - // The framework offset is 1 greater than the actual offset, - // since 0 is used as an indicator for "no framework name". - StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1); - HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); - } - - assert((End - d) % 4 == 0 && - "Wrong data length in HeaderFileInfo deserialization"); - while (d != End) { - uint32_t LocalSMID = endian::readNext<uint32_t, little, unaligned>(d); - auto HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>(LocalSMID & 3); - LocalSMID >>= 2; - - // This header is part of a module. Associate it with the module to enable - // implicit module import. - SubmoduleID GlobalSMID = Reader.getGlobalSubmoduleID(M, LocalSMID); - Module *Mod = Reader.getSubmodule(GlobalSMID); - FileManager &FileMgr = Reader.getFileManager(); - ModuleMap &ModMap = - Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap(); - - std::string Filename = key.Filename; - if (key.Imported) - Reader.ResolveImportedPath(M, Filename); - // FIXME: This is not always the right filename-as-written, but we're not - // going to use this information to rebuild the module, so it doesn't make - // a lot of difference. - Module::Header H = { key.Filename, FileMgr.getFile(Filename) }; - ModMap.addHeader(Mod, H, HeaderRole, /*Imported*/true); - HFI.isModuleHeader |= !(HeaderRole & ModuleMap::TextualHeader); - } - - // This HeaderFileInfo was externally loaded. - HFI.External = true; - HFI.IsValid = true; - return HFI; -} - -void ASTReader::addPendingMacro(IdentifierInfo *II, - ModuleFile *M, - uint64_t MacroDirectivesOffset) { - assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard"); - PendingMacroIDs[II].push_back(PendingMacroInfo(M, MacroDirectivesOffset)); -} - -void ASTReader::ReadDefinedMacros() { - // Note that we are loading defined macros. - Deserializing Macros(this); - - for (ModuleFile &I : llvm::reverse(ModuleMgr)) { - BitstreamCursor &MacroCursor = I.MacroCursor; - - // If there was no preprocessor block, skip this file. - if (MacroCursor.getBitcodeBytes().empty()) - continue; - - BitstreamCursor Cursor = MacroCursor; - Cursor.JumpToBit(I.MacroStartOffset); - - RecordData Record; - while (true) { - llvm::BitstreamEntry E = Cursor.advanceSkippingSubblocks(); - - switch (E.Kind) { - case llvm::BitstreamEntry::SubBlock: // Handled for us already. - case llvm::BitstreamEntry::Error: - Error("malformed block record in AST file"); - return; - case llvm::BitstreamEntry::EndBlock: - goto NextCursor; - - case llvm::BitstreamEntry::Record: - Record.clear(); - switch (Cursor.readRecord(E.ID, Record)) { - default: // Default behavior: ignore. - break; - - case PP_MACRO_OBJECT_LIKE: - case PP_MACRO_FUNCTION_LIKE: { - IdentifierInfo *II = getLocalIdentifier(I, Record[0]); - if (II->isOutOfDate()) - updateOutOfDateIdentifier(*II); - break; - } - - case PP_TOKEN: - // Ignore tokens. - break; - } - break; - } - } - NextCursor: ; - } -} - -namespace { - - /// Visitor class used to look up identifirs in an AST file. - class IdentifierLookupVisitor { - StringRef Name; - unsigned NameHash; - unsigned PriorGeneration; - unsigned &NumIdentifierLookups; - unsigned &NumIdentifierLookupHits; - IdentifierInfo *Found = nullptr; - - public: - IdentifierLookupVisitor(StringRef Name, unsigned PriorGeneration, - unsigned &NumIdentifierLookups, - unsigned &NumIdentifierLookupHits) - : Name(Name), NameHash(ASTIdentifierLookupTrait::ComputeHash(Name)), - PriorGeneration(PriorGeneration), - NumIdentifierLookups(NumIdentifierLookups), - NumIdentifierLookupHits(NumIdentifierLookupHits) {} - - bool operator()(ModuleFile &M) { - // If we've already searched this module file, skip it now. - if (M.Generation <= PriorGeneration) - return true; - - ASTIdentifierLookupTable *IdTable - = (ASTIdentifierLookupTable *)M.IdentifierLookupTable; - if (!IdTable) - return false; - - ASTIdentifierLookupTrait Trait(IdTable->getInfoObj().getReader(), M, - Found); - ++NumIdentifierLookups; - ASTIdentifierLookupTable::iterator Pos = - IdTable->find_hashed(Name, NameHash, &Trait); - if (Pos == IdTable->end()) - return false; - - // Dereferencing the iterator has the effect of building the - // IdentifierInfo node and populating it with the various - // declarations it needs. - ++NumIdentifierLookupHits; - Found = *Pos; - return true; - } - - // Retrieve the identifier info found within the module - // files. - IdentifierInfo *getIdentifierInfo() const { return Found; } - }; - -} // namespace - -void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) { - // Note that we are loading an identifier. - Deserializing AnIdentifier(this); - - unsigned PriorGeneration = 0; - if (getContext().getLangOpts().Modules) - PriorGeneration = IdentifierGeneration[&II]; - - // If there is a global index, look there first to determine which modules - // provably do not have any results for this identifier. - GlobalModuleIndex::HitSet Hits; - GlobalModuleIndex::HitSet *HitsPtr = nullptr; - if (!loadGlobalIndex()) { - if (GlobalIndex->lookupIdentifier(II.getName(), Hits)) { - HitsPtr = &Hits; - } - } - - IdentifierLookupVisitor Visitor(II.getName(), PriorGeneration, - NumIdentifierLookups, - NumIdentifierLookupHits); - ModuleMgr.visit(Visitor, HitsPtr); - markIdentifierUpToDate(&II); -} - -void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) { - if (!II) - return; - - II->setOutOfDate(false); - - // Update the generation for this identifier. - if (getContext().getLangOpts().Modules) - IdentifierGeneration[II] = getGeneration(); -} - -void ASTReader::resolvePendingMacro(IdentifierInfo *II, - const PendingMacroInfo &PMInfo) { - ModuleFile &M = *PMInfo.M; - - BitstreamCursor &Cursor = M.MacroCursor; - SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(PMInfo.MacroDirectivesOffset); - - struct ModuleMacroRecord { - SubmoduleID SubModID; - MacroInfo *MI; - SmallVector<SubmoduleID, 8> Overrides; - }; - llvm::SmallVector<ModuleMacroRecord, 8> ModuleMacros; - - // We expect to see a sequence of PP_MODULE_MACRO records listing exported - // macros, followed by a PP_MACRO_DIRECTIVE_HISTORY record with the complete - // macro histroy. - RecordData Record; - while (true) { - llvm::BitstreamEntry Entry = - Cursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd); - if (Entry.Kind != llvm::BitstreamEntry::Record) { - Error("malformed block record in AST file"); - return; - } - - Record.clear(); - switch ((PreprocessorRecordTypes)Cursor.readRecord(Entry.ID, Record)) { - case PP_MACRO_DIRECTIVE_HISTORY: - break; - - case PP_MODULE_MACRO: { - ModuleMacros.push_back(ModuleMacroRecord()); - auto &Info = ModuleMacros.back(); - Info.SubModID = getGlobalSubmoduleID(M, Record[0]); - Info.MI = getMacro(getGlobalMacroID(M, Record[1])); - for (int I = 2, N = Record.size(); I != N; ++I) - Info.Overrides.push_back(getGlobalSubmoduleID(M, Record[I])); - continue; - } - - default: - Error("malformed block record in AST file"); - return; - } - - // We found the macro directive history; that's the last record - // for this macro. - break; - } - - // Module macros are listed in reverse dependency order. - { - std::reverse(ModuleMacros.begin(), ModuleMacros.end()); - llvm::SmallVector<ModuleMacro*, 8> Overrides; - for (auto &MMR : ModuleMacros) { - Overrides.clear(); - for (unsigned ModID : MMR.Overrides) { - Module *Mod = getSubmodule(ModID); - auto *Macro = PP.getModuleMacro(Mod, II); - assert(Macro && "missing definition for overridden macro"); - Overrides.push_back(Macro); - } - - bool Inserted = false; - Module *Owner = getSubmodule(MMR.SubModID); - PP.addModuleMacro(Owner, II, MMR.MI, Overrides, Inserted); - } - } - - // Don't read the directive history for a module; we don't have anywhere - // to put it. - if (M.isModule()) - return; - - // Deserialize the macro directives history in reverse source-order. - MacroDirective *Latest = nullptr, *Earliest = nullptr; - unsigned Idx = 0, N = Record.size(); - while (Idx < N) { - MacroDirective *MD = nullptr; - SourceLocation Loc = ReadSourceLocation(M, Record, Idx); - MacroDirective::Kind K = (MacroDirective::Kind)Record[Idx++]; - switch (K) { - case MacroDirective::MD_Define: { - MacroInfo *MI = getMacro(getGlobalMacroID(M, Record[Idx++])); - MD = PP.AllocateDefMacroDirective(MI, Loc); - break; - } - case MacroDirective::MD_Undefine: - MD = PP.AllocateUndefMacroDirective(Loc); - break; - case MacroDirective::MD_Visibility: - bool isPublic = Record[Idx++]; - MD = PP.AllocateVisibilityMacroDirective(Loc, isPublic); - break; - } - - if (!Latest) - Latest = MD; - if (Earliest) - Earliest->setPrevious(MD); - Earliest = MD; - } - - if (Latest) - PP.setLoadedMacroDirective(II, Earliest, Latest); -} - -ASTReader::InputFileInfo -ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) { - // Go find this input file. - BitstreamCursor &Cursor = F.InputFilesCursor; - SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(F.InputFileOffsets[ID-1]); - - unsigned Code = Cursor.ReadCode(); - RecordData Record; - StringRef Blob; - - unsigned Result = Cursor.readRecord(Code, Record, &Blob); - assert(static_cast<InputFileRecordTypes>(Result) == INPUT_FILE && - "invalid record type for input file"); - (void)Result; - - assert(Record[0] == ID && "Bogus stored ID or offset"); - InputFileInfo R; - R.StoredSize = static_cast<off_t>(Record[1]); - R.StoredTime = static_cast<time_t>(Record[2]); - R.Overridden = static_cast<bool>(Record[3]); - R.Transient = static_cast<bool>(Record[4]); - R.TopLevelModuleMap = static_cast<bool>(Record[5]); - R.Filename = Blob; - ResolveImportedPath(F, R.Filename); - return R; -} - -static unsigned moduleKindForDiagnostic(ModuleKind Kind); -InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { - // If this ID is bogus, just return an empty input file. - if (ID == 0 || ID > F.InputFilesLoaded.size()) - return InputFile(); - - // If we've already loaded this input file, return it. - if (F.InputFilesLoaded[ID-1].getFile()) - return F.InputFilesLoaded[ID-1]; - - if (F.InputFilesLoaded[ID-1].isNotFound()) - return InputFile(); - - // Go find this input file. - BitstreamCursor &Cursor = F.InputFilesCursor; - SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(F.InputFileOffsets[ID-1]); - - InputFileInfo FI = readInputFileInfo(F, ID); - off_t StoredSize = FI.StoredSize; - time_t StoredTime = FI.StoredTime; - bool Overridden = FI.Overridden; - bool Transient = FI.Transient; - StringRef Filename = FI.Filename; - - const FileEntry *File = FileMgr.getFile(Filename, /*OpenFile=*/false); - // If we didn't find the file, resolve it relative to the - // original directory from which this AST file was created. - if (File == nullptr && !F.OriginalDir.empty() && !F.BaseDirectory.empty() && - F.OriginalDir != F.BaseDirectory) { - std::string Resolved = resolveFileRelativeToOriginalDir( - Filename, F.OriginalDir, F.BaseDirectory); - if (!Resolved.empty()) - File = FileMgr.getFile(Resolved); - } - - // For an overridden file, create a virtual file with the stored - // size/timestamp. - if ((Overridden || Transient) && File == nullptr) - File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime); - - if (File == nullptr) { - if (Complain) { - std::string ErrorStr = "could not find file '"; - ErrorStr += Filename; - ErrorStr += "' referenced by AST file '"; - ErrorStr += F.FileName; - ErrorStr += "'"; - Error(ErrorStr); - } - // Record that we didn't find the file. - F.InputFilesLoaded[ID-1] = InputFile::getNotFound(); - return InputFile(); - } - - // Check if there was a request to override the contents of the file - // that was part of the precompiled header. Overriding such a file - // can lead to problems when lexing using the source locations from the - // PCH. - SourceManager &SM = getSourceManager(); - // FIXME: Reject if the overrides are different. - if ((!Overridden && !Transient) && SM.isFileOverridden(File)) { - if (Complain) - Error(diag::err_fe_pch_file_overridden, Filename); - // After emitting the diagnostic, recover by disabling the override so - // that the original file will be used. - // - // FIXME: This recovery is just as broken as the original state; there may - // be another precompiled module that's using the overridden contents, or - // we might be half way through parsing it. Instead, we should treat the - // overridden contents as belonging to a separate FileEntry. - SM.disableFileContentsOverride(File); - // The FileEntry is a virtual file entry with the size of the contents - // that would override the original contents. Set it to the original's - // size/time. - FileMgr.modifyFileEntry(const_cast<FileEntry*>(File), - StoredSize, StoredTime); - } - - bool IsOutOfDate = false; - - // For an overridden file, there is nothing to validate. - if (!Overridden && // - (StoredSize != File->getSize() || - (StoredTime && StoredTime != File->getModificationTime() && - !DisableValidation) - )) { - if (Complain) { - // Build a list of the PCH imports that got us here (in reverse). - SmallVector<ModuleFile *, 4> ImportStack(1, &F); - while (!ImportStack.back()->ImportedBy.empty()) - ImportStack.push_back(ImportStack.back()->ImportedBy[0]); - - // The top-level PCH is stale. - StringRef TopLevelPCHName(ImportStack.back()->FileName); - unsigned DiagnosticKind = moduleKindForDiagnostic(ImportStack.back()->Kind); - if (DiagnosticKind == 0) - Error(diag::err_fe_pch_file_modified, Filename, TopLevelPCHName); - else if (DiagnosticKind == 1) - Error(diag::err_fe_module_file_modified, Filename, TopLevelPCHName); - else - Error(diag::err_fe_ast_file_modified, Filename, TopLevelPCHName); - - // Print the import stack. - if (ImportStack.size() > 1 && !Diags.isDiagnosticInFlight()) { - Diag(diag::note_pch_required_by) - << Filename << ImportStack[0]->FileName; - for (unsigned I = 1; I < ImportStack.size(); ++I) - Diag(diag::note_pch_required_by) - << ImportStack[I-1]->FileName << ImportStack[I]->FileName; - } - - if (!Diags.isDiagnosticInFlight()) - Diag(diag::note_pch_rebuild_required) << TopLevelPCHName; - } - - IsOutOfDate = true; - } - // FIXME: If the file is overridden and we've already opened it, - // issue an error (or split it into a separate FileEntry). - - InputFile IF = InputFile(File, Overridden || Transient, IsOutOfDate); - - // Note that we've loaded this input file. - F.InputFilesLoaded[ID-1] = IF; - return IF; -} - -/// If we are loading a relocatable PCH or module file, and the filename -/// is not an absolute path, add the system or module root to the beginning of -/// the file name. -void ASTReader::ResolveImportedPath(ModuleFile &M, std::string &Filename) { - // Resolve relative to the base directory, if we have one. - if (!M.BaseDirectory.empty()) - return ResolveImportedPath(Filename, M.BaseDirectory); -} - -void ASTReader::ResolveImportedPath(std::string &Filename, StringRef Prefix) { - if (Filename.empty() || llvm::sys::path::is_absolute(Filename)) - return; - - SmallString<128> Buffer; - llvm::sys::path::append(Buffer, Prefix, Filename); - Filename.assign(Buffer.begin(), Buffer.end()); -} - -static bool isDiagnosedResult(ASTReader::ASTReadResult ARR, unsigned Caps) { - switch (ARR) { - case ASTReader::Failure: return true; - case ASTReader::Missing: return !(Caps & ASTReader::ARR_Missing); - case ASTReader::OutOfDate: return !(Caps & ASTReader::ARR_OutOfDate); - case ASTReader::VersionMismatch: return !(Caps & ASTReader::ARR_VersionMismatch); - case ASTReader::ConfigurationMismatch: - return !(Caps & ASTReader::ARR_ConfigurationMismatch); - case ASTReader::HadErrors: return true; - case ASTReader::Success: return false; - } - - llvm_unreachable("unknown ASTReadResult"); -} - -ASTReader::ASTReadResult ASTReader::ReadOptionsBlock( - BitstreamCursor &Stream, unsigned ClientLoadCapabilities, - bool AllowCompatibleConfigurationMismatch, ASTReaderListener &Listener, - std::string &SuggestedPredefines) { - if (Stream.EnterSubBlock(OPTIONS_BLOCK_ID)) - return Failure; - - // Read all of the records in the options block. - RecordData Record; - ASTReadResult Result = Success; - while (true) { - llvm::BitstreamEntry Entry = Stream.advance(); - - switch (Entry.Kind) { - case llvm::BitstreamEntry::Error: - case llvm::BitstreamEntry::SubBlock: - return Failure; - - case llvm::BitstreamEntry::EndBlock: - return Result; - - case llvm::BitstreamEntry::Record: - // The interesting case. - break; - } - - // Read and process a record. - Record.clear(); - switch ((OptionsRecordTypes)Stream.readRecord(Entry.ID, Record)) { - case LANGUAGE_OPTIONS: { - bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0; - if (ParseLanguageOptions(Record, Complain, Listener, - AllowCompatibleConfigurationMismatch)) - Result = ConfigurationMismatch; - break; - } - - case TARGET_OPTIONS: { - bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0; - if (ParseTargetOptions(Record, Complain, Listener, - AllowCompatibleConfigurationMismatch)) - Result = ConfigurationMismatch; - break; - } - - case FILE_SYSTEM_OPTIONS: { - bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0; - if (!AllowCompatibleConfigurationMismatch && - ParseFileSystemOptions(Record, Complain, Listener)) - Result = ConfigurationMismatch; - break; - } - - case HEADER_SEARCH_OPTIONS: { - bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0; - if (!AllowCompatibleConfigurationMismatch && - ParseHeaderSearchOptions(Record, Complain, Listener)) - Result = ConfigurationMismatch; - break; - } - - case PREPROCESSOR_OPTIONS: - bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0; - if (!AllowCompatibleConfigurationMismatch && - ParsePreprocessorOptions(Record, Complain, Listener, - SuggestedPredefines)) - Result = ConfigurationMismatch; - break; - } - } -} - -ASTReader::ASTReadResult -ASTReader::ReadControlBlock(ModuleFile &F, - SmallVectorImpl<ImportedModule> &Loaded, - const ModuleFile *ImportedBy, - unsigned ClientLoadCapabilities) { - BitstreamCursor &Stream = F.Stream; - ASTReadResult Result = Success; - - if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) { - Error("malformed block record in AST file"); - return Failure; - } - - // Lambda to read the unhashed control block the first time it's called. - // - // For PCM files, the unhashed control block cannot be read until after the - // MODULE_NAME record. However, PCH files have no MODULE_NAME, and yet still - // need to look ahead before reading the IMPORTS record. For consistency, - // this block is always read somehow (see BitstreamEntry::EndBlock). - bool HasReadUnhashedControlBlock = false; - auto readUnhashedControlBlockOnce = [&]() { - if (!HasReadUnhashedControlBlock) { - HasReadUnhashedControlBlock = true; - if (ASTReadResult Result = - readUnhashedControlBlock(F, ImportedBy, ClientLoadCapabilities)) - return Result; - } - return Success; - }; - - // Read all of the records and blocks in the control block. - RecordData Record; - unsigned NumInputs = 0; - unsigned NumUserInputs = 0; - while (true) { - llvm::BitstreamEntry Entry = Stream.advance(); - - switch (Entry.Kind) { - case llvm::BitstreamEntry::Error: - Error("malformed block record in AST file"); - return Failure; - case llvm::BitstreamEntry::EndBlock: { - // Validate the module before returning. This call catches an AST with - // no module name and no imports. - if (ASTReadResult Result = readUnhashedControlBlockOnce()) - return Result; - - // Validate input files. - const HeaderSearchOptions &HSOpts = - PP.getHeaderSearchInfo().getHeaderSearchOpts(); - - // All user input files reside at the index range [0, NumUserInputs), and - // system input files reside at [NumUserInputs, NumInputs). For explicitly - // loaded module files, ignore missing inputs. - if (!DisableValidation && F.Kind != MK_ExplicitModule && - F.Kind != MK_PrebuiltModule) { - bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0; - - // If we are reading a module, we will create a verification timestamp, - // so we verify all input files. Otherwise, verify only user input - // files. - - unsigned N = NumUserInputs; - if (ValidateSystemInputs || - (HSOpts.ModulesValidateOncePerBuildSession && - F.InputFilesValidationTimestamp <= HSOpts.BuildSessionTimestamp && - F.Kind == MK_ImplicitModule)) - N = NumInputs; - - for (unsigned I = 0; I < N; ++I) { - InputFile IF = getInputFile(F, I+1, Complain); - if (!IF.getFile() || IF.isOutOfDate()) - return OutOfDate; - } - } - - if (Listener) - Listener->visitModuleFile(F.FileName, F.Kind); - - if (Listener && Listener->needsInputFileVisitation()) { - unsigned N = Listener->needsSystemInputFileVisitation() ? NumInputs - : NumUserInputs; - for (unsigned I = 0; I < N; ++I) { - bool IsSystem = I >= NumUserInputs; - InputFileInfo FI = readInputFileInfo(F, I+1); - Listener->visitInputFile(FI.Filename, IsSystem, FI.Overridden, - F.Kind == MK_ExplicitModule || - F.Kind == MK_PrebuiltModule); - } - } - - return Result; - } - - case llvm::BitstreamEntry::SubBlock: - switch (Entry.ID) { - case INPUT_FILES_BLOCK_ID: - F.InputFilesCursor = Stream; - if (Stream.SkipBlock() || // Skip with the main cursor - // Read the abbreviations - ReadBlockAbbrevs(F.InputFilesCursor, INPUT_FILES_BLOCK_ID)) { - Error("malformed block record in AST file"); - return Failure; - } - continue; - - case OPTIONS_BLOCK_ID: - // If we're reading the first module for this group, check its options - // are compatible with ours. For modules it imports, no further checking - // is required, because we checked them when we built it. - if (Listener && !ImportedBy) { - // Should we allow the configuration of the module file to differ from - // the configuration of the current translation unit in a compatible - // way? - // - // FIXME: Allow this for files explicitly specified with -include-pch. - bool AllowCompatibleConfigurationMismatch = - F.Kind == MK_ExplicitModule || F.Kind == MK_PrebuiltModule; - - Result = ReadOptionsBlock(Stream, ClientLoadCapabilities, - AllowCompatibleConfigurationMismatch, - *Listener, SuggestedPredefines); - if (Result == Failure) { - Error("malformed block record in AST file"); - return Result; - } - - if (DisableValidation || - (AllowConfigurationMismatch && Result == ConfigurationMismatch)) - Result = Success; - - // If we can't load the module, exit early since we likely - // will rebuild the module anyway. The stream may be in the - // middle of a block. - if (Result != Success) - return Result; - } else if (Stream.SkipBlock()) { - Error("malformed block record in AST file"); - return Failure; - } - continue; - - default: - if (Stream.SkipBlock()) { - Error("malformed block record in AST file"); - return Failure; - } - continue; - } - - case llvm::BitstreamEntry::Record: - // The interesting case. - break; - } - - // Read and process a record. - Record.clear(); - StringRef Blob; - switch ((ControlRecordTypes)Stream.readRecord(Entry.ID, Record, &Blob)) { - case METADATA: { - if (Record[0] != VERSION_MAJOR && !DisableValidation) { - if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0) - Diag(Record[0] < VERSION_MAJOR? diag::err_pch_version_too_old - : diag::err_pch_version_too_new); - return VersionMismatch; - } - - bool hasErrors = Record[7]; - if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) { - Diag(diag::err_pch_with_compiler_errors); - return HadErrors; - } - if (hasErrors) { - Diags.ErrorOccurred = true; - Diags.UncompilableErrorOccurred = true; - Diags.UnrecoverableErrorOccurred = true; - } - - F.RelocatablePCH = Record[4]; - // Relative paths in a relocatable PCH are relative to our sysroot. - if (F.RelocatablePCH) - F.BaseDirectory = isysroot.empty() ? "/" : isysroot; - - F.HasTimestamps = Record[5]; - - F.PCHHasObjectFile = Record[6]; - - const std::string &CurBranch = getClangFullRepositoryVersion(); - StringRef ASTBranch = Blob; - if (StringRef(CurBranch) != ASTBranch && !DisableValidation) { - if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0) - Diag(diag::err_pch_different_branch) << ASTBranch << CurBranch; - return VersionMismatch; - } - break; - } - - case IMPORTS: { - // Validate the AST before processing any imports (otherwise, untangling - // them can be error-prone and expensive). A module will have a name and - // will already have been validated, but this catches the PCH case. - if (ASTReadResult Result = readUnhashedControlBlockOnce()) - return Result; - - // Load each of the imported PCH files. - unsigned Idx = 0, N = Record.size(); - while (Idx < N) { - // Read information about the AST file. - ModuleKind ImportedKind = (ModuleKind)Record[Idx++]; - // The import location will be the local one for now; we will adjust - // all import locations of module imports after the global source - // location info are setup, in ReadAST. - SourceLocation ImportLoc = - ReadUntranslatedSourceLocation(Record[Idx++]); - off_t StoredSize = (off_t)Record[Idx++]; - time_t StoredModTime = (time_t)Record[Idx++]; - ASTFileSignature StoredSignature = { - {{(uint32_t)Record[Idx++], (uint32_t)Record[Idx++], - (uint32_t)Record[Idx++], (uint32_t)Record[Idx++], - (uint32_t)Record[Idx++]}}}; - - std::string ImportedName = ReadString(Record, Idx); - std::string ImportedFile; - - // For prebuilt and explicit modules first consult the file map for - // an override. Note that here we don't search prebuilt module - // directories, only the explicit name to file mappings. Also, we will - // still verify the size/signature making sure it is essentially the - // same file but perhaps in a different location. - if (ImportedKind == MK_PrebuiltModule || ImportedKind == MK_ExplicitModule) - ImportedFile = PP.getHeaderSearchInfo().getPrebuiltModuleFileName( - ImportedName, /*FileMapOnly*/ true); - - if (ImportedFile.empty()) - ImportedFile = ReadPath(F, Record, Idx); - else - SkipPath(Record, Idx); - - // If our client can't cope with us being out of date, we can't cope with - // our dependency being missing. - unsigned Capabilities = ClientLoadCapabilities; - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) - Capabilities &= ~ARR_Missing; - - // Load the AST file. - auto Result = ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, - Loaded, StoredSize, StoredModTime, - StoredSignature, Capabilities); - - // If we diagnosed a problem, produce a backtrace. - if (isDiagnosedResult(Result, Capabilities)) - Diag(diag::note_module_file_imported_by) - << F.FileName << !F.ModuleName.empty() << F.ModuleName; - - switch (Result) { - case Failure: return Failure; - // If we have to ignore the dependency, we'll have to ignore this too. - case Missing: - case OutOfDate: return OutOfDate; - case VersionMismatch: return VersionMismatch; - case ConfigurationMismatch: return ConfigurationMismatch; - case HadErrors: return HadErrors; - case Success: break; - } - } - break; - } - - case ORIGINAL_FILE: - F.OriginalSourceFileID = FileID::get(Record[0]); - F.ActualOriginalSourceFileName = Blob; - F.OriginalSourceFileName = F.ActualOriginalSourceFileName; - ResolveImportedPath(F, F.OriginalSourceFileName); - break; - - case ORIGINAL_FILE_ID: - F.OriginalSourceFileID = FileID::get(Record[0]); - break; - - case ORIGINAL_PCH_DIR: - F.OriginalDir = Blob; - break; - - case MODULE_NAME: - F.ModuleName = Blob; - if (Listener) - Listener->ReadModuleName(F.ModuleName); - - // Validate the AST as soon as we have a name so we can exit early on - // failure. - if (ASTReadResult Result = readUnhashedControlBlockOnce()) - return Result; - - break; - - case MODULE_DIRECTORY: { - assert(!F.ModuleName.empty() && - "MODULE_DIRECTORY found before MODULE_NAME"); - // If we've already loaded a module map file covering this module, we may - // have a better path for it (relative to the current build). - Module *M = PP.getHeaderSearchInfo().lookupModule( - F.ModuleName, /*AllowSearch*/ true, - /*AllowExtraModuleMapSearch*/ true); - if (M && M->Directory) { - // If we're implicitly loading a module, the base directory can't - // change between the build and use. - // Don't emit module relocation error if we have -fno-validate-pch - if (!PP.getPreprocessorOpts().DisablePCHValidation && - F.Kind != MK_ExplicitModule && F.Kind != MK_PrebuiltModule) { - const DirectoryEntry *BuildDir = - PP.getFileManager().getDirectory(Blob); - if (!BuildDir || BuildDir != M->Directory) { - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) - Diag(diag::err_imported_module_relocated) - << F.ModuleName << Blob << M->Directory->getName(); - return OutOfDate; - } - } - F.BaseDirectory = M->Directory->getName(); - } else { - F.BaseDirectory = Blob; - } - break; - } - - case MODULE_MAP_FILE: - if (ASTReadResult Result = - ReadModuleMapFileBlock(Record, F, ImportedBy, ClientLoadCapabilities)) - return Result; - break; - - case INPUT_FILE_OFFSETS: - NumInputs = Record[0]; - NumUserInputs = Record[1]; - F.InputFileOffsets = - (const llvm::support::unaligned_uint64_t *)Blob.data(); - F.InputFilesLoaded.resize(NumInputs); - F.NumUserInputFiles = NumUserInputs; - break; - } - } -} - -ASTReader::ASTReadResult -ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { - BitstreamCursor &Stream = F.Stream; - - if (Stream.EnterSubBlock(AST_BLOCK_ID)) { - Error("malformed block record in AST file"); - return Failure; - } - - // Read all of the records and blocks for the AST file. - RecordData Record; - while (true) { - llvm::BitstreamEntry Entry = Stream.advance(); - - switch (Entry.Kind) { - case llvm::BitstreamEntry::Error: - Error("error at end of module block in AST file"); - return Failure; - case llvm::BitstreamEntry::EndBlock: - // Outside of C++, we do not store a lookup map for the translation unit. - // Instead, mark it as needing a lookup map to be built if this module - // contains any declarations lexically within it (which it always does!). - // This usually has no cost, since we very rarely need the lookup map for - // the translation unit outside C++. - if (ASTContext *Ctx = ContextObj) { - DeclContext *DC = Ctx->getTranslationUnitDecl(); - if (DC->hasExternalLexicalStorage() && !Ctx->getLangOpts().CPlusPlus) - DC->setMustBuildLookupTable(); - } - - return Success; - case llvm::BitstreamEntry::SubBlock: - switch (Entry.ID) { - case DECLTYPES_BLOCK_ID: - // We lazily load the decls block, but we want to set up the - // DeclsCursor cursor to point into it. Clone our current bitcode - // cursor to it, enter the block and read the abbrevs in that block. - // With the main cursor, we just skip over it. - F.DeclsCursor = Stream; - if (Stream.SkipBlock() || // Skip with the main cursor. - // Read the abbrevs. - ReadBlockAbbrevs(F.DeclsCursor, DECLTYPES_BLOCK_ID)) { - Error("malformed block record in AST file"); - return Failure; - } - break; - - case PREPROCESSOR_BLOCK_ID: - F.MacroCursor = Stream; - if (!PP.getExternalSource()) - PP.setExternalSource(this); - - if (Stream.SkipBlock() || - ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) { - Error("malformed block record in AST file"); - return Failure; - } - F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo(); - break; - - case PREPROCESSOR_DETAIL_BLOCK_ID: - F.PreprocessorDetailCursor = Stream; - if (Stream.SkipBlock() || - ReadBlockAbbrevs(F.PreprocessorDetailCursor, - PREPROCESSOR_DETAIL_BLOCK_ID)) { - Error("malformed preprocessor detail record in AST file"); - return Failure; - } - F.PreprocessorDetailStartOffset - = F.PreprocessorDetailCursor.GetCurrentBitNo(); - - if (!PP.getPreprocessingRecord()) - PP.createPreprocessingRecord(); - if (!PP.getPreprocessingRecord()->getExternalSource()) - PP.getPreprocessingRecord()->SetExternalSource(*this); - break; - - case SOURCE_MANAGER_BLOCK_ID: - if (ReadSourceManagerBlock(F)) - return Failure; - break; - - case SUBMODULE_BLOCK_ID: - if (ASTReadResult Result = - ReadSubmoduleBlock(F, ClientLoadCapabilities)) - return Result; - break; - - case COMMENTS_BLOCK_ID: { - BitstreamCursor C = Stream; - if (Stream.SkipBlock() || - ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID)) { - Error("malformed comments block in AST file"); - return Failure; - } - CommentsCursors.push_back(std::make_pair(C, &F)); - break; - } - - default: - if (Stream.SkipBlock()) { - Error("malformed block record in AST file"); - return Failure; - } - break; - } - continue; - - case llvm::BitstreamEntry::Record: - // The interesting case. - break; - } - - // Read and process a record. - Record.clear(); - StringRef Blob; - auto RecordType = - (ASTRecordTypes)Stream.readRecord(Entry.ID, Record, &Blob); - - // If we're not loading an AST context, we don't care about most records. - if (!ContextObj) { - switch (RecordType) { - case IDENTIFIER_TABLE: - case IDENTIFIER_OFFSET: - case INTERESTING_IDENTIFIERS: - case STATISTICS: - case PP_CONDITIONAL_STACK: - case PP_COUNTER_VALUE: - case SOURCE_LOCATION_OFFSETS: - case MODULE_OFFSET_MAP: - case SOURCE_MANAGER_LINE_TABLE: - case SOURCE_LOCATION_PRELOADS: - case PPD_ENTITIES_OFFSETS: - case HEADER_SEARCH_TABLE: - case IMPORTED_MODULES: - case MACRO_OFFSET: - break; - default: - continue; - } - } - - switch (RecordType) { - default: // Default behavior: ignore. - break; - - case TYPE_OFFSET: { - if (F.LocalNumTypes != 0) { - Error("duplicate TYPE_OFFSET record in AST file"); - return Failure; - } - F.TypeOffsets = (const uint32_t *)Blob.data(); - F.LocalNumTypes = Record[0]; - unsigned LocalBaseTypeIndex = Record[1]; - F.BaseTypeIndex = getTotalNumTypes(); - - if (F.LocalNumTypes > 0) { - // Introduce the global -> local mapping for types within this module. - GlobalTypeMap.insert(std::make_pair(getTotalNumTypes(), &F)); - - // Introduce the local -> global mapping for types within this module. - F.TypeRemap.insertOrReplace( - std::make_pair(LocalBaseTypeIndex, - F.BaseTypeIndex - LocalBaseTypeIndex)); - - TypesLoaded.resize(TypesLoaded.size() + F.LocalNumTypes); - } - break; - } - - case DECL_OFFSET: { - if (F.LocalNumDecls != 0) { - Error("duplicate DECL_OFFSET record in AST file"); - return Failure; - } - F.DeclOffsets = (const DeclOffset *)Blob.data(); - F.LocalNumDecls = Record[0]; - unsigned LocalBaseDeclID = Record[1]; - F.BaseDeclID = getTotalNumDecls(); - - if (F.LocalNumDecls > 0) { - // Introduce the global -> local mapping for declarations within this - // module. - GlobalDeclMap.insert( - std::make_pair(getTotalNumDecls() + NUM_PREDEF_DECL_IDS, &F)); - - // Introduce the local -> global mapping for declarations within this - // module. - F.DeclRemap.insertOrReplace( - std::make_pair(LocalBaseDeclID, F.BaseDeclID - LocalBaseDeclID)); - - // Introduce the global -> local mapping for declarations within this - // module. - F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID; - - DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls); - } - break; - } - - case TU_UPDATE_LEXICAL: { - DeclContext *TU = ContextObj->getTranslationUnitDecl(); - LexicalContents Contents( - reinterpret_cast<const llvm::support::unaligned_uint32_t *>( - Blob.data()), - static_cast<unsigned int>(Blob.size() / 4)); - TULexicalDecls.push_back(std::make_pair(&F, Contents)); - TU->setHasExternalLexicalStorage(true); - break; - } - - case UPDATE_VISIBLE: { - unsigned Idx = 0; - serialization::DeclID ID = ReadDeclID(F, Record, Idx); - auto *Data = (const unsigned char*)Blob.data(); - PendingVisibleUpdates[ID].push_back(PendingVisibleUpdate{&F, Data}); - // If we've already loaded the decl, perform the updates when we finish - // loading this block. - if (Decl *D = GetExistingDecl(ID)) - PendingUpdateRecords.push_back( - PendingUpdateRecord(ID, D, /*JustLoaded=*/false)); - break; - } - - case IDENTIFIER_TABLE: - F.IdentifierTableData = Blob.data(); - if (Record[0]) { - F.IdentifierLookupTable = ASTIdentifierLookupTable::Create( - (const unsigned char *)F.IdentifierTableData + Record[0], - (const unsigned char *)F.IdentifierTableData + sizeof(uint32_t), - (const unsigned char *)F.IdentifierTableData, - ASTIdentifierLookupTrait(*this, F)); - - PP.getIdentifierTable().setExternalIdentifierLookup(this); - } - break; - - case IDENTIFIER_OFFSET: { - if (F.LocalNumIdentifiers != 0) { - Error("duplicate IDENTIFIER_OFFSET record in AST file"); - return Failure; - } - F.IdentifierOffsets = (const uint32_t *)Blob.data(); - F.LocalNumIdentifiers = Record[0]; - unsigned LocalBaseIdentifierID = Record[1]; - F.BaseIdentifierID = getTotalNumIdentifiers(); - - if (F.LocalNumIdentifiers > 0) { - // Introduce the global -> local mapping for identifiers within this - // module. - GlobalIdentifierMap.insert(std::make_pair(getTotalNumIdentifiers() + 1, - &F)); - - // Introduce the local -> global mapping for identifiers within this - // module. - F.IdentifierRemap.insertOrReplace( - std::make_pair(LocalBaseIdentifierID, - F.BaseIdentifierID - LocalBaseIdentifierID)); - - IdentifiersLoaded.resize(IdentifiersLoaded.size() - + F.LocalNumIdentifiers); - } - break; - } - - case INTERESTING_IDENTIFIERS: - F.PreloadIdentifierOffsets.assign(Record.begin(), Record.end()); - break; - - case EAGERLY_DESERIALIZED_DECLS: - // FIXME: Skip reading this record if our ASTConsumer doesn't care - // about "interesting" decls (for instance, if we're building a module). - for (unsigned I = 0, N = Record.size(); I != N; ++I) - EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I])); - break; - - case MODULAR_CODEGEN_DECLS: - // FIXME: Skip reading this record if our ASTConsumer doesn't care about - // them (ie: if we're not codegenerating this module). - if (F.Kind == MK_MainFile) - for (unsigned I = 0, N = Record.size(); I != N; ++I) - EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I])); - break; - - case SPECIAL_TYPES: - if (SpecialTypes.empty()) { - for (unsigned I = 0, N = Record.size(); I != N; ++I) - SpecialTypes.push_back(getGlobalTypeID(F, Record[I])); - break; - } - - if (SpecialTypes.size() != Record.size()) { - Error("invalid special-types record"); - return Failure; - } - - for (unsigned I = 0, N = Record.size(); I != N; ++I) { - serialization::TypeID ID = getGlobalTypeID(F, Record[I]); - if (!SpecialTypes[I]) - SpecialTypes[I] = ID; - // FIXME: If ID && SpecialTypes[I] != ID, do we need a separate - // merge step? - } - break; - - case STATISTICS: - TotalNumStatements += Record[0]; - TotalNumMacros += Record[1]; - TotalLexicalDeclContexts += Record[2]; - TotalVisibleDeclContexts += Record[3]; - break; - - case UNUSED_FILESCOPED_DECLS: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - UnusedFileScopedDecls.push_back(getGlobalDeclID(F, Record[I])); - break; - - case DELEGATING_CTORS: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - DelegatingCtorDecls.push_back(getGlobalDeclID(F, Record[I])); - break; - - case WEAK_UNDECLARED_IDENTIFIERS: - if (Record.size() % 4 != 0) { - Error("invalid weak identifiers record"); - return Failure; - } - - // FIXME: Ignore weak undeclared identifiers from non-original PCH - // files. This isn't the way to do it :) - WeakUndeclaredIdentifiers.clear(); - - // Translate the weak, undeclared identifiers into global IDs. - for (unsigned I = 0, N = Record.size(); I < N; /* in loop */) { - WeakUndeclaredIdentifiers.push_back( - getGlobalIdentifierID(F, Record[I++])); - WeakUndeclaredIdentifiers.push_back( - getGlobalIdentifierID(F, Record[I++])); - WeakUndeclaredIdentifiers.push_back( - ReadSourceLocation(F, Record, I).getRawEncoding()); - WeakUndeclaredIdentifiers.push_back(Record[I++]); - } - break; - - case SELECTOR_OFFSETS: { - F.SelectorOffsets = (const uint32_t *)Blob.data(); - F.LocalNumSelectors = Record[0]; - unsigned LocalBaseSelectorID = Record[1]; - F.BaseSelectorID = getTotalNumSelectors(); - - if (F.LocalNumSelectors > 0) { - // Introduce the global -> local mapping for selectors within this - // module. - GlobalSelectorMap.insert(std::make_pair(getTotalNumSelectors()+1, &F)); - - // Introduce the local -> global mapping for selectors within this - // module. - F.SelectorRemap.insertOrReplace( - std::make_pair(LocalBaseSelectorID, - F.BaseSelectorID - LocalBaseSelectorID)); - - SelectorsLoaded.resize(SelectorsLoaded.size() + F.LocalNumSelectors); - } - break; - } - - case METHOD_POOL: - F.SelectorLookupTableData = (const unsigned char *)Blob.data(); - if (Record[0]) - F.SelectorLookupTable - = ASTSelectorLookupTable::Create( - F.SelectorLookupTableData + Record[0], - F.SelectorLookupTableData, - ASTSelectorLookupTrait(*this, F)); - TotalNumMethodPoolEntries += Record[1]; - break; - - case REFERENCED_SELECTOR_POOL: - if (!Record.empty()) { - for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) { - ReferencedSelectorsData.push_back(getGlobalSelectorID(F, - Record[Idx++])); - ReferencedSelectorsData.push_back(ReadSourceLocation(F, Record, Idx). - getRawEncoding()); - } - } - break; - - case PP_CONDITIONAL_STACK: - if (!Record.empty()) { - unsigned Idx = 0, End = Record.size() - 1; - bool ReachedEOFWhileSkipping = Record[Idx++]; - llvm::Optional<Preprocessor::PreambleSkipInfo> SkipInfo; - if (ReachedEOFWhileSkipping) { - SourceLocation HashToken = ReadSourceLocation(F, Record, Idx); - SourceLocation IfTokenLoc = ReadSourceLocation(F, Record, Idx); - bool FoundNonSkipPortion = Record[Idx++]; - bool FoundElse = Record[Idx++]; - SourceLocation ElseLoc = ReadSourceLocation(F, Record, Idx); - SkipInfo.emplace(HashToken, IfTokenLoc, FoundNonSkipPortion, - FoundElse, ElseLoc); - } - SmallVector<PPConditionalInfo, 4> ConditionalStack; - while (Idx < End) { - auto Loc = ReadSourceLocation(F, Record, Idx); - bool WasSkipping = Record[Idx++]; - bool FoundNonSkip = Record[Idx++]; - bool FoundElse = Record[Idx++]; - ConditionalStack.push_back( - {Loc, WasSkipping, FoundNonSkip, FoundElse}); - } - PP.setReplayablePreambleConditionalStack(ConditionalStack, SkipInfo); - } - break; - - case PP_COUNTER_VALUE: - if (!Record.empty() && Listener) - Listener->ReadCounter(F, Record[0]); - break; - - case FILE_SORTED_DECLS: - F.FileSortedDecls = (const DeclID *)Blob.data(); - F.NumFileSortedDecls = Record[0]; - break; - - case SOURCE_LOCATION_OFFSETS: { - F.SLocEntryOffsets = (const uint32_t *)Blob.data(); - F.LocalNumSLocEntries = Record[0]; - unsigned SLocSpaceSize = Record[1]; - std::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) = - SourceMgr.AllocateLoadedSLocEntries(F.LocalNumSLocEntries, - SLocSpaceSize); - if (!F.SLocEntryBaseID) { - Error("ran out of source locations"); - break; - } - // Make our entry in the range map. BaseID is negative and growing, so - // we invert it. Because we invert it, though, we need the other end of - // the range. - unsigned RangeStart = - unsigned(-F.SLocEntryBaseID) - F.LocalNumSLocEntries + 1; - GlobalSLocEntryMap.insert(std::make_pair(RangeStart, &F)); - F.FirstLoc = SourceLocation::getFromRawEncoding(F.SLocEntryBaseOffset); - - // SLocEntryBaseOffset is lower than MaxLoadedOffset and decreasing. - assert((F.SLocEntryBaseOffset & (1U << 31U)) == 0); - GlobalSLocOffsetMap.insert( - std::make_pair(SourceManager::MaxLoadedOffset - F.SLocEntryBaseOffset - - SLocSpaceSize,&F)); - - // Initialize the remapping table. - // Invalid stays invalid. - F.SLocRemap.insertOrReplace(std::make_pair(0U, 0)); - // This module. Base was 2 when being compiled. - F.SLocRemap.insertOrReplace(std::make_pair(2U, - static_cast<int>(F.SLocEntryBaseOffset - 2))); - - TotalNumSLocEntries += F.LocalNumSLocEntries; - break; - } - - case MODULE_OFFSET_MAP: - F.ModuleOffsetMap = Blob; - break; - - case SOURCE_MANAGER_LINE_TABLE: - if (ParseLineTable(F, Record)) - return Failure; - break; - - case SOURCE_LOCATION_PRELOADS: { - // Need to transform from the local view (1-based IDs) to the global view, - // which is based off F.SLocEntryBaseID. - if (!F.PreloadSLocEntries.empty()) { - Error("Multiple SOURCE_LOCATION_PRELOADS records in AST file"); - return Failure; - } - - F.PreloadSLocEntries.swap(Record); - break; - } - - case EXT_VECTOR_DECLS: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - ExtVectorDecls.push_back(getGlobalDeclID(F, Record[I])); - break; - - case VTABLE_USES: - if (Record.size() % 3 != 0) { - Error("Invalid VTABLE_USES record"); - return Failure; - } - - // Later tables overwrite earlier ones. - // FIXME: Modules will have some trouble with this. This is clearly not - // the right way to do this. - VTableUses.clear(); - - for (unsigned Idx = 0, N = Record.size(); Idx != N; /* In loop */) { - VTableUses.push_back(getGlobalDeclID(F, Record[Idx++])); - VTableUses.push_back( - ReadSourceLocation(F, Record, Idx).getRawEncoding()); - VTableUses.push_back(Record[Idx++]); - } - break; - - case PENDING_IMPLICIT_INSTANTIATIONS: - if (PendingInstantiations.size() % 2 != 0) { - Error("Invalid existing PendingInstantiations"); - return Failure; - } - - if (Record.size() % 2 != 0) { - Error("Invalid PENDING_IMPLICIT_INSTANTIATIONS block"); - return Failure; - } - - for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) { - PendingInstantiations.push_back(getGlobalDeclID(F, Record[I++])); - PendingInstantiations.push_back( - ReadSourceLocation(F, Record, I).getRawEncoding()); - } - break; - - case SEMA_DECL_REFS: - if (Record.size() != 3) { - Error("Invalid SEMA_DECL_REFS block"); - return Failure; - } - for (unsigned I = 0, N = Record.size(); I != N; ++I) - SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I])); - break; - - case PPD_ENTITIES_OFFSETS: { - F.PreprocessedEntityOffsets = (const PPEntityOffset *)Blob.data(); - assert(Blob.size() % sizeof(PPEntityOffset) == 0); - F.NumPreprocessedEntities = Blob.size() / sizeof(PPEntityOffset); - - unsigned LocalBasePreprocessedEntityID = Record[0]; - - unsigned StartingID; - if (!PP.getPreprocessingRecord()) - PP.createPreprocessingRecord(); - if (!PP.getPreprocessingRecord()->getExternalSource()) - PP.getPreprocessingRecord()->SetExternalSource(*this); - StartingID - = PP.getPreprocessingRecord() - ->allocateLoadedEntities(F.NumPreprocessedEntities); - F.BasePreprocessedEntityID = StartingID; - - if (F.NumPreprocessedEntities > 0) { - // Introduce the global -> local mapping for preprocessed entities in - // this module. - GlobalPreprocessedEntityMap.insert(std::make_pair(StartingID, &F)); - - // Introduce the local -> global mapping for preprocessed entities in - // this module. - F.PreprocessedEntityRemap.insertOrReplace( - std::make_pair(LocalBasePreprocessedEntityID, - F.BasePreprocessedEntityID - LocalBasePreprocessedEntityID)); - } - - break; - } - - case PPD_SKIPPED_RANGES: { - F.PreprocessedSkippedRangeOffsets = (const PPSkippedRange*)Blob.data(); - assert(Blob.size() % sizeof(PPSkippedRange) == 0); - F.NumPreprocessedSkippedRanges = Blob.size() / sizeof(PPSkippedRange); - - if (!PP.getPreprocessingRecord()) - PP.createPreprocessingRecord(); - if (!PP.getPreprocessingRecord()->getExternalSource()) - PP.getPreprocessingRecord()->SetExternalSource(*this); - F.BasePreprocessedSkippedRangeID = PP.getPreprocessingRecord() - ->allocateSkippedRanges(F.NumPreprocessedSkippedRanges); - - if (F.NumPreprocessedSkippedRanges > 0) - GlobalSkippedRangeMap.insert( - std::make_pair(F.BasePreprocessedSkippedRangeID, &F)); - break; - } - - case DECL_UPDATE_OFFSETS: - if (Record.size() % 2 != 0) { - Error("invalid DECL_UPDATE_OFFSETS block in AST file"); - return Failure; - } - for (unsigned I = 0, N = Record.size(); I != N; I += 2) { - GlobalDeclID ID = getGlobalDeclID(F, Record[I]); - DeclUpdateOffsets[ID].push_back(std::make_pair(&F, Record[I + 1])); - - // If we've already loaded the decl, perform the updates when we finish - // loading this block. - if (Decl *D = GetExistingDecl(ID)) - PendingUpdateRecords.push_back( - PendingUpdateRecord(ID, D, /*JustLoaded=*/false)); - } - break; - - case OBJC_CATEGORIES_MAP: - if (F.LocalNumObjCCategoriesInMap != 0) { - Error("duplicate OBJC_CATEGORIES_MAP record in AST file"); - return Failure; - } - - F.LocalNumObjCCategoriesInMap = Record[0]; - F.ObjCCategoriesMap = (const ObjCCategoriesInfo *)Blob.data(); - break; - - case OBJC_CATEGORIES: - F.ObjCCategories.swap(Record); - break; - - case CUDA_SPECIAL_DECL_REFS: - // Later tables overwrite earlier ones. - // FIXME: Modules will have trouble with this. - CUDASpecialDeclRefs.clear(); - for (unsigned I = 0, N = Record.size(); I != N; ++I) - CUDASpecialDeclRefs.push_back(getGlobalDeclID(F, Record[I])); - break; - - case HEADER_SEARCH_TABLE: - F.HeaderFileInfoTableData = Blob.data(); - F.LocalNumHeaderFileInfos = Record[1]; - if (Record[0]) { - F.HeaderFileInfoTable - = HeaderFileInfoLookupTable::Create( - (const unsigned char *)F.HeaderFileInfoTableData + Record[0], - (const unsigned char *)F.HeaderFileInfoTableData, - HeaderFileInfoTrait(*this, F, - &PP.getHeaderSearchInfo(), - Blob.data() + Record[2])); - - PP.getHeaderSearchInfo().SetExternalSource(this); - if (!PP.getHeaderSearchInfo().getExternalLookup()) - PP.getHeaderSearchInfo().SetExternalLookup(this); - } - break; - - case FP_PRAGMA_OPTIONS: - // Later tables overwrite earlier ones. - FPPragmaOptions.swap(Record); - break; - - case OPENCL_EXTENSIONS: - for (unsigned I = 0, E = Record.size(); I != E; ) { - auto Name = ReadString(Record, I); - auto &Opt = OpenCLExtensions.OptMap[Name]; - Opt.Supported = Record[I++] != 0; - Opt.Enabled = Record[I++] != 0; - Opt.Avail = Record[I++]; - Opt.Core = Record[I++]; - } - break; - - case OPENCL_EXTENSION_TYPES: - for (unsigned I = 0, E = Record.size(); I != E;) { - auto TypeID = static_cast<::TypeID>(Record[I++]); - auto *Type = GetType(TypeID).getTypePtr(); - auto NumExt = static_cast<unsigned>(Record[I++]); - for (unsigned II = 0; II != NumExt; ++II) { - auto Ext = ReadString(Record, I); - OpenCLTypeExtMap[Type].insert(Ext); - } - } - break; - - case OPENCL_EXTENSION_DECLS: - for (unsigned I = 0, E = Record.size(); I != E;) { - auto DeclID = static_cast<::DeclID>(Record[I++]); - auto *Decl = GetDecl(DeclID); - auto NumExt = static_cast<unsigned>(Record[I++]); - for (unsigned II = 0; II != NumExt; ++II) { - auto Ext = ReadString(Record, I); - OpenCLDeclExtMap[Decl].insert(Ext); - } - } - break; - - case TENTATIVE_DEFINITIONS: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - TentativeDefinitions.push_back(getGlobalDeclID(F, Record[I])); - break; - - case KNOWN_NAMESPACES: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - KnownNamespaces.push_back(getGlobalDeclID(F, Record[I])); - break; - - case UNDEFINED_BUT_USED: - if (UndefinedButUsed.size() % 2 != 0) { - Error("Invalid existing UndefinedButUsed"); - return Failure; - } - - if (Record.size() % 2 != 0) { - Error("invalid undefined-but-used record"); - return Failure; - } - for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) { - UndefinedButUsed.push_back(getGlobalDeclID(F, Record[I++])); - UndefinedButUsed.push_back( - ReadSourceLocation(F, Record, I).getRawEncoding()); - } - break; - - case DELETE_EXPRS_TO_ANALYZE: - for (unsigned I = 0, N = Record.size(); I != N;) { - DelayedDeleteExprs.push_back(getGlobalDeclID(F, Record[I++])); - const uint64_t Count = Record[I++]; - DelayedDeleteExprs.push_back(Count); - for (uint64_t C = 0; C < Count; ++C) { - DelayedDeleteExprs.push_back(ReadSourceLocation(F, Record, I).getRawEncoding()); - bool IsArrayForm = Record[I++] == 1; - DelayedDeleteExprs.push_back(IsArrayForm); - } - } - break; - - case IMPORTED_MODULES: - if (!F.isModule()) { - // If we aren't loading a module (which has its own exports), make - // all of the imported modules visible. - // FIXME: Deal with macros-only imports. - for (unsigned I = 0, N = Record.size(); I != N; /**/) { - unsigned GlobalID = getGlobalSubmoduleID(F, Record[I++]); - SourceLocation Loc = ReadSourceLocation(F, Record, I); - if (GlobalID) { - ImportedModules.push_back(ImportedSubmodule(GlobalID, Loc)); - if (DeserializationListener) - DeserializationListener->ModuleImportRead(GlobalID, Loc); - } - } - } - break; - - case MACRO_OFFSET: { - if (F.LocalNumMacros != 0) { - Error("duplicate MACRO_OFFSET record in AST file"); - return Failure; - } - F.MacroOffsets = (const uint32_t *)Blob.data(); - F.LocalNumMacros = Record[0]; - unsigned LocalBaseMacroID = Record[1]; - F.BaseMacroID = getTotalNumMacros(); - - if (F.LocalNumMacros > 0) { - // Introduce the global -> local mapping for macros within this module. - GlobalMacroMap.insert(std::make_pair(getTotalNumMacros() + 1, &F)); - - // Introduce the local -> global mapping for macros within this module. - F.MacroRemap.insertOrReplace( - std::make_pair(LocalBaseMacroID, - F.BaseMacroID - LocalBaseMacroID)); - - MacrosLoaded.resize(MacrosLoaded.size() + F.LocalNumMacros); - } - break; - } - - case LATE_PARSED_TEMPLATE: - LateParsedTemplates.append(Record.begin(), Record.end()); - break; - - case OPTIMIZE_PRAGMA_OPTIONS: - if (Record.size() != 1) { - Error("invalid pragma optimize record"); - return Failure; - } - OptimizeOffPragmaLocation = ReadSourceLocation(F, Record[0]); - break; - - case MSSTRUCT_PRAGMA_OPTIONS: - if (Record.size() != 1) { - Error("invalid pragma ms_struct record"); - return Failure; - } - PragmaMSStructState = Record[0]; - break; - - case POINTERS_TO_MEMBERS_PRAGMA_OPTIONS: - if (Record.size() != 2) { - Error("invalid pragma ms_struct record"); - return Failure; - } - PragmaMSPointersToMembersState = Record[0]; - PointersToMembersPragmaLocation = ReadSourceLocation(F, Record[1]); - break; - - case UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - UnusedLocalTypedefNameCandidates.push_back( - getGlobalDeclID(F, Record[I])); - break; - - case CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH: - if (Record.size() != 1) { - Error("invalid cuda pragma options record"); - return Failure; - } - ForceCUDAHostDeviceDepth = Record[0]; - break; - - case PACK_PRAGMA_OPTIONS: { - if (Record.size() < 3) { - Error("invalid pragma pack record"); - return Failure; - } - PragmaPackCurrentValue = Record[0]; - PragmaPackCurrentLocation = ReadSourceLocation(F, Record[1]); - unsigned NumStackEntries = Record[2]; - unsigned Idx = 3; - // Reset the stack when importing a new module. - PragmaPackStack.clear(); - for (unsigned I = 0; I < NumStackEntries; ++I) { - PragmaPackStackEntry Entry; - Entry.Value = Record[Idx++]; - Entry.Location = ReadSourceLocation(F, Record[Idx++]); - Entry.PushLocation = ReadSourceLocation(F, Record[Idx++]); - PragmaPackStrings.push_back(ReadString(Record, Idx)); - Entry.SlotLabel = PragmaPackStrings.back(); - PragmaPackStack.push_back(Entry); - } - break; - } - } - } -} - -void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const { - assert(!F.ModuleOffsetMap.empty() && "no module offset map to read"); - - // Additional remapping information. - const unsigned char *Data = (const unsigned char*)F.ModuleOffsetMap.data(); - const unsigned char *DataEnd = Data + F.ModuleOffsetMap.size(); - F.ModuleOffsetMap = StringRef(); - - // If we see this entry before SOURCE_LOCATION_OFFSETS, add placeholders. - if (F.SLocRemap.find(0) == F.SLocRemap.end()) { - F.SLocRemap.insert(std::make_pair(0U, 0)); - F.SLocRemap.insert(std::make_pair(2U, 1)); - } - - // Continuous range maps we may be updating in our module. - using RemapBuilder = ContinuousRangeMap<uint32_t, int, 2>::Builder; - RemapBuilder SLocRemap(F.SLocRemap); - RemapBuilder IdentifierRemap(F.IdentifierRemap); - RemapBuilder MacroRemap(F.MacroRemap); - RemapBuilder PreprocessedEntityRemap(F.PreprocessedEntityRemap); - RemapBuilder SubmoduleRemap(F.SubmoduleRemap); - RemapBuilder SelectorRemap(F.SelectorRemap); - RemapBuilder DeclRemap(F.DeclRemap); - RemapBuilder TypeRemap(F.TypeRemap); - - while (Data < DataEnd) { - // FIXME: Looking up dependency modules by filename is horrible. Let's - // start fixing this with prebuilt and explicit modules and see how it - // goes... - using namespace llvm::support; - ModuleKind Kind = static_cast<ModuleKind>( - endian::readNext<uint8_t, little, unaligned>(Data)); - uint16_t Len = endian::readNext<uint16_t, little, unaligned>(Data); - StringRef Name = StringRef((const char*)Data, Len); - Data += Len; - ModuleFile *OM = (Kind == MK_PrebuiltModule || Kind == MK_ExplicitModule - ? ModuleMgr.lookupByModuleName(Name) - : ModuleMgr.lookupByFileName(Name)); - if (!OM) { - std::string Msg = - "SourceLocation remap refers to unknown module, cannot find "; - Msg.append(Name); - Error(Msg); - return; - } - - uint32_t SLocOffset = - endian::readNext<uint32_t, little, unaligned>(Data); - uint32_t IdentifierIDOffset = - endian::readNext<uint32_t, little, unaligned>(Data); - uint32_t MacroIDOffset = - endian::readNext<uint32_t, little, unaligned>(Data); - uint32_t PreprocessedEntityIDOffset = - endian::readNext<uint32_t, little, unaligned>(Data); - uint32_t SubmoduleIDOffset = - endian::readNext<uint32_t, little, unaligned>(Data); - uint32_t SelectorIDOffset = - endian::readNext<uint32_t, little, unaligned>(Data); - uint32_t DeclIDOffset = - endian::readNext<uint32_t, little, unaligned>(Data); - uint32_t TypeIndexOffset = - endian::readNext<uint32_t, little, unaligned>(Data); - - uint32_t None = std::numeric_limits<uint32_t>::max(); - - auto mapOffset = [&](uint32_t Offset, uint32_t BaseOffset, - RemapBuilder &Remap) { - if (Offset != None) - Remap.insert(std::make_pair(Offset, - static_cast<int>(BaseOffset - Offset))); - }; - mapOffset(SLocOffset, OM->SLocEntryBaseOffset, SLocRemap); - mapOffset(IdentifierIDOffset, OM->BaseIdentifierID, IdentifierRemap); - mapOffset(MacroIDOffset, OM->BaseMacroID, MacroRemap); - mapOffset(PreprocessedEntityIDOffset, OM->BasePreprocessedEntityID, - PreprocessedEntityRemap); - mapOffset(SubmoduleIDOffset, OM->BaseSubmoduleID, SubmoduleRemap); - mapOffset(SelectorIDOffset, OM->BaseSelectorID, SelectorRemap); - mapOffset(DeclIDOffset, OM->BaseDeclID, DeclRemap); - mapOffset(TypeIndexOffset, OM->BaseTypeIndex, TypeRemap); - - // Global -> local mappings. - F.GlobalToLocalDeclIDs[OM] = DeclIDOffset; - } -} - -ASTReader::ASTReadResult -ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, - const ModuleFile *ImportedBy, - unsigned ClientLoadCapabilities) { - unsigned Idx = 0; - F.ModuleMapPath = ReadPath(F, Record, Idx); - - // Try to resolve ModuleName in the current header search context and - // verify that it is found in the same module map file as we saved. If the - // top-level AST file is a main file, skip this check because there is no - // usable header search context. - assert(!F.ModuleName.empty() && - "MODULE_NAME should come before MODULE_MAP_FILE"); - if (F.Kind == MK_ImplicitModule && ModuleMgr.begin()->Kind != MK_MainFile) { - // An implicitly-loaded module file should have its module listed in some - // module map file that we've already loaded. - Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName); - auto &Map = PP.getHeaderSearchInfo().getModuleMap(); - const FileEntry *ModMap = M ? Map.getModuleMapFileForUniquing(M) : nullptr; - // Don't emit module relocation error if we have -fno-validate-pch - if (!PP.getPreprocessorOpts().DisablePCHValidation && !ModMap) { - assert(ImportedBy && "top-level import should be verified"); - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) { - if (auto *ASTFE = M ? M->getASTFile() : nullptr) { - // This module was defined by an imported (explicit) module. - Diag(diag::err_module_file_conflict) << F.ModuleName << F.FileName - << ASTFE->getName(); - } else { - // This module was built with a different module map. - Diag(diag::err_imported_module_not_found) - << F.ModuleName << F.FileName << ImportedBy->FileName - << F.ModuleMapPath; - // In case it was imported by a PCH, there's a chance the user is - // just missing to include the search path to the directory containing - // the modulemap. - if (ImportedBy->Kind == MK_PCH) - Diag(diag::note_imported_by_pch_module_not_found) - << llvm::sys::path::parent_path(F.ModuleMapPath); - } - } - return OutOfDate; - } - - assert(M->Name == F.ModuleName && "found module with different name"); - - // Check the primary module map file. - const FileEntry *StoredModMap = FileMgr.getFile(F.ModuleMapPath); - if (StoredModMap == nullptr || StoredModMap != ModMap) { - assert(ModMap && "found module is missing module map file"); - assert(ImportedBy && "top-level import should be verified"); - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) - Diag(diag::err_imported_module_modmap_changed) - << F.ModuleName << ImportedBy->FileName - << ModMap->getName() << F.ModuleMapPath; - return OutOfDate; - } - - llvm::SmallPtrSet<const FileEntry *, 1> AdditionalStoredMaps; - for (unsigned I = 0, N = Record[Idx++]; I < N; ++I) { - // FIXME: we should use input files rather than storing names. - std::string Filename = ReadPath(F, Record, Idx); - const FileEntry *F = - FileMgr.getFile(Filename, false, false); - if (F == nullptr) { - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) - Error("could not find file '" + Filename +"' referenced by AST file"); - return OutOfDate; - } - AdditionalStoredMaps.insert(F); - } - - // Check any additional module map files (e.g. module.private.modulemap) - // that are not in the pcm. - if (auto *AdditionalModuleMaps = Map.getAdditionalModuleMapFiles(M)) { - for (const FileEntry *ModMap : *AdditionalModuleMaps) { - // Remove files that match - // Note: SmallPtrSet::erase is really remove - if (!AdditionalStoredMaps.erase(ModMap)) { - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) - Diag(diag::err_module_different_modmap) - << F.ModuleName << /*new*/0 << ModMap->getName(); - return OutOfDate; - } - } - } - - // Check any additional module map files that are in the pcm, but not - // found in header search. Cases that match are already removed. - for (const FileEntry *ModMap : AdditionalStoredMaps) { - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) - Diag(diag::err_module_different_modmap) - << F.ModuleName << /*not new*/1 << ModMap->getName(); - return OutOfDate; - } - } - - if (Listener) - Listener->ReadModuleMapFile(F.ModuleMapPath); - return Success; -} - -/// Move the given method to the back of the global list of methods. -static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) { - // Find the entry for this selector in the method pool. - Sema::GlobalMethodPool::iterator Known - = S.MethodPool.find(Method->getSelector()); - if (Known == S.MethodPool.end()) - return; - - // Retrieve the appropriate method list. - ObjCMethodList &Start = Method->isInstanceMethod()? Known->second.first - : Known->second.second; - bool Found = false; - for (ObjCMethodList *List = &Start; List; List = List->getNext()) { - if (!Found) { - if (List->getMethod() == Method) { - Found = true; - } else { - // Keep searching. - continue; - } - } - - if (List->getNext()) - List->setMethod(List->getNext()->getMethod()); - else - List->setMethod(Method); - } -} - -void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner) { - assert(Owner->NameVisibility != Module::Hidden && "nothing to make visible?"); - for (Decl *D : Names) { - bool wasHidden = D->isHidden(); - D->setVisibleDespiteOwningModule(); - - if (wasHidden && SemaObj) { - if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D)) { - moveMethodToBackOfGlobalList(*SemaObj, Method); - } - } - } -} - -void ASTReader::makeModuleVisible(Module *Mod, - Module::NameVisibilityKind NameVisibility, - SourceLocation ImportLoc) { - llvm::SmallPtrSet<Module *, 4> Visited; - SmallVector<Module *, 4> Stack; - Stack.push_back(Mod); - while (!Stack.empty()) { - Mod = Stack.pop_back_val(); - - if (NameVisibility <= Mod->NameVisibility) { - // This module already has this level of visibility (or greater), so - // there is nothing more to do. - continue; - } - - if (!Mod->isAvailable()) { - // Modules that aren't available cannot be made visible. - continue; - } - - // Update the module's name visibility. - Mod->NameVisibility = NameVisibility; - - // If we've already deserialized any names from this module, - // mark them as visible. - HiddenNamesMapType::iterator Hidden = HiddenNamesMap.find(Mod); - if (Hidden != HiddenNamesMap.end()) { - auto HiddenNames = std::move(*Hidden); - HiddenNamesMap.erase(Hidden); - makeNamesVisible(HiddenNames.second, HiddenNames.first); - assert(HiddenNamesMap.find(Mod) == HiddenNamesMap.end() && - "making names visible added hidden names"); - } - - // Push any exported modules onto the stack to be marked as visible. - SmallVector<Module *, 16> Exports; - Mod->getExportedModules(Exports); - for (SmallVectorImpl<Module *>::iterator - I = Exports.begin(), E = Exports.end(); I != E; ++I) { - Module *Exported = *I; - if (Visited.insert(Exported).second) - Stack.push_back(Exported); - } - } -} - -/// 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 ASTReader::mergeDefinitionVisibility(NamedDecl *Def, - NamedDecl *MergedDef) { - if (Def->isHidden()) { - // If MergedDef is visible or becomes visible, make the definition visible. - if (!MergedDef->isHidden()) - Def->setVisibleDespiteOwningModule(); - else { - getContext().mergeDefinitionIntoModule( - Def, MergedDef->getImportedOwningModule(), - /*NotifyListeners*/ false); - PendingMergedDefinitionsToDeduplicate.insert(Def); - } - } -} - -bool ASTReader::loadGlobalIndex() { - if (GlobalIndex) - return false; - - if (TriedLoadingGlobalIndex || !UseGlobalIndex || - !PP.getLangOpts().Modules) - return true; - - // Try to load the global index. - TriedLoadingGlobalIndex = true; - StringRef ModuleCachePath - = getPreprocessor().getHeaderSearchInfo().getModuleCachePath(); - std::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode> Result - = GlobalModuleIndex::readIndex(ModuleCachePath); - if (!Result.first) - return true; - - GlobalIndex.reset(Result.first); - ModuleMgr.setGlobalIndex(GlobalIndex.get()); - return false; -} - -bool ASTReader::isGlobalIndexUnavailable() const { - return PP.getLangOpts().Modules && UseGlobalIndex && - !hasGlobalIndex() && TriedLoadingGlobalIndex; -} - -static void updateModuleTimestamp(ModuleFile &MF) { - // Overwrite the timestamp file contents so that file's mtime changes. - std::string TimestampFilename = MF.getTimestampFilename(); - std::error_code EC; - llvm::raw_fd_ostream OS(TimestampFilename, EC, llvm::sys::fs::F_Text); - if (EC) - return; - OS << "Timestamp file\n"; - OS.close(); - OS.clear_error(); // Avoid triggering a fatal error. -} - -/// Given a cursor at the start of an AST file, scan ahead and drop the -/// cursor into the start of the given block ID, returning false on success and -/// true on failure. -static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) { - while (true) { - llvm::BitstreamEntry Entry = Cursor.advance(); - switch (Entry.Kind) { - case llvm::BitstreamEntry::Error: - case llvm::BitstreamEntry::EndBlock: - return true; - - case llvm::BitstreamEntry::Record: - // Ignore top-level records. - Cursor.skipRecord(Entry.ID); - break; - - case llvm::BitstreamEntry::SubBlock: - if (Entry.ID == BlockID) { - if (Cursor.EnterSubBlock(BlockID)) - return true; - // Found it! - return false; - } - - if (Cursor.SkipBlock()) - return true; - } - } -} - -ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, - ModuleKind Type, - SourceLocation ImportLoc, - unsigned ClientLoadCapabilities, - SmallVectorImpl<ImportedSubmodule> *Imported) { - llvm::SaveAndRestore<SourceLocation> - SetCurImportLocRAII(CurrentImportLoc, ImportLoc); - - // Defer any pending actions until we get to the end of reading the AST file. - Deserializing AnASTFile(this); - - // Bump the generation number. - unsigned PreviousGeneration = 0; - if (ContextObj) - PreviousGeneration = incrementGeneration(*ContextObj); - - unsigned NumModules = ModuleMgr.size(); - SmallVector<ImportedModule, 4> Loaded; - switch (ASTReadResult ReadResult = - ReadASTCore(FileName, Type, ImportLoc, - /*ImportedBy=*/nullptr, Loaded, 0, 0, - ASTFileSignature(), ClientLoadCapabilities)) { - case Failure: - case Missing: - case OutOfDate: - case VersionMismatch: - case ConfigurationMismatch: - case HadErrors: { - llvm::SmallPtrSet<ModuleFile *, 4> LoadedSet; - for (const ImportedModule &IM : Loaded) - LoadedSet.insert(IM.Mod); - - ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, LoadedSet, - PP.getLangOpts().Modules - ? &PP.getHeaderSearchInfo().getModuleMap() - : nullptr); - - // If we find that any modules are unusable, the global index is going - // to be out-of-date. Just remove it. - GlobalIndex.reset(); - ModuleMgr.setGlobalIndex(nullptr); - return ReadResult; - } - case Success: - break; - } - - // Here comes stuff that we only do once the entire chain is loaded. - - // Load the AST blocks of all of the modules that we loaded. - for (SmallVectorImpl<ImportedModule>::iterator M = Loaded.begin(), - MEnd = Loaded.end(); - M != MEnd; ++M) { - ModuleFile &F = *M->Mod; - - // Read the AST block. - if (ASTReadResult Result = ReadASTBlock(F, ClientLoadCapabilities)) - return Result; - - // Read the extension blocks. - while (!SkipCursorToBlock(F.Stream, EXTENSION_BLOCK_ID)) { - if (ASTReadResult Result = ReadExtensionBlock(F)) - return Result; - } - - // Once read, set the ModuleFile bit base offset and update the size in - // bits of all files we've seen. - F.GlobalBitOffset = TotalModulesSizeInBits; - TotalModulesSizeInBits += F.SizeInBits; - GlobalBitOffsetsMap.insert(std::make_pair(F.GlobalBitOffset, &F)); - - // Preload SLocEntries. - for (unsigned I = 0, N = F.PreloadSLocEntries.size(); I != N; ++I) { - int Index = int(F.PreloadSLocEntries[I] - 1) + F.SLocEntryBaseID; - // Load it through the SourceManager and don't call ReadSLocEntry() - // directly because the entry may have already been loaded in which case - // calling ReadSLocEntry() directly would trigger an assertion in - // SourceManager. - SourceMgr.getLoadedSLocEntryByID(Index); - } - - // Map the original source file ID into the ID space of the current - // compilation. - if (F.OriginalSourceFileID.isValid()) { - F.OriginalSourceFileID = FileID::get( - F.SLocEntryBaseID + F.OriginalSourceFileID.getOpaqueValue() - 1); - } - - // Preload all the pending interesting identifiers by marking them out of - // date. - for (auto Offset : F.PreloadIdentifierOffsets) { - const unsigned char *Data = reinterpret_cast<const unsigned char *>( - F.IdentifierTableData + Offset); - - ASTIdentifierLookupTrait Trait(*this, F); - auto KeyDataLen = Trait.ReadKeyDataLength(Data); - auto Key = Trait.ReadKey(Data, KeyDataLen.first); - auto &II = PP.getIdentifierTable().getOwn(Key); - II.setOutOfDate(true); - - // Mark this identifier as being from an AST file so that we can track - // whether we need to serialize it. - markIdentifierFromAST(*this, II); - - // Associate the ID with the identifier so that the writer can reuse it. - auto ID = Trait.ReadIdentifierID(Data + KeyDataLen.first); - SetIdentifierInfo(ID, &II); - } - } - - // Setup the import locations and notify the module manager that we've - // committed to these module files. - for (SmallVectorImpl<ImportedModule>::iterator M = Loaded.begin(), - MEnd = Loaded.end(); - M != MEnd; ++M) { - ModuleFile &F = *M->Mod; - - ModuleMgr.moduleFileAccepted(&F); - - // Set the import location. - F.DirectImportLoc = ImportLoc; - // FIXME: We assume that locations from PCH / preamble do not need - // any translation. - if (!M->ImportedBy) - F.ImportLoc = M->ImportLoc; - else - F.ImportLoc = TranslateSourceLocation(*M->ImportedBy, M->ImportLoc); - } - - if (!PP.getLangOpts().CPlusPlus || - (Type != MK_ImplicitModule && Type != MK_ExplicitModule && - Type != MK_PrebuiltModule)) { - // Mark all of the identifiers in the identifier table as being out of date, - // so that various accessors know to check the loaded modules when the - // identifier is used. - // - // For C++ modules, we don't need information on many identifiers (just - // those that provide macros or are poisoned), so we mark all of - // the interesting ones via PreloadIdentifierOffsets. - for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(), - IdEnd = PP.getIdentifierTable().end(); - Id != IdEnd; ++Id) - Id->second->setOutOfDate(true); - } - // Mark selectors as out of date. - for (auto Sel : SelectorGeneration) - SelectorOutOfDate[Sel.first] = true; - - // Resolve any unresolved module exports. - for (unsigned I = 0, N = UnresolvedModuleRefs.size(); I != N; ++I) { - UnresolvedModuleRef &Unresolved = UnresolvedModuleRefs[I]; - SubmoduleID GlobalID = getGlobalSubmoduleID(*Unresolved.File,Unresolved.ID); - Module *ResolvedMod = getSubmodule(GlobalID); - - switch (Unresolved.Kind) { - case UnresolvedModuleRef::Conflict: - if (ResolvedMod) { - Module::Conflict Conflict; - Conflict.Other = ResolvedMod; - Conflict.Message = Unresolved.String.str(); - Unresolved.Mod->Conflicts.push_back(Conflict); - } - continue; - - case UnresolvedModuleRef::Import: - if (ResolvedMod) - Unresolved.Mod->Imports.insert(ResolvedMod); - continue; - - case UnresolvedModuleRef::Export: - if (ResolvedMod || Unresolved.IsWildcard) - Unresolved.Mod->Exports.push_back( - Module::ExportDecl(ResolvedMod, Unresolved.IsWildcard)); - continue; - } - } - UnresolvedModuleRefs.clear(); - - if (Imported) - Imported->append(ImportedModules.begin(), - ImportedModules.end()); - - // FIXME: How do we load the 'use'd modules? They may not be submodules. - // Might be unnecessary as use declarations are only used to build the - // module itself. - - if (ContextObj) - InitializeContext(); - - if (SemaObj) - UpdateSema(); - - if (DeserializationListener) - DeserializationListener->ReaderInitialized(this); - - ModuleFile &PrimaryModule = ModuleMgr.getPrimaryModule(); - if (PrimaryModule.OriginalSourceFileID.isValid()) { - // If this AST file is a precompiled preamble, then set the - // preamble file ID of the source manager to the file source file - // from which the preamble was built. - if (Type == MK_Preamble) { - SourceMgr.setPreambleFileID(PrimaryModule.OriginalSourceFileID); - } else if (Type == MK_MainFile) { - SourceMgr.setMainFileID(PrimaryModule.OriginalSourceFileID); - } - } - - // For any Objective-C class definitions we have already loaded, make sure - // that we load any additional categories. - if (ContextObj) { - for (unsigned I = 0, N = ObjCClassesLoaded.size(); I != N; ++I) { - loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(), - ObjCClassesLoaded[I], - PreviousGeneration); - } - } - - if (PP.getHeaderSearchInfo() - .getHeaderSearchOpts() - .ModulesValidateOncePerBuildSession) { - // Now we are certain that the module and all modules it depends on are - // up to date. Create or update timestamp files for modules that are - // located in the module cache (not for PCH files that could be anywhere - // in the filesystem). - for (unsigned I = 0, N = Loaded.size(); I != N; ++I) { - ImportedModule &M = Loaded[I]; - if (M.Mod->Kind == MK_ImplicitModule) { - updateModuleTimestamp(*M.Mod); - } - } - } - - return Success; -} - -static ASTFileSignature readASTFileSignature(StringRef PCH); - -/// Whether \p Stream starts with the AST/PCH file magic number 'CPCH'. -static bool startsWithASTFileMagic(BitstreamCursor &Stream) { - return Stream.canSkipToPos(4) && - Stream.Read(8) == 'C' && - Stream.Read(8) == 'P' && - Stream.Read(8) == 'C' && - Stream.Read(8) == 'H'; -} - -static unsigned moduleKindForDiagnostic(ModuleKind Kind) { - switch (Kind) { - case MK_PCH: - return 0; // PCH - case MK_ImplicitModule: - case MK_ExplicitModule: - case MK_PrebuiltModule: - return 1; // module - case MK_MainFile: - case MK_Preamble: - return 2; // main source file - } - llvm_unreachable("unknown module kind"); -} - -ASTReader::ASTReadResult -ASTReader::ReadASTCore(StringRef FileName, - ModuleKind Type, - SourceLocation ImportLoc, - ModuleFile *ImportedBy, - SmallVectorImpl<ImportedModule> &Loaded, - off_t ExpectedSize, time_t ExpectedModTime, - ASTFileSignature ExpectedSignature, - unsigned ClientLoadCapabilities) { - ModuleFile *M; - std::string ErrorStr; - ModuleManager::AddModuleResult AddResult - = ModuleMgr.addModule(FileName, Type, ImportLoc, ImportedBy, - getGeneration(), ExpectedSize, ExpectedModTime, - ExpectedSignature, readASTFileSignature, - M, ErrorStr); - - switch (AddResult) { - case ModuleManager::AlreadyLoaded: - return Success; - - case ModuleManager::NewlyLoaded: - // Load module file below. - break; - - case ModuleManager::Missing: - // The module file was missing; if the client can handle that, return - // it. - if (ClientLoadCapabilities & ARR_Missing) - return Missing; - - // Otherwise, return an error. - Diag(diag::err_module_file_not_found) << moduleKindForDiagnostic(Type) - << FileName << !ErrorStr.empty() - << ErrorStr; - return Failure; - - case ModuleManager::OutOfDate: - // We couldn't load the module file because it is out-of-date. If the - // client can handle out-of-date, return it. - if (ClientLoadCapabilities & ARR_OutOfDate) - return OutOfDate; - - // Otherwise, return an error. - Diag(diag::err_module_file_out_of_date) << moduleKindForDiagnostic(Type) - << FileName << !ErrorStr.empty() - << ErrorStr; - return Failure; - } - - assert(M && "Missing module file"); - - ModuleFile &F = *M; - BitstreamCursor &Stream = F.Stream; - Stream = BitstreamCursor(PCHContainerRdr.ExtractPCH(*F.Buffer)); - F.SizeInBits = F.Buffer->getBufferSize() * 8; - - // Sniff for the signature. - if (!startsWithASTFileMagic(Stream)) { - Diag(diag::err_module_file_invalid) << moduleKindForDiagnostic(Type) - << FileName; - return Failure; - } - - // This is used for compatibility with older PCH formats. - bool HaveReadControlBlock = false; - while (true) { - llvm::BitstreamEntry Entry = Stream.advance(); - - switch (Entry.Kind) { - case llvm::BitstreamEntry::Error: - case llvm::BitstreamEntry::Record: - case llvm::BitstreamEntry::EndBlock: - Error("invalid record at top-level of AST file"); - return Failure; - - case llvm::BitstreamEntry::SubBlock: - break; - } - - switch (Entry.ID) { - case CONTROL_BLOCK_ID: - HaveReadControlBlock = true; - switch (ReadControlBlock(F, Loaded, ImportedBy, ClientLoadCapabilities)) { - case Success: - // Check that we didn't try to load a non-module AST file as a module. - // - // FIXME: Should we also perform the converse check? Loading a module as - // a PCH file sort of works, but it's a bit wonky. - if ((Type == MK_ImplicitModule || Type == MK_ExplicitModule || - Type == MK_PrebuiltModule) && - F.ModuleName.empty()) { - auto Result = (Type == MK_ImplicitModule) ? OutOfDate : Failure; - if (Result != OutOfDate || - (ClientLoadCapabilities & ARR_OutOfDate) == 0) - Diag(diag::err_module_file_not_module) << FileName; - return Result; - } - break; - - case Failure: return Failure; - case Missing: return Missing; - case OutOfDate: return OutOfDate; - case VersionMismatch: return VersionMismatch; - case ConfigurationMismatch: return ConfigurationMismatch; - case HadErrors: return HadErrors; - } - break; - - case AST_BLOCK_ID: - if (!HaveReadControlBlock) { - if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0) - Diag(diag::err_pch_version_too_old); - return VersionMismatch; - } - - // Record that we've loaded this module. - Loaded.push_back(ImportedModule(M, ImportedBy, ImportLoc)); - return Success; - - case UNHASHED_CONTROL_BLOCK_ID: - // This block is handled using look-ahead during ReadControlBlock. We - // shouldn't get here! - Error("malformed block record in AST file"); - return Failure; - - default: - if (Stream.SkipBlock()) { - Error("malformed block record in AST file"); - return Failure; - } - break; - } - } - - return Success; -} - -ASTReader::ASTReadResult -ASTReader::readUnhashedControlBlock(ModuleFile &F, bool WasImportedBy, - unsigned ClientLoadCapabilities) { - const HeaderSearchOptions &HSOpts = - PP.getHeaderSearchInfo().getHeaderSearchOpts(); - bool AllowCompatibleConfigurationMismatch = - F.Kind == MK_ExplicitModule || F.Kind == MK_PrebuiltModule; - - ASTReadResult Result = readUnhashedControlBlockImpl( - &F, F.Data, ClientLoadCapabilities, AllowCompatibleConfigurationMismatch, - Listener.get(), - WasImportedBy ? false : HSOpts.ModulesValidateDiagnosticOptions); - - // If F was directly imported by another module, it's implicitly validated by - // the importing module. - if (DisableValidation || WasImportedBy || - (AllowConfigurationMismatch && Result == ConfigurationMismatch)) - return Success; - - if (Result == Failure) { - Error("malformed block record in AST file"); - return Failure; - } - - if (Result == OutOfDate && F.Kind == MK_ImplicitModule) { - // If this module has already been finalized in the PCMCache, we're stuck - // with it; we can only load a single version of each module. - // - // This can happen when a module is imported in two contexts: in one, as a - // user module; in another, as a system module (due to an import from - // another module marked with the [system] flag). It usually indicates a - // bug in the module map: this module should also be marked with [system]. - // - // If -Wno-system-headers (the default), and the first import is as a - // system module, then validation will fail during the as-user import, - // since -Werror flags won't have been validated. However, it's reasonable - // to treat this consistently as a system module. - // - // If -Wsystem-headers, the PCM on disk was built with - // -Wno-system-headers, and the first import is as a user module, then - // validation will fail during the as-system import since the PCM on disk - // doesn't guarantee that -Werror was respected. However, the -Werror - // flags were checked during the initial as-user import. - if (PCMCache.isBufferFinal(F.FileName)) { - Diag(diag::warn_module_system_bit_conflict) << F.FileName; - return Success; - } - } - - return Result; -} - -ASTReader::ASTReadResult ASTReader::readUnhashedControlBlockImpl( - ModuleFile *F, llvm::StringRef StreamData, unsigned ClientLoadCapabilities, - bool AllowCompatibleConfigurationMismatch, ASTReaderListener *Listener, - bool ValidateDiagnosticOptions) { - // Initialize a stream. - BitstreamCursor Stream(StreamData); - - // Sniff for the signature. - if (!startsWithASTFileMagic(Stream)) - return Failure; - - // Scan for the UNHASHED_CONTROL_BLOCK_ID block. - if (SkipCursorToBlock(Stream, UNHASHED_CONTROL_BLOCK_ID)) - return Failure; - - // Read all of the records in the options block. - RecordData Record; - ASTReadResult Result = Success; - while (true) { - llvm::BitstreamEntry Entry = Stream.advance(); - - switch (Entry.Kind) { - case llvm::BitstreamEntry::Error: - case llvm::BitstreamEntry::SubBlock: - return Failure; - - case llvm::BitstreamEntry::EndBlock: - return Result; - - case llvm::BitstreamEntry::Record: - // The interesting case. - break; - } - - // Read and process a record. - Record.clear(); - switch ( - (UnhashedControlBlockRecordTypes)Stream.readRecord(Entry.ID, Record)) { - case SIGNATURE: - if (F) - std::copy(Record.begin(), Record.end(), F->Signature.data()); - break; - case DIAGNOSTIC_OPTIONS: { - bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0; - if (Listener && ValidateDiagnosticOptions && - !AllowCompatibleConfigurationMismatch && - ParseDiagnosticOptions(Record, Complain, *Listener)) - Result = OutOfDate; // Don't return early. Read the signature. - break; - } - case DIAG_PRAGMA_MAPPINGS: - if (!F) - break; - if (F->PragmaDiagMappings.empty()) - F->PragmaDiagMappings.swap(Record); - else - F->PragmaDiagMappings.insert(F->PragmaDiagMappings.end(), - Record.begin(), Record.end()); - break; - } - } -} - -/// Parse a record and blob containing module file extension metadata. -static bool parseModuleFileExtensionMetadata( - const SmallVectorImpl<uint64_t> &Record, - StringRef Blob, - ModuleFileExtensionMetadata &Metadata) { - if (Record.size() < 4) return true; - - Metadata.MajorVersion = Record[0]; - Metadata.MinorVersion = Record[1]; - - unsigned BlockNameLen = Record[2]; - unsigned UserInfoLen = Record[3]; - - if (BlockNameLen + UserInfoLen > Blob.size()) return true; - - Metadata.BlockName = std::string(Blob.data(), Blob.data() + BlockNameLen); - Metadata.UserInfo = std::string(Blob.data() + BlockNameLen, - Blob.data() + BlockNameLen + UserInfoLen); - return false; -} - -ASTReader::ASTReadResult ASTReader::ReadExtensionBlock(ModuleFile &F) { - BitstreamCursor &Stream = F.Stream; - - RecordData Record; - while (true) { - llvm::BitstreamEntry Entry = Stream.advance(); - switch (Entry.Kind) { - case llvm::BitstreamEntry::SubBlock: - if (Stream.SkipBlock()) - return Failure; - - continue; - - case llvm::BitstreamEntry::EndBlock: - return Success; - - case llvm::BitstreamEntry::Error: - return HadErrors; - - case llvm::BitstreamEntry::Record: - break; - } - - Record.clear(); - StringRef Blob; - unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob); - switch (RecCode) { - case EXTENSION_METADATA: { - ModuleFileExtensionMetadata Metadata; - if (parseModuleFileExtensionMetadata(Record, Blob, Metadata)) - return Failure; - - // Find a module file extension with this block name. - auto Known = ModuleFileExtensions.find(Metadata.BlockName); - if (Known == ModuleFileExtensions.end()) break; - - // Form a reader. - if (auto Reader = Known->second->createExtensionReader(Metadata, *this, - F, Stream)) { - F.ExtensionReaders.push_back(std::move(Reader)); - } - - break; - } - } - } - - return Success; -} - -void ASTReader::InitializeContext() { - assert(ContextObj && "no context to initialize"); - ASTContext &Context = *ContextObj; - - // If there's a listener, notify them that we "read" the translation unit. - if (DeserializationListener) - DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID, - Context.getTranslationUnitDecl()); - - // FIXME: Find a better way to deal with collisions between these - // built-in types. Right now, we just ignore the problem. - - // Load the special types. - if (SpecialTypes.size() >= NumSpecialTypeIDs) { - if (unsigned String = SpecialTypes[SPECIAL_TYPE_CF_CONSTANT_STRING]) { - if (!Context.CFConstantStringTypeDecl) - Context.setCFConstantStringType(GetType(String)); - } - - if (unsigned File = SpecialTypes[SPECIAL_TYPE_FILE]) { - QualType FileType = GetType(File); - if (FileType.isNull()) { - Error("FILE type is NULL"); - return; - } - - if (!Context.FILEDecl) { - if (const TypedefType *Typedef = FileType->getAs<TypedefType>()) - Context.setFILEDecl(Typedef->getDecl()); - else { - const TagType *Tag = FileType->getAs<TagType>(); - if (!Tag) { - Error("Invalid FILE type in AST file"); - return; - } - Context.setFILEDecl(Tag->getDecl()); - } - } - } - - if (unsigned Jmp_buf = SpecialTypes[SPECIAL_TYPE_JMP_BUF]) { - QualType Jmp_bufType = GetType(Jmp_buf); - if (Jmp_bufType.isNull()) { - Error("jmp_buf type is NULL"); - return; - } - - if (!Context.jmp_bufDecl) { - if (const TypedefType *Typedef = Jmp_bufType->getAs<TypedefType>()) - Context.setjmp_bufDecl(Typedef->getDecl()); - else { - const TagType *Tag = Jmp_bufType->getAs<TagType>(); - if (!Tag) { - Error("Invalid jmp_buf type in AST file"); - return; - } - Context.setjmp_bufDecl(Tag->getDecl()); - } - } - } - - if (unsigned Sigjmp_buf = SpecialTypes[SPECIAL_TYPE_SIGJMP_BUF]) { - QualType Sigjmp_bufType = GetType(Sigjmp_buf); - if (Sigjmp_bufType.isNull()) { - Error("sigjmp_buf type is NULL"); - return; - } - - if (!Context.sigjmp_bufDecl) { - if (const TypedefType *Typedef = Sigjmp_bufType->getAs<TypedefType>()) - Context.setsigjmp_bufDecl(Typedef->getDecl()); - else { - const TagType *Tag = Sigjmp_bufType->getAs<TagType>(); - assert(Tag && "Invalid sigjmp_buf type in AST file"); - Context.setsigjmp_bufDecl(Tag->getDecl()); - } - } - } - - if (unsigned ObjCIdRedef - = SpecialTypes[SPECIAL_TYPE_OBJC_ID_REDEFINITION]) { - if (Context.ObjCIdRedefinitionType.isNull()) - Context.ObjCIdRedefinitionType = GetType(ObjCIdRedef); - } - - if (unsigned ObjCClassRedef - = SpecialTypes[SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) { - if (Context.ObjCClassRedefinitionType.isNull()) - Context.ObjCClassRedefinitionType = GetType(ObjCClassRedef); - } - - if (unsigned ObjCSelRedef - = SpecialTypes[SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) { - if (Context.ObjCSelRedefinitionType.isNull()) - Context.ObjCSelRedefinitionType = GetType(ObjCSelRedef); - } - - if (unsigned Ucontext_t = SpecialTypes[SPECIAL_TYPE_UCONTEXT_T]) { - QualType Ucontext_tType = GetType(Ucontext_t); - if (Ucontext_tType.isNull()) { - Error("ucontext_t type is NULL"); - return; - } - - if (!Context.ucontext_tDecl) { - if (const TypedefType *Typedef = Ucontext_tType->getAs<TypedefType>()) - Context.setucontext_tDecl(Typedef->getDecl()); - else { - const TagType *Tag = Ucontext_tType->getAs<TagType>(); - assert(Tag && "Invalid ucontext_t type in AST file"); - Context.setucontext_tDecl(Tag->getDecl()); - } - } - } - } - - ReadPragmaDiagnosticMappings(Context.getDiagnostics()); - - // If there were any CUDA special declarations, deserialize them. - if (!CUDASpecialDeclRefs.empty()) { - assert(CUDASpecialDeclRefs.size() == 1 && "More decl refs than expected!"); - Context.setcudaConfigureCallDecl( - cast<FunctionDecl>(GetDecl(CUDASpecialDeclRefs[0]))); - } - - // Re-export any modules that were imported by a non-module AST file. - // FIXME: This does not make macro-only imports visible again. - for (auto &Import : ImportedModules) { - if (Module *Imported = getSubmodule(Import.ID)) { - makeModuleVisible(Imported, Module::AllVisible, - /*ImportLoc=*/Import.ImportLoc); - if (Import.ImportLoc.isValid()) - PP.makeModuleVisible(Imported, Import.ImportLoc); - // FIXME: should we tell Sema to make the module visible too? - } - } - ImportedModules.clear(); -} - -void ASTReader::finalizeForWriting() { - // Nothing to do for now. -} - -/// Reads and return the signature record from \p PCH's control block, or -/// else returns 0. -static ASTFileSignature readASTFileSignature(StringRef PCH) { - BitstreamCursor Stream(PCH); - if (!startsWithASTFileMagic(Stream)) - return ASTFileSignature(); - - // Scan for the UNHASHED_CONTROL_BLOCK_ID block. - if (SkipCursorToBlock(Stream, UNHASHED_CONTROL_BLOCK_ID)) - return ASTFileSignature(); - - // Scan for SIGNATURE inside the diagnostic options block. - ASTReader::RecordData Record; - while (true) { - llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); - if (Entry.Kind != llvm::BitstreamEntry::Record) - return ASTFileSignature(); - - Record.clear(); - StringRef Blob; - if (SIGNATURE == Stream.readRecord(Entry.ID, Record, &Blob)) - return {{{(uint32_t)Record[0], (uint32_t)Record[1], (uint32_t)Record[2], - (uint32_t)Record[3], (uint32_t)Record[4]}}}; - } -} - -/// Retrieve the name of the original source file name -/// directly from the AST file, without actually loading the AST -/// file. -std::string ASTReader::getOriginalSourceFile( - const std::string &ASTFileName, FileManager &FileMgr, - const PCHContainerReader &PCHContainerRdr, DiagnosticsEngine &Diags) { - // Open the AST file. - auto Buffer = FileMgr.getBufferForFile(ASTFileName); - if (!Buffer) { - Diags.Report(diag::err_fe_unable_to_read_pch_file) - << ASTFileName << Buffer.getError().message(); - return std::string(); - } - - // Initialize the stream - BitstreamCursor Stream(PCHContainerRdr.ExtractPCH(**Buffer)); - - // Sniff for the signature. - if (!startsWithASTFileMagic(Stream)) { - Diags.Report(diag::err_fe_not_a_pch_file) << ASTFileName; - return std::string(); - } - - // Scan for the CONTROL_BLOCK_ID block. - if (SkipCursorToBlock(Stream, CONTROL_BLOCK_ID)) { - Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName; - return std::string(); - } - - // Scan for ORIGINAL_FILE inside the control block. - RecordData Record; - while (true) { - llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); - if (Entry.Kind == llvm::BitstreamEntry::EndBlock) - return std::string(); - - if (Entry.Kind != llvm::BitstreamEntry::Record) { - Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName; - return std::string(); - } - - Record.clear(); - StringRef Blob; - if (Stream.readRecord(Entry.ID, Record, &Blob) == ORIGINAL_FILE) - return Blob.str(); - } -} - -namespace { - - class SimplePCHValidator : public ASTReaderListener { - const LangOptions &ExistingLangOpts; - const TargetOptions &ExistingTargetOpts; - const PreprocessorOptions &ExistingPPOpts; - std::string ExistingModuleCachePath; - FileManager &FileMgr; - - public: - SimplePCHValidator(const LangOptions &ExistingLangOpts, - const TargetOptions &ExistingTargetOpts, - const PreprocessorOptions &ExistingPPOpts, - StringRef ExistingModuleCachePath, - FileManager &FileMgr) - : ExistingLangOpts(ExistingLangOpts), - ExistingTargetOpts(ExistingTargetOpts), - ExistingPPOpts(ExistingPPOpts), - ExistingModuleCachePath(ExistingModuleCachePath), - FileMgr(FileMgr) {} - - bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain, - bool AllowCompatibleDifferences) override { - return checkLanguageOptions(ExistingLangOpts, LangOpts, nullptr, - AllowCompatibleDifferences); - } - - bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain, - bool AllowCompatibleDifferences) override { - return checkTargetOptions(ExistingTargetOpts, TargetOpts, nullptr, - AllowCompatibleDifferences); - } - - bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, - StringRef SpecificModuleCachePath, - bool Complain) override { - return checkHeaderSearchOptions(HSOpts, SpecificModuleCachePath, - ExistingModuleCachePath, - nullptr, ExistingLangOpts); - } - - bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, - bool Complain, - std::string &SuggestedPredefines) override { - return checkPreprocessorOptions(ExistingPPOpts, PPOpts, nullptr, FileMgr, - SuggestedPredefines, ExistingLangOpts); - } - }; - -} // namespace - -bool ASTReader::readASTFileControlBlock( - StringRef Filename, FileManager &FileMgr, - const PCHContainerReader &PCHContainerRdr, - bool FindModuleFileExtensions, - ASTReaderListener &Listener, bool ValidateDiagnosticOptions) { - // Open the AST file. - // FIXME: This allows use of the VFS; we do not allow use of the - // VFS when actually loading a module. - auto Buffer = FileMgr.getBufferForFile(Filename); - if (!Buffer) { - return true; - } - - // Initialize the stream - StringRef Bytes = PCHContainerRdr.ExtractPCH(**Buffer); - BitstreamCursor Stream(Bytes); - - // Sniff for the signature. - if (!startsWithASTFileMagic(Stream)) - return true; - - // Scan for the CONTROL_BLOCK_ID block. - if (SkipCursorToBlock(Stream, CONTROL_BLOCK_ID)) - return true; - - bool NeedsInputFiles = Listener.needsInputFileVisitation(); - bool NeedsSystemInputFiles = Listener.needsSystemInputFileVisitation(); - bool NeedsImports = Listener.needsImportVisitation(); - BitstreamCursor InputFilesCursor; - - RecordData Record; - std::string ModuleDir; - bool DoneWithControlBlock = false; - while (!DoneWithControlBlock) { - llvm::BitstreamEntry Entry = Stream.advance(); - - switch (Entry.Kind) { - case llvm::BitstreamEntry::SubBlock: { - switch (Entry.ID) { - case OPTIONS_BLOCK_ID: { - std::string IgnoredSuggestedPredefines; - if (ReadOptionsBlock(Stream, ARR_ConfigurationMismatch | ARR_OutOfDate, - /*AllowCompatibleConfigurationMismatch*/ false, - Listener, IgnoredSuggestedPredefines) != Success) - return true; - break; - } - - case INPUT_FILES_BLOCK_ID: - InputFilesCursor = Stream; - if (Stream.SkipBlock() || - (NeedsInputFiles && - ReadBlockAbbrevs(InputFilesCursor, INPUT_FILES_BLOCK_ID))) - return true; - break; - - default: - if (Stream.SkipBlock()) - return true; - break; - } - - continue; - } - - case llvm::BitstreamEntry::EndBlock: - DoneWithControlBlock = true; - break; - - case llvm::BitstreamEntry::Error: - return true; - - case llvm::BitstreamEntry::Record: - break; - } - - if (DoneWithControlBlock) break; - - Record.clear(); - StringRef Blob; - unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob); - switch ((ControlRecordTypes)RecCode) { - case METADATA: - if (Record[0] != VERSION_MAJOR) - return true; - if (Listener.ReadFullVersionInformation(Blob)) - return true; - break; - case MODULE_NAME: - Listener.ReadModuleName(Blob); - break; - case MODULE_DIRECTORY: - ModuleDir = Blob; - break; - case MODULE_MAP_FILE: { - unsigned Idx = 0; - auto Path = ReadString(Record, Idx); - ResolveImportedPath(Path, ModuleDir); - Listener.ReadModuleMapFile(Path); - break; - } - case INPUT_FILE_OFFSETS: { - if (!NeedsInputFiles) - break; - - unsigned NumInputFiles = Record[0]; - unsigned NumUserFiles = Record[1]; - const llvm::support::unaligned_uint64_t *InputFileOffs = - (const llvm::support::unaligned_uint64_t *)Blob.data(); - for (unsigned I = 0; I != NumInputFiles; ++I) { - // Go find this input file. - bool isSystemFile = I >= NumUserFiles; - - if (isSystemFile && !NeedsSystemInputFiles) - break; // the rest are system input files - - BitstreamCursor &Cursor = InputFilesCursor; - SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(InputFileOffs[I]); - - unsigned Code = Cursor.ReadCode(); - RecordData Record; - StringRef Blob; - bool shouldContinue = false; - switch ((InputFileRecordTypes)Cursor.readRecord(Code, Record, &Blob)) { - case INPUT_FILE: - bool Overridden = static_cast<bool>(Record[3]); - std::string Filename = Blob; - ResolveImportedPath(Filename, ModuleDir); - shouldContinue = Listener.visitInputFile( - Filename, isSystemFile, Overridden, /*IsExplicitModule*/false); - break; - } - if (!shouldContinue) - break; - } - break; - } - - case IMPORTS: { - if (!NeedsImports) - break; - - unsigned Idx = 0, N = Record.size(); - while (Idx < N) { - // Read information about the AST file. - Idx += 1+1+1+1+5; // Kind, ImportLoc, Size, ModTime, Signature - std::string ModuleName = ReadString(Record, Idx); - std::string Filename = ReadString(Record, Idx); - ResolveImportedPath(Filename, ModuleDir); - Listener.visitImport(ModuleName, Filename); - } - break; - } - - default: - // No other validation to perform. - break; - } - } - - // Look for module file extension blocks, if requested. - if (FindModuleFileExtensions) { - BitstreamCursor SavedStream = Stream; - while (!SkipCursorToBlock(Stream, EXTENSION_BLOCK_ID)) { - bool DoneWithExtensionBlock = false; - while (!DoneWithExtensionBlock) { - llvm::BitstreamEntry Entry = Stream.advance(); - - switch (Entry.Kind) { - case llvm::BitstreamEntry::SubBlock: - if (Stream.SkipBlock()) - return true; - - continue; - - case llvm::BitstreamEntry::EndBlock: - DoneWithExtensionBlock = true; - continue; - - case llvm::BitstreamEntry::Error: - return true; - - case llvm::BitstreamEntry::Record: - break; - } - - Record.clear(); - StringRef Blob; - unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob); - switch (RecCode) { - case EXTENSION_METADATA: { - ModuleFileExtensionMetadata Metadata; - if (parseModuleFileExtensionMetadata(Record, Blob, Metadata)) - return true; - - Listener.readModuleFileExtension(Metadata); - break; - } - } - } - } - Stream = SavedStream; - } - - // Scan for the UNHASHED_CONTROL_BLOCK_ID block. - if (readUnhashedControlBlockImpl( - nullptr, Bytes, ARR_ConfigurationMismatch | ARR_OutOfDate, - /*AllowCompatibleConfigurationMismatch*/ false, &Listener, - ValidateDiagnosticOptions) != Success) - return true; - - return false; -} - -bool ASTReader::isAcceptableASTFile(StringRef Filename, FileManager &FileMgr, - const PCHContainerReader &PCHContainerRdr, - const LangOptions &LangOpts, - const TargetOptions &TargetOpts, - const PreprocessorOptions &PPOpts, - StringRef ExistingModuleCachePath) { - SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, - ExistingModuleCachePath, FileMgr); - return !readASTFileControlBlock(Filename, FileMgr, PCHContainerRdr, - /*FindModuleFileExtensions=*/false, - validator, - /*ValidateDiagnosticOptions=*/true); -} - -ASTReader::ASTReadResult -ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { - // Enter the submodule block. - if (F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) { - Error("malformed submodule block record in AST file"); - return Failure; - } - - ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap(); - bool First = true; - Module *CurrentModule = nullptr; - RecordData Record; - while (true) { - llvm::BitstreamEntry Entry = F.Stream.advanceSkippingSubblocks(); - - switch (Entry.Kind) { - case llvm::BitstreamEntry::SubBlock: // Handled for us already. - case llvm::BitstreamEntry::Error: - Error("malformed block record in AST file"); - return Failure; - case llvm::BitstreamEntry::EndBlock: - return Success; - case llvm::BitstreamEntry::Record: - // The interesting case. - break; - } - - // Read a record. - StringRef Blob; - Record.clear(); - auto Kind = F.Stream.readRecord(Entry.ID, Record, &Blob); - - if ((Kind == SUBMODULE_METADATA) != First) { - Error("submodule metadata record should be at beginning of block"); - return Failure; - } - First = false; - - // Submodule information is only valid if we have a current module. - // FIXME: Should we error on these cases? - if (!CurrentModule && Kind != SUBMODULE_METADATA && - Kind != SUBMODULE_DEFINITION) - continue; - - switch (Kind) { - default: // Default behavior: ignore. - break; - - case SUBMODULE_DEFINITION: { - if (Record.size() < 12) { - Error("malformed module definition"); - return Failure; - } - - StringRef Name = Blob; - unsigned Idx = 0; - SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[Idx++]); - SubmoduleID Parent = getGlobalSubmoduleID(F, Record[Idx++]); - Module::ModuleKind Kind = (Module::ModuleKind)Record[Idx++]; - bool IsFramework = Record[Idx++]; - bool IsExplicit = Record[Idx++]; - bool IsSystem = Record[Idx++]; - bool IsExternC = Record[Idx++]; - bool InferSubmodules = Record[Idx++]; - bool InferExplicitSubmodules = Record[Idx++]; - bool InferExportWildcard = Record[Idx++]; - bool ConfigMacrosExhaustive = Record[Idx++]; - bool ModuleMapIsPrivate = Record[Idx++]; - - Module *ParentModule = nullptr; - if (Parent) - ParentModule = getSubmodule(Parent); - - // Retrieve this (sub)module from the module map, creating it if - // necessary. - CurrentModule = - ModMap.findOrCreateModule(Name, ParentModule, IsFramework, IsExplicit) - .first; - - // FIXME: set the definition loc for CurrentModule, or call - // ModMap.setInferredModuleAllowedBy() - - SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS; - if (GlobalIndex >= SubmodulesLoaded.size() || - SubmodulesLoaded[GlobalIndex]) { - Error("too many submodules"); - return Failure; - } - - if (!ParentModule) { - if (const FileEntry *CurFile = CurrentModule->getASTFile()) { - // Don't emit module relocation error if we have -fno-validate-pch - if (!PP.getPreprocessorOpts().DisablePCHValidation && - CurFile != F.File) { - if (!Diags.isDiagnosticInFlight()) { - Diag(diag::err_module_file_conflict) - << CurrentModule->getTopLevelModuleName() - << CurFile->getName() - << F.File->getName(); - } - return Failure; - } - } - - CurrentModule->setASTFile(F.File); - CurrentModule->PresumedModuleMapFile = F.ModuleMapPath; - } - - CurrentModule->Kind = Kind; - CurrentModule->Signature = F.Signature; - CurrentModule->IsFromModuleFile = true; - CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem; - CurrentModule->IsExternC = IsExternC; - CurrentModule->InferSubmodules = InferSubmodules; - CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules; - CurrentModule->InferExportWildcard = InferExportWildcard; - CurrentModule->ConfigMacrosExhaustive = ConfigMacrosExhaustive; - CurrentModule->ModuleMapIsPrivate = ModuleMapIsPrivate; - if (DeserializationListener) - DeserializationListener->ModuleRead(GlobalID, CurrentModule); - - SubmodulesLoaded[GlobalIndex] = CurrentModule; - - // Clear out data that will be replaced by what is in the module file. - CurrentModule->LinkLibraries.clear(); - CurrentModule->ConfigMacros.clear(); - CurrentModule->UnresolvedConflicts.clear(); - CurrentModule->Conflicts.clear(); - - // The module is available unless it's missing a requirement; relevant - // requirements will be (re-)added by SUBMODULE_REQUIRES records. - // Missing headers that were present when the module was built do not - // make it unavailable -- if we got this far, this must be an explicitly - // imported module file. - CurrentModule->Requirements.clear(); - CurrentModule->MissingHeaders.clear(); - CurrentModule->IsMissingRequirement = - ParentModule && ParentModule->IsMissingRequirement; - CurrentModule->IsAvailable = !CurrentModule->IsMissingRequirement; - break; - } - - case SUBMODULE_UMBRELLA_HEADER: { - std::string Filename = Blob; - ResolveImportedPath(F, Filename); - if (auto *Umbrella = PP.getFileManager().getFile(Filename)) { - if (!CurrentModule->getUmbrellaHeader()) - ModMap.setUmbrellaHeader(CurrentModule, Umbrella, Blob); - else if (CurrentModule->getUmbrellaHeader().Entry != Umbrella) { - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) - Error("mismatched umbrella headers in submodule"); - return OutOfDate; - } - } - break; - } - - case SUBMODULE_HEADER: - case SUBMODULE_EXCLUDED_HEADER: - case SUBMODULE_PRIVATE_HEADER: - // We lazily associate headers with their modules via the HeaderInfo table. - // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead - // of complete filenames or remove it entirely. - break; - - case SUBMODULE_TEXTUAL_HEADER: - case SUBMODULE_PRIVATE_TEXTUAL_HEADER: - // FIXME: Textual headers are not marked in the HeaderInfo table. Load - // them here. - break; - - case SUBMODULE_TOPHEADER: - CurrentModule->addTopHeaderFilename(Blob); - break; - - case SUBMODULE_UMBRELLA_DIR: { - std::string Dirname = Blob; - ResolveImportedPath(F, Dirname); - if (auto *Umbrella = PP.getFileManager().getDirectory(Dirname)) { - if (!CurrentModule->getUmbrellaDir()) - ModMap.setUmbrellaDir(CurrentModule, Umbrella, Blob); - else if (CurrentModule->getUmbrellaDir().Entry != Umbrella) { - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) - Error("mismatched umbrella directories in submodule"); - return OutOfDate; - } - } - break; - } - - case SUBMODULE_METADATA: { - F.BaseSubmoduleID = getTotalNumSubmodules(); - F.LocalNumSubmodules = Record[0]; - unsigned LocalBaseSubmoduleID = Record[1]; - if (F.LocalNumSubmodules > 0) { - // Introduce the global -> local mapping for submodules within this - // module. - GlobalSubmoduleMap.insert(std::make_pair(getTotalNumSubmodules()+1,&F)); - - // Introduce the local -> global mapping for submodules within this - // module. - F.SubmoduleRemap.insertOrReplace( - std::make_pair(LocalBaseSubmoduleID, - F.BaseSubmoduleID - LocalBaseSubmoduleID)); - - SubmodulesLoaded.resize(SubmodulesLoaded.size() + F.LocalNumSubmodules); - } - break; - } - - case SUBMODULE_IMPORTS: - for (unsigned Idx = 0; Idx != Record.size(); ++Idx) { - UnresolvedModuleRef Unresolved; - Unresolved.File = &F; - Unresolved.Mod = CurrentModule; - Unresolved.ID = Record[Idx]; - Unresolved.Kind = UnresolvedModuleRef::Import; - Unresolved.IsWildcard = false; - UnresolvedModuleRefs.push_back(Unresolved); - } - break; - - case SUBMODULE_EXPORTS: - for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { - UnresolvedModuleRef Unresolved; - Unresolved.File = &F; - Unresolved.Mod = CurrentModule; - Unresolved.ID = Record[Idx]; - Unresolved.Kind = UnresolvedModuleRef::Export; - Unresolved.IsWildcard = Record[Idx + 1]; - UnresolvedModuleRefs.push_back(Unresolved); - } - - // Once we've loaded the set of exports, there's no reason to keep - // the parsed, unresolved exports around. - CurrentModule->UnresolvedExports.clear(); - break; - - case SUBMODULE_REQUIRES: - CurrentModule->addRequirement(Blob, Record[0], PP.getLangOpts(), - PP.getTargetInfo()); - break; - - case SUBMODULE_LINK_LIBRARY: - ModMap.resolveLinkAsDependencies(CurrentModule); - CurrentModule->LinkLibraries.push_back( - Module::LinkLibrary(Blob, Record[0])); - break; - - case SUBMODULE_CONFIG_MACRO: - CurrentModule->ConfigMacros.push_back(Blob.str()); - break; - - case SUBMODULE_CONFLICT: { - UnresolvedModuleRef Unresolved; - Unresolved.File = &F; - Unresolved.Mod = CurrentModule; - Unresolved.ID = Record[0]; - Unresolved.Kind = UnresolvedModuleRef::Conflict; - Unresolved.IsWildcard = false; - Unresolved.String = Blob; - UnresolvedModuleRefs.push_back(Unresolved); - break; - } - - case SUBMODULE_INITIALIZERS: { - if (!ContextObj) - break; - SmallVector<uint32_t, 16> Inits; - for (auto &ID : Record) - Inits.push_back(getGlobalDeclID(F, ID)); - ContextObj->addLazyModuleInitializers(CurrentModule, Inits); - break; - } - - case SUBMODULE_EXPORT_AS: - CurrentModule->ExportAsModule = Blob.str(); - ModMap.addLinkAsDependency(CurrentModule); - break; - } - } -} - -/// Parse the record that corresponds to a LangOptions data -/// structure. -/// -/// This routine parses the language options from the AST file and then gives -/// them to the AST listener if one is set. -/// -/// \returns true if the listener deems the file unacceptable, false otherwise. -bool ASTReader::ParseLanguageOptions(const RecordData &Record, - bool Complain, - ASTReaderListener &Listener, - bool AllowCompatibleDifferences) { - LangOptions LangOpts; - unsigned Idx = 0; -#define LANGOPT(Name, Bits, Default, Description) \ - LangOpts.Name = Record[Idx++]; -#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ - LangOpts.set##Name(static_cast<LangOptions::Type>(Record[Idx++])); -#include "clang/Basic/LangOptions.def" -#define SANITIZER(NAME, ID) \ - LangOpts.Sanitize.set(SanitizerKind::ID, Record[Idx++]); -#include "clang/Basic/Sanitizers.def" - - for (unsigned N = Record[Idx++]; N; --N) - LangOpts.ModuleFeatures.push_back(ReadString(Record, Idx)); - - ObjCRuntime::Kind runtimeKind = (ObjCRuntime::Kind) Record[Idx++]; - VersionTuple runtimeVersion = ReadVersionTuple(Record, Idx); - LangOpts.ObjCRuntime = ObjCRuntime(runtimeKind, runtimeVersion); - - LangOpts.CurrentModule = ReadString(Record, Idx); - - // Comment options. - for (unsigned N = Record[Idx++]; N; --N) { - LangOpts.CommentOpts.BlockCommandNames.push_back( - ReadString(Record, Idx)); - } - LangOpts.CommentOpts.ParseAllComments = Record[Idx++]; - - // OpenMP offloading options. - for (unsigned N = Record[Idx++]; N; --N) { - LangOpts.OMPTargetTriples.push_back(llvm::Triple(ReadString(Record, Idx))); - } - - LangOpts.OMPHostIRFile = ReadString(Record, Idx); - - return Listener.ReadLanguageOptions(LangOpts, Complain, - AllowCompatibleDifferences); -} - -bool ASTReader::ParseTargetOptions(const RecordData &Record, bool Complain, - ASTReaderListener &Listener, - bool AllowCompatibleDifferences) { - unsigned Idx = 0; - TargetOptions TargetOpts; - TargetOpts.Triple = ReadString(Record, Idx); - TargetOpts.CPU = ReadString(Record, Idx); - TargetOpts.ABI = ReadString(Record, Idx); - for (unsigned N = Record[Idx++]; N; --N) { - TargetOpts.FeaturesAsWritten.push_back(ReadString(Record, Idx)); - } - for (unsigned N = Record[Idx++]; N; --N) { - TargetOpts.Features.push_back(ReadString(Record, Idx)); - } - - return Listener.ReadTargetOptions(TargetOpts, Complain, - AllowCompatibleDifferences); -} - -bool ASTReader::ParseDiagnosticOptions(const RecordData &Record, bool Complain, - ASTReaderListener &Listener) { - IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions); - unsigned Idx = 0; -#define DIAGOPT(Name, Bits, Default) DiagOpts->Name = Record[Idx++]; -#define ENUM_DIAGOPT(Name, Type, Bits, Default) \ - DiagOpts->set##Name(static_cast<Type>(Record[Idx++])); -#include "clang/Basic/DiagnosticOptions.def" - - for (unsigned N = Record[Idx++]; N; --N) - DiagOpts->Warnings.push_back(ReadString(Record, Idx)); - for (unsigned N = Record[Idx++]; N; --N) - DiagOpts->Remarks.push_back(ReadString(Record, Idx)); - - return Listener.ReadDiagnosticOptions(DiagOpts, Complain); -} - -bool ASTReader::ParseFileSystemOptions(const RecordData &Record, bool Complain, - ASTReaderListener &Listener) { - FileSystemOptions FSOpts; - unsigned Idx = 0; - FSOpts.WorkingDir = ReadString(Record, Idx); - return Listener.ReadFileSystemOptions(FSOpts, Complain); -} - -bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record, - bool Complain, - ASTReaderListener &Listener) { - HeaderSearchOptions HSOpts; - unsigned Idx = 0; - HSOpts.Sysroot = ReadString(Record, Idx); - - // Include entries. - for (unsigned N = Record[Idx++]; N; --N) { - std::string Path = ReadString(Record, Idx); - frontend::IncludeDirGroup Group - = static_cast<frontend::IncludeDirGroup>(Record[Idx++]); - bool IsFramework = Record[Idx++]; - bool IgnoreSysRoot = Record[Idx++]; - HSOpts.UserEntries.emplace_back(std::move(Path), Group, IsFramework, - IgnoreSysRoot); - } - - // System header prefixes. - for (unsigned N = Record[Idx++]; N; --N) { - std::string Prefix = ReadString(Record, Idx); - bool IsSystemHeader = Record[Idx++]; - HSOpts.SystemHeaderPrefixes.emplace_back(std::move(Prefix), IsSystemHeader); - } - - HSOpts.ResourceDir = ReadString(Record, Idx); - HSOpts.ModuleCachePath = ReadString(Record, Idx); - HSOpts.ModuleUserBuildPath = ReadString(Record, Idx); - HSOpts.DisableModuleHash = Record[Idx++]; - HSOpts.ImplicitModuleMaps = Record[Idx++]; - HSOpts.ModuleMapFileHomeIsCwd = Record[Idx++]; - HSOpts.UseBuiltinIncludes = Record[Idx++]; - HSOpts.UseStandardSystemIncludes = Record[Idx++]; - HSOpts.UseStandardCXXIncludes = Record[Idx++]; - HSOpts.UseLibcxx = Record[Idx++]; - std::string SpecificModuleCachePath = ReadString(Record, Idx); - - return Listener.ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath, - Complain); -} - -bool ASTReader::ParsePreprocessorOptions(const RecordData &Record, - bool Complain, - ASTReaderListener &Listener, - std::string &SuggestedPredefines) { - PreprocessorOptions PPOpts; - unsigned Idx = 0; - - // Macro definitions/undefs - for (unsigned N = Record[Idx++]; N; --N) { - std::string Macro = ReadString(Record, Idx); - bool IsUndef = Record[Idx++]; - PPOpts.Macros.push_back(std::make_pair(Macro, IsUndef)); - } - - // Includes - for (unsigned N = Record[Idx++]; N; --N) { - PPOpts.Includes.push_back(ReadString(Record, Idx)); - } - - // Macro Includes - for (unsigned N = Record[Idx++]; N; --N) { - PPOpts.MacroIncludes.push_back(ReadString(Record, Idx)); - } - - PPOpts.UsePredefines = Record[Idx++]; - PPOpts.DetailedRecord = Record[Idx++]; - PPOpts.ImplicitPCHInclude = ReadString(Record, Idx); - PPOpts.ObjCXXARCStandardLibrary = - static_cast<ObjCXXARCStandardLibraryKind>(Record[Idx++]); - SuggestedPredefines.clear(); - return Listener.ReadPreprocessorOptions(PPOpts, Complain, - SuggestedPredefines); -} - -std::pair<ModuleFile *, unsigned> -ASTReader::getModulePreprocessedEntity(unsigned GlobalIndex) { - GlobalPreprocessedEntityMapType::iterator - I = GlobalPreprocessedEntityMap.find(GlobalIndex); - assert(I != GlobalPreprocessedEntityMap.end() && - "Corrupted global preprocessed entity map"); - ModuleFile *M = I->second; - unsigned LocalIndex = GlobalIndex - M->BasePreprocessedEntityID; - return std::make_pair(M, LocalIndex); -} - -llvm::iterator_range<PreprocessingRecord::iterator> -ASTReader::getModulePreprocessedEntities(ModuleFile &Mod) const { - if (PreprocessingRecord *PPRec = PP.getPreprocessingRecord()) - return PPRec->getIteratorsForLoadedRange(Mod.BasePreprocessedEntityID, - Mod.NumPreprocessedEntities); - - return llvm::make_range(PreprocessingRecord::iterator(), - PreprocessingRecord::iterator()); -} - -llvm::iterator_range<ASTReader::ModuleDeclIterator> -ASTReader::getModuleFileLevelDecls(ModuleFile &Mod) { - return llvm::make_range( - ModuleDeclIterator(this, &Mod, Mod.FileSortedDecls), - ModuleDeclIterator(this, &Mod, - Mod.FileSortedDecls + Mod.NumFileSortedDecls)); -} - -SourceRange ASTReader::ReadSkippedRange(unsigned GlobalIndex) { - auto I = GlobalSkippedRangeMap.find(GlobalIndex); - assert(I != GlobalSkippedRangeMap.end() && - "Corrupted global skipped range map"); - ModuleFile *M = I->second; - unsigned LocalIndex = GlobalIndex - M->BasePreprocessedSkippedRangeID; - assert(LocalIndex < M->NumPreprocessedSkippedRanges); - PPSkippedRange RawRange = M->PreprocessedSkippedRangeOffsets[LocalIndex]; - SourceRange Range(TranslateSourceLocation(*M, RawRange.getBegin()), - TranslateSourceLocation(*M, RawRange.getEnd())); - assert(Range.isValid()); - return Range; -} - -PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { - PreprocessedEntityID PPID = Index+1; - std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index); - ModuleFile &M = *PPInfo.first; - unsigned LocalIndex = PPInfo.second; - const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex]; - - if (!PP.getPreprocessingRecord()) { - Error("no preprocessing record"); - return nullptr; - } - - SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor); - M.PreprocessorDetailCursor.JumpToBit(PPOffs.BitOffset); - - llvm::BitstreamEntry Entry = - M.PreprocessorDetailCursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd); - if (Entry.Kind != llvm::BitstreamEntry::Record) - return nullptr; - - // Read the record. - SourceRange Range(TranslateSourceLocation(M, PPOffs.getBegin()), - TranslateSourceLocation(M, PPOffs.getEnd())); - PreprocessingRecord &PPRec = *PP.getPreprocessingRecord(); - StringRef Blob; - RecordData Record; - PreprocessorDetailRecordTypes RecType = - (PreprocessorDetailRecordTypes)M.PreprocessorDetailCursor.readRecord( - Entry.ID, Record, &Blob); - switch (RecType) { - case PPD_MACRO_EXPANSION: { - bool isBuiltin = Record[0]; - IdentifierInfo *Name = nullptr; - MacroDefinitionRecord *Def = nullptr; - if (isBuiltin) - Name = getLocalIdentifier(M, Record[1]); - else { - PreprocessedEntityID GlobalID = - getGlobalPreprocessedEntityID(M, Record[1]); - Def = cast<MacroDefinitionRecord>( - PPRec.getLoadedPreprocessedEntity(GlobalID - 1)); - } - - MacroExpansion *ME; - if (isBuiltin) - ME = new (PPRec) MacroExpansion(Name, Range); - else - ME = new (PPRec) MacroExpansion(Def, Range); - - return ME; - } - - case PPD_MACRO_DEFINITION: { - // Decode the identifier info and then check again; if the macro is - // still defined and associated with the identifier, - IdentifierInfo *II = getLocalIdentifier(M, Record[0]); - MacroDefinitionRecord *MD = new (PPRec) MacroDefinitionRecord(II, Range); - - if (DeserializationListener) - DeserializationListener->MacroDefinitionRead(PPID, MD); - - return MD; - } - - case PPD_INCLUSION_DIRECTIVE: { - const char *FullFileNameStart = Blob.data() + Record[0]; - StringRef FullFileName(FullFileNameStart, Blob.size() - Record[0]); - const FileEntry *File = nullptr; - if (!FullFileName.empty()) - File = PP.getFileManager().getFile(FullFileName); - - // FIXME: Stable encoding - InclusionDirective::InclusionKind Kind - = static_cast<InclusionDirective::InclusionKind>(Record[2]); - InclusionDirective *ID - = new (PPRec) InclusionDirective(PPRec, Kind, - StringRef(Blob.data(), Record[0]), - Record[1], Record[3], - File, - Range); - return ID; - } - } - - llvm_unreachable("Invalid PreprocessorDetailRecordTypes"); -} - -/// Find the next module that contains entities and return the ID -/// of the first entry. -/// -/// \param SLocMapI points at a chunk of a module that contains no -/// preprocessed entities or the entities it contains are not the ones we are -/// looking for. -PreprocessedEntityID ASTReader::findNextPreprocessedEntity( - GlobalSLocOffsetMapType::const_iterator SLocMapI) const { - ++SLocMapI; - for (GlobalSLocOffsetMapType::const_iterator - EndI = GlobalSLocOffsetMap.end(); SLocMapI != EndI; ++SLocMapI) { - ModuleFile &M = *SLocMapI->second; - if (M.NumPreprocessedEntities) - return M.BasePreprocessedEntityID; - } - - return getTotalNumPreprocessedEntities(); -} - -namespace { - -struct PPEntityComp { - const ASTReader &Reader; - ModuleFile &M; - - PPEntityComp(const ASTReader &Reader, ModuleFile &M) : Reader(Reader), M(M) {} - - bool operator()(const PPEntityOffset &L, const PPEntityOffset &R) const { - SourceLocation LHS = getLoc(L); - SourceLocation RHS = getLoc(R); - return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); - } - - bool operator()(const PPEntityOffset &L, SourceLocation RHS) const { - SourceLocation LHS = getLoc(L); - return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); - } - - bool operator()(SourceLocation LHS, const PPEntityOffset &R) const { - SourceLocation RHS = getLoc(R); - return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); - } - - SourceLocation getLoc(const PPEntityOffset &PPE) const { - return Reader.TranslateSourceLocation(M, PPE.getBegin()); - } -}; - -} // namespace - -PreprocessedEntityID ASTReader::findPreprocessedEntity(SourceLocation Loc, - bool EndsAfter) const { - if (SourceMgr.isLocalSourceLocation(Loc)) - return getTotalNumPreprocessedEntities(); - - GlobalSLocOffsetMapType::const_iterator SLocMapI = GlobalSLocOffsetMap.find( - SourceManager::MaxLoadedOffset - Loc.getOffset() - 1); - assert(SLocMapI != GlobalSLocOffsetMap.end() && - "Corrupted global sloc offset map"); - - if (SLocMapI->second->NumPreprocessedEntities == 0) - return findNextPreprocessedEntity(SLocMapI); - - ModuleFile &M = *SLocMapI->second; - - using pp_iterator = const PPEntityOffset *; - - pp_iterator pp_begin = M.PreprocessedEntityOffsets; - pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities; - - size_t Count = M.NumPreprocessedEntities; - size_t Half; - pp_iterator First = pp_begin; - pp_iterator PPI; - - if (EndsAfter) { - PPI = std::upper_bound(pp_begin, pp_end, Loc, - PPEntityComp(*this, M)); - } else { - // Do a binary search manually instead of using std::lower_bound because - // The end locations of entities may be unordered (when a macro expansion - // is inside another macro argument), but for this case it is not important - // whether we get the first macro expansion or its containing macro. - while (Count > 0) { - Half = Count / 2; - PPI = First; - std::advance(PPI, Half); - if (SourceMgr.isBeforeInTranslationUnit( - TranslateSourceLocation(M, PPI->getEnd()), Loc)) { - First = PPI; - ++First; - Count = Count - Half - 1; - } else - Count = Half; - } - } - - if (PPI == pp_end) - return findNextPreprocessedEntity(SLocMapI); - - return M.BasePreprocessedEntityID + (PPI - pp_begin); -} - -/// Returns a pair of [Begin, End) indices of preallocated -/// preprocessed entities that \arg Range encompasses. -std::pair<unsigned, unsigned> - ASTReader::findPreprocessedEntitiesInRange(SourceRange Range) { - if (Range.isInvalid()) - return std::make_pair(0,0); - assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin())); - - PreprocessedEntityID BeginID = - findPreprocessedEntity(Range.getBegin(), false); - PreprocessedEntityID EndID = findPreprocessedEntity(Range.getEnd(), true); - return std::make_pair(BeginID, EndID); -} - -/// Optionally returns true or false if the preallocated preprocessed -/// entity with index \arg Index came from file \arg FID. -Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index, - FileID FID) { - if (FID.isInvalid()) - return false; - - std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index); - ModuleFile &M = *PPInfo.first; - unsigned LocalIndex = PPInfo.second; - const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex]; - - SourceLocation Loc = TranslateSourceLocation(M, PPOffs.getBegin()); - if (Loc.isInvalid()) - return false; - - if (SourceMgr.isInFileID(SourceMgr.getFileLoc(Loc), FID)) - return true; - else - return false; -} - -namespace { - - /// Visitor used to search for information about a header file. - class HeaderFileInfoVisitor { - const FileEntry *FE; - Optional<HeaderFileInfo> HFI; - - public: - explicit HeaderFileInfoVisitor(const FileEntry *FE) : FE(FE) {} - - bool operator()(ModuleFile &M) { - HeaderFileInfoLookupTable *Table - = static_cast<HeaderFileInfoLookupTable *>(M.HeaderFileInfoTable); - if (!Table) - return false; - - // Look in the on-disk hash table for an entry for this file name. - HeaderFileInfoLookupTable::iterator Pos = Table->find(FE); - if (Pos == Table->end()) - return false; - - HFI = *Pos; - return true; - } - - Optional<HeaderFileInfo> getHeaderFileInfo() const { return HFI; } - }; - -} // namespace - -HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) { - HeaderFileInfoVisitor Visitor(FE); - ModuleMgr.visit(Visitor); - if (Optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo()) - return *HFI; - - return HeaderFileInfo(); -} - -void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { - using DiagState = DiagnosticsEngine::DiagState; - SmallVector<DiagState *, 32> DiagStates; - - for (ModuleFile &F : ModuleMgr) { - unsigned Idx = 0; - auto &Record = F.PragmaDiagMappings; - if (Record.empty()) - continue; - - DiagStates.clear(); - - auto ReadDiagState = - [&](const DiagState &BasedOn, SourceLocation Loc, - bool IncludeNonPragmaStates) -> DiagnosticsEngine::DiagState * { - unsigned BackrefID = Record[Idx++]; - if (BackrefID != 0) - return DiagStates[BackrefID - 1]; - - // A new DiagState was created here. - Diag.DiagStates.push_back(BasedOn); - DiagState *NewState = &Diag.DiagStates.back(); - DiagStates.push_back(NewState); - unsigned Size = Record[Idx++]; - assert(Idx + Size * 2 <= Record.size() && - "Invalid data, not enough diag/map pairs"); - while (Size--) { - unsigned DiagID = Record[Idx++]; - DiagnosticMapping NewMapping = - DiagnosticMapping::deserialize(Record[Idx++]); - if (!NewMapping.isPragma() && !IncludeNonPragmaStates) - continue; - - DiagnosticMapping &Mapping = NewState->getOrAddMapping(DiagID); - - // If this mapping was specified as a warning but the severity was - // upgraded due to diagnostic settings, simulate the current diagnostic - // settings (and use a warning). - if (NewMapping.wasUpgradedFromWarning() && !Mapping.isErrorOrFatal()) { - NewMapping.setSeverity(diag::Severity::Warning); - NewMapping.setUpgradedFromWarning(false); - } - - Mapping = NewMapping; - } - return NewState; - }; - - // Read the first state. - DiagState *FirstState; - if (F.Kind == MK_ImplicitModule) { - // Implicitly-built modules are reused with different diagnostic - // settings. Use the initial diagnostic state from Diag to simulate this - // compilation's diagnostic settings. - FirstState = Diag.DiagStatesByLoc.FirstDiagState; - DiagStates.push_back(FirstState); - - // Skip the initial diagnostic state from the serialized module. - assert(Record[1] == 0 && - "Invalid data, unexpected backref in initial state"); - Idx = 3 + Record[2] * 2; - assert(Idx < Record.size() && - "Invalid data, not enough state change pairs in initial state"); - } else if (F.isModule()) { - // For an explicit module, preserve the flags from the module build - // command line (-w, -Weverything, -Werror, ...) along with any explicit - // -Wblah flags. - unsigned Flags = Record[Idx++]; - DiagState Initial; - Initial.SuppressSystemWarnings = Flags & 1; Flags >>= 1; - Initial.ErrorsAsFatal = Flags & 1; Flags >>= 1; - Initial.WarningsAsErrors = Flags & 1; Flags >>= 1; - Initial.EnableAllWarnings = Flags & 1; Flags >>= 1; - Initial.IgnoreAllWarnings = Flags & 1; Flags >>= 1; - Initial.ExtBehavior = (diag::Severity)Flags; - FirstState = ReadDiagState(Initial, SourceLocation(), true); - - assert(F.OriginalSourceFileID.isValid()); - - // Set up the root buffer of the module to start with the initial - // diagnostic state of the module itself, to cover files that contain no - // explicit transitions (for which we did not serialize anything). - Diag.DiagStatesByLoc.Files[F.OriginalSourceFileID] - .StateTransitions.push_back({FirstState, 0}); - } else { - // For prefix ASTs, start with whatever the user configured on the - // command line. - Idx++; // Skip flags. - FirstState = ReadDiagState(*Diag.DiagStatesByLoc.CurDiagState, - SourceLocation(), false); - } - - // Read the state transitions. - unsigned NumLocations = Record[Idx++]; - while (NumLocations--) { - assert(Idx < Record.size() && - "Invalid data, missing pragma diagnostic states"); - SourceLocation Loc = ReadSourceLocation(F, Record[Idx++]); - auto IDAndOffset = SourceMgr.getDecomposedLoc(Loc); - assert(IDAndOffset.first.isValid() && "invalid FileID for transition"); - assert(IDAndOffset.second == 0 && "not a start location for a FileID"); - unsigned Transitions = Record[Idx++]; - - // Note that we don't need to set up Parent/ParentOffset here, because - // we won't be changing the diagnostic state within imported FileIDs - // (other than perhaps appending to the main source file, which has no - // parent). - auto &F = Diag.DiagStatesByLoc.Files[IDAndOffset.first]; - F.StateTransitions.reserve(F.StateTransitions.size() + Transitions); - for (unsigned I = 0; I != Transitions; ++I) { - unsigned Offset = Record[Idx++]; - auto *State = - ReadDiagState(*FirstState, Loc.getLocWithOffset(Offset), false); - F.StateTransitions.push_back({State, Offset}); - } - } - - // Read the final state. - assert(Idx < Record.size() && - "Invalid data, missing final pragma diagnostic state"); - SourceLocation CurStateLoc = - ReadSourceLocation(F, F.PragmaDiagMappings[Idx++]); - auto *CurState = ReadDiagState(*FirstState, CurStateLoc, false); - - if (!F.isModule()) { - Diag.DiagStatesByLoc.CurDiagState = CurState; - Diag.DiagStatesByLoc.CurDiagStateLoc = CurStateLoc; - - // Preserve the property that the imaginary root file describes the - // current state. - FileID NullFile; - auto &T = Diag.DiagStatesByLoc.Files[NullFile].StateTransitions; - if (T.empty()) - T.push_back({CurState, 0}); - else - T[0].State = CurState; - } - - // Don't try to read these mappings again. - Record.clear(); - } -} - -/// Get the correct cursor and offset for loading a type. -ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) { - GlobalTypeMapType::iterator I = GlobalTypeMap.find(Index); - assert(I != GlobalTypeMap.end() && "Corrupted global type map"); - ModuleFile *M = I->second; - return RecordLocation(M, M->TypeOffsets[Index - M->BaseTypeIndex]); -} - -/// Read and return the type with the given index.. -/// -/// The index is the type ID, shifted and minus the number of predefs. This -/// routine actually reads the record corresponding to the type at the given -/// location. It is a helper routine for GetType, which deals with reading type -/// IDs. -QualType ASTReader::readTypeRecord(unsigned Index) { - assert(ContextObj && "reading type with no AST context"); - ASTContext &Context = *ContextObj; - RecordLocation Loc = TypeCursorForIndex(Index); - BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; - - // Keep track of where we are in the stream, then jump back there - // after reading this type. - SavedStreamPosition SavedPosition(DeclsCursor); - - ReadingKindTracker ReadingKind(Read_Type, *this); - - // Note that we are loading a type record. - Deserializing AType(this); - - unsigned Idx = 0; - DeclsCursor.JumpToBit(Loc.Offset); - RecordData Record; - unsigned Code = DeclsCursor.ReadCode(); - switch ((TypeCode)DeclsCursor.readRecord(Code, Record)) { - case TYPE_EXT_QUAL: { - if (Record.size() != 2) { - Error("Incorrect encoding of extended qualifier type"); - return QualType(); - } - QualType Base = readType(*Loc.F, Record, Idx); - Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[Idx++]); - return Context.getQualifiedType(Base, Quals); - } - - case TYPE_COMPLEX: { - if (Record.size() != 1) { - Error("Incorrect encoding of complex type"); - return QualType(); - } - QualType ElemType = readType(*Loc.F, Record, Idx); - return Context.getComplexType(ElemType); - } - - case TYPE_POINTER: { - if (Record.size() != 1) { - Error("Incorrect encoding of pointer type"); - return QualType(); - } - QualType PointeeType = readType(*Loc.F, Record, Idx); - return Context.getPointerType(PointeeType); - } - - case TYPE_DECAYED: { - if (Record.size() != 1) { - Error("Incorrect encoding of decayed type"); - return QualType(); - } - QualType OriginalType = readType(*Loc.F, Record, Idx); - QualType DT = Context.getAdjustedParameterType(OriginalType); - if (!isa<DecayedType>(DT)) - Error("Decayed type does not decay"); - return DT; - } - - case TYPE_ADJUSTED: { - if (Record.size() != 2) { - Error("Incorrect encoding of adjusted type"); - return QualType(); - } - QualType OriginalTy = readType(*Loc.F, Record, Idx); - QualType AdjustedTy = readType(*Loc.F, Record, Idx); - return Context.getAdjustedType(OriginalTy, AdjustedTy); - } - - case TYPE_BLOCK_POINTER: { - if (Record.size() != 1) { - Error("Incorrect encoding of block pointer type"); - return QualType(); - } - QualType PointeeType = readType(*Loc.F, Record, Idx); - return Context.getBlockPointerType(PointeeType); - } - - case TYPE_LVALUE_REFERENCE: { - if (Record.size() != 2) { - Error("Incorrect encoding of lvalue reference type"); - return QualType(); - } - QualType PointeeType = readType(*Loc.F, Record, Idx); - return Context.getLValueReferenceType(PointeeType, Record[1]); - } - - case TYPE_RVALUE_REFERENCE: { - if (Record.size() != 1) { - Error("Incorrect encoding of rvalue reference type"); - return QualType(); - } - QualType PointeeType = readType(*Loc.F, Record, Idx); - return Context.getRValueReferenceType(PointeeType); - } - - case TYPE_MEMBER_POINTER: { - if (Record.size() != 2) { - Error("Incorrect encoding of member pointer type"); - return QualType(); - } - QualType PointeeType = readType(*Loc.F, Record, Idx); - QualType ClassType = readType(*Loc.F, Record, Idx); - if (PointeeType.isNull() || ClassType.isNull()) - return QualType(); - - return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr()); - } - - case TYPE_CONSTANT_ARRAY: { - QualType ElementType = readType(*Loc.F, Record, Idx); - ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; - unsigned IndexTypeQuals = Record[2]; - unsigned Idx = 3; - llvm::APInt Size = ReadAPInt(Record, Idx); - return Context.getConstantArrayType(ElementType, Size, - ASM, IndexTypeQuals); - } - - case TYPE_INCOMPLETE_ARRAY: { - QualType ElementType = readType(*Loc.F, Record, Idx); - ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; - unsigned IndexTypeQuals = Record[2]; - return Context.getIncompleteArrayType(ElementType, ASM, IndexTypeQuals); - } - - case TYPE_VARIABLE_ARRAY: { - QualType ElementType = readType(*Loc.F, Record, Idx); - ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; - unsigned IndexTypeQuals = Record[2]; - SourceLocation LBLoc = ReadSourceLocation(*Loc.F, Record[3]); - SourceLocation RBLoc = ReadSourceLocation(*Loc.F, Record[4]); - return Context.getVariableArrayType(ElementType, ReadExpr(*Loc.F), - ASM, IndexTypeQuals, - SourceRange(LBLoc, RBLoc)); - } - - case TYPE_VECTOR: { - if (Record.size() != 3) { - Error("incorrect encoding of vector type in AST file"); - return QualType(); - } - - QualType ElementType = readType(*Loc.F, Record, Idx); - unsigned NumElements = Record[1]; - unsigned VecKind = Record[2]; - return Context.getVectorType(ElementType, NumElements, - (VectorType::VectorKind)VecKind); - } - - case TYPE_EXT_VECTOR: { - if (Record.size() != 3) { - Error("incorrect encoding of extended vector type in AST file"); - return QualType(); - } - - QualType ElementType = readType(*Loc.F, Record, Idx); - unsigned NumElements = Record[1]; - return Context.getExtVectorType(ElementType, NumElements); - } - - case TYPE_FUNCTION_NO_PROTO: { - if (Record.size() != 8) { - Error("incorrect encoding of no-proto function type"); - return QualType(); - } - QualType ResultType = readType(*Loc.F, Record, Idx); - FunctionType::ExtInfo Info(Record[1], Record[2], Record[3], - (CallingConv)Record[4], Record[5], Record[6], - Record[7]); - return Context.getFunctionNoProtoType(ResultType, Info); - } - - case TYPE_FUNCTION_PROTO: { - QualType ResultType = readType(*Loc.F, Record, Idx); - - FunctionProtoType::ExtProtoInfo EPI; - EPI.ExtInfo = FunctionType::ExtInfo(/*noreturn*/ Record[1], - /*hasregparm*/ Record[2], - /*regparm*/ Record[3], - static_cast<CallingConv>(Record[4]), - /*produces*/ Record[5], - /*nocallersavedregs*/ Record[6], - /*nocfcheck*/ Record[7]); - - unsigned Idx = 8; - - EPI.Variadic = Record[Idx++]; - EPI.HasTrailingReturn = Record[Idx++]; - EPI.TypeQuals = Qualifiers::fromOpaqueValue(Record[Idx++]); - EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]); - SmallVector<QualType, 8> ExceptionStorage; - readExceptionSpec(*Loc.F, ExceptionStorage, EPI.ExceptionSpec, Record, Idx); - - unsigned NumParams = Record[Idx++]; - SmallVector<QualType, 16> ParamTypes; - for (unsigned I = 0; I != NumParams; ++I) - ParamTypes.push_back(readType(*Loc.F, Record, Idx)); - - SmallVector<FunctionProtoType::ExtParameterInfo, 4> ExtParameterInfos; - if (Idx != Record.size()) { - for (unsigned I = 0; I != NumParams; ++I) - ExtParameterInfos.push_back( - FunctionProtoType::ExtParameterInfo - ::getFromOpaqueValue(Record[Idx++])); - EPI.ExtParameterInfos = ExtParameterInfos.data(); - } - - assert(Idx == Record.size()); - - return Context.getFunctionType(ResultType, ParamTypes, EPI); - } - - case TYPE_UNRESOLVED_USING: { - unsigned Idx = 0; - return Context.getTypeDeclType( - ReadDeclAs<UnresolvedUsingTypenameDecl>(*Loc.F, Record, Idx)); - } - - case TYPE_TYPEDEF: { - if (Record.size() != 2) { - Error("incorrect encoding of typedef type"); - return QualType(); - } - unsigned Idx = 0; - TypedefNameDecl *Decl = ReadDeclAs<TypedefNameDecl>(*Loc.F, Record, Idx); - QualType Canonical = readType(*Loc.F, Record, Idx); - if (!Canonical.isNull()) - Canonical = Context.getCanonicalType(Canonical); - return Context.getTypedefType(Decl, Canonical); - } - - case TYPE_TYPEOF_EXPR: - return Context.getTypeOfExprType(ReadExpr(*Loc.F)); - - case TYPE_TYPEOF: { - if (Record.size() != 1) { - Error("incorrect encoding of typeof(type) in AST file"); - return QualType(); - } - QualType UnderlyingType = readType(*Loc.F, Record, Idx); - return Context.getTypeOfType(UnderlyingType); - } - - case TYPE_DECLTYPE: { - QualType UnderlyingType = readType(*Loc.F, Record, Idx); - return Context.getDecltypeType(ReadExpr(*Loc.F), UnderlyingType); - } - - case TYPE_UNARY_TRANSFORM: { - QualType BaseType = readType(*Loc.F, Record, Idx); - QualType UnderlyingType = readType(*Loc.F, Record, Idx); - UnaryTransformType::UTTKind UKind = (UnaryTransformType::UTTKind)Record[2]; - return Context.getUnaryTransformType(BaseType, UnderlyingType, UKind); - } - - case TYPE_AUTO: { - QualType Deduced = readType(*Loc.F, Record, Idx); - AutoTypeKeyword Keyword = (AutoTypeKeyword)Record[Idx++]; - bool IsDependent = Deduced.isNull() ? Record[Idx++] : false; - return Context.getAutoType(Deduced, Keyword, IsDependent); - } - - case TYPE_DEDUCED_TEMPLATE_SPECIALIZATION: { - TemplateName Name = ReadTemplateName(*Loc.F, Record, Idx); - QualType Deduced = readType(*Loc.F, Record, Idx); - bool IsDependent = Deduced.isNull() ? Record[Idx++] : false; - return Context.getDeducedTemplateSpecializationType(Name, Deduced, - IsDependent); - } - - case TYPE_RECORD: { - if (Record.size() != 2) { - Error("incorrect encoding of record type"); - return QualType(); - } - unsigned Idx = 0; - bool IsDependent = Record[Idx++]; - RecordDecl *RD = ReadDeclAs<RecordDecl>(*Loc.F, Record, Idx); - RD = cast_or_null<RecordDecl>(RD->getCanonicalDecl()); - QualType T = Context.getRecordType(RD); - const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent); - return T; - } - - case TYPE_ENUM: { - if (Record.size() != 2) { - Error("incorrect encoding of enum type"); - return QualType(); - } - unsigned Idx = 0; - bool IsDependent = Record[Idx++]; - QualType T - = Context.getEnumType(ReadDeclAs<EnumDecl>(*Loc.F, Record, Idx)); - const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent); - return T; - } - - case TYPE_ATTRIBUTED: { - if (Record.size() != 3) { - Error("incorrect encoding of attributed type"); - return QualType(); - } - QualType modifiedType = readType(*Loc.F, Record, Idx); - QualType equivalentType = readType(*Loc.F, Record, Idx); - AttributedType::Kind kind = static_cast<AttributedType::Kind>(Record[2]); - return Context.getAttributedType(kind, modifiedType, equivalentType); - } - - case TYPE_PAREN: { - if (Record.size() != 1) { - Error("incorrect encoding of paren type"); - return QualType(); - } - QualType InnerType = readType(*Loc.F, Record, Idx); - return Context.getParenType(InnerType); - } - - case TYPE_PACK_EXPANSION: { - if (Record.size() != 2) { - Error("incorrect encoding of pack expansion type"); - return QualType(); - } - QualType Pattern = readType(*Loc.F, Record, Idx); - if (Pattern.isNull()) - return QualType(); - Optional<unsigned> NumExpansions; - if (Record[1]) - NumExpansions = Record[1] - 1; - return Context.getPackExpansionType(Pattern, NumExpansions); - } - - case TYPE_ELABORATED: { - unsigned Idx = 0; - ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx); - QualType NamedType = readType(*Loc.F, Record, Idx); - TagDecl *OwnedTagDecl = ReadDeclAs<TagDecl>(*Loc.F, Record, Idx); - return Context.getElaboratedType(Keyword, NNS, NamedType, OwnedTagDecl); - } - - case TYPE_OBJC_INTERFACE: { - unsigned Idx = 0; - ObjCInterfaceDecl *ItfD - = ReadDeclAs<ObjCInterfaceDecl>(*Loc.F, Record, Idx); - return Context.getObjCInterfaceType(ItfD->getCanonicalDecl()); - } - - case TYPE_OBJC_TYPE_PARAM: { - unsigned Idx = 0; - ObjCTypeParamDecl *Decl - = ReadDeclAs<ObjCTypeParamDecl>(*Loc.F, Record, Idx); - unsigned NumProtos = Record[Idx++]; - SmallVector<ObjCProtocolDecl*, 4> Protos; - for (unsigned I = 0; I != NumProtos; ++I) - Protos.push_back(ReadDeclAs<ObjCProtocolDecl>(*Loc.F, Record, Idx)); - return Context.getObjCTypeParamType(Decl, Protos); - } - - case TYPE_OBJC_OBJECT: { - unsigned Idx = 0; - QualType Base = readType(*Loc.F, Record, Idx); - unsigned NumTypeArgs = Record[Idx++]; - SmallVector<QualType, 4> TypeArgs; - for (unsigned I = 0; I != NumTypeArgs; ++I) - TypeArgs.push_back(readType(*Loc.F, Record, Idx)); - unsigned NumProtos = Record[Idx++]; - SmallVector<ObjCProtocolDecl*, 4> Protos; - for (unsigned I = 0; I != NumProtos; ++I) - Protos.push_back(ReadDeclAs<ObjCProtocolDecl>(*Loc.F, Record, Idx)); - bool IsKindOf = Record[Idx++]; - return Context.getObjCObjectType(Base, TypeArgs, Protos, IsKindOf); - } - - case TYPE_OBJC_OBJECT_POINTER: { - unsigned Idx = 0; - QualType Pointee = readType(*Loc.F, Record, Idx); - return Context.getObjCObjectPointerType(Pointee); - } - - case TYPE_SUBST_TEMPLATE_TYPE_PARM: { - unsigned Idx = 0; - QualType Parm = readType(*Loc.F, Record, Idx); - QualType Replacement = readType(*Loc.F, Record, Idx); - return Context.getSubstTemplateTypeParmType( - cast<TemplateTypeParmType>(Parm), - Context.getCanonicalType(Replacement)); - } - - case TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK: { - unsigned Idx = 0; - QualType Parm = readType(*Loc.F, Record, Idx); - TemplateArgument ArgPack = ReadTemplateArgument(*Loc.F, Record, Idx); - return Context.getSubstTemplateTypeParmPackType( - cast<TemplateTypeParmType>(Parm), - ArgPack); - } - - case TYPE_INJECTED_CLASS_NAME: { - CXXRecordDecl *D = ReadDeclAs<CXXRecordDecl>(*Loc.F, Record, Idx); - QualType TST = readType(*Loc.F, Record, Idx); // probably derivable - // FIXME: ASTContext::getInjectedClassNameType is not currently suitable - // for AST reading, too much interdependencies. - const Type *T = nullptr; - for (auto *DI = D; DI; DI = DI->getPreviousDecl()) { - if (const Type *Existing = DI->getTypeForDecl()) { - T = Existing; - break; - } - } - if (!T) { - T = new (Context, TypeAlignment) InjectedClassNameType(D, TST); - for (auto *DI = D; DI; DI = DI->getPreviousDecl()) - DI->setTypeForDecl(T); - } - return QualType(T, 0); - } - - case TYPE_TEMPLATE_TYPE_PARM: { - unsigned Idx = 0; - unsigned Depth = Record[Idx++]; - unsigned Index = Record[Idx++]; - bool Pack = Record[Idx++]; - TemplateTypeParmDecl *D - = ReadDeclAs<TemplateTypeParmDecl>(*Loc.F, Record, Idx); - return Context.getTemplateTypeParmType(Depth, Index, Pack, D); - } - - case TYPE_DEPENDENT_NAME: { - unsigned Idx = 0; - ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx); - const IdentifierInfo *Name = GetIdentifierInfo(*Loc.F, Record, Idx); - QualType Canon = readType(*Loc.F, Record, Idx); - if (!Canon.isNull()) - Canon = Context.getCanonicalType(Canon); - return Context.getDependentNameType(Keyword, NNS, Name, Canon); - } - - case TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION: { - unsigned Idx = 0; - ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx); - const IdentifierInfo *Name = GetIdentifierInfo(*Loc.F, Record, Idx); - unsigned NumArgs = Record[Idx++]; - SmallVector<TemplateArgument, 8> Args; - Args.reserve(NumArgs); - while (NumArgs--) - Args.push_back(ReadTemplateArgument(*Loc.F, Record, Idx)); - return Context.getDependentTemplateSpecializationType(Keyword, NNS, Name, - Args); - } - - case TYPE_DEPENDENT_SIZED_ARRAY: { - unsigned Idx = 0; - - // ArrayType - QualType ElementType = readType(*Loc.F, Record, Idx); - ArrayType::ArraySizeModifier ASM - = (ArrayType::ArraySizeModifier)Record[Idx++]; - unsigned IndexTypeQuals = Record[Idx++]; - - // DependentSizedArrayType - Expr *NumElts = ReadExpr(*Loc.F); - SourceRange Brackets = ReadSourceRange(*Loc.F, Record, Idx); - - return Context.getDependentSizedArrayType(ElementType, NumElts, ASM, - IndexTypeQuals, Brackets); - } - - case TYPE_TEMPLATE_SPECIALIZATION: { - unsigned Idx = 0; - bool IsDependent = Record[Idx++]; - TemplateName Name = ReadTemplateName(*Loc.F, Record, Idx); - SmallVector<TemplateArgument, 8> Args; - ReadTemplateArgumentList(Args, *Loc.F, Record, Idx); - QualType Underlying = readType(*Loc.F, Record, Idx); - QualType T; - if (Underlying.isNull()) - T = Context.getCanonicalTemplateSpecializationType(Name, Args); - else - T = Context.getTemplateSpecializationType(Name, Args, Underlying); - const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent); - return T; - } - - case TYPE_ATOMIC: { - if (Record.size() != 1) { - Error("Incorrect encoding of atomic type"); - return QualType(); - } - QualType ValueType = readType(*Loc.F, Record, Idx); - return Context.getAtomicType(ValueType); - } - - case TYPE_PIPE: { - if (Record.size() != 2) { - Error("Incorrect encoding of pipe type"); - return QualType(); - } - - // Reading the pipe element type. - QualType ElementType = readType(*Loc.F, Record, Idx); - unsigned ReadOnly = Record[1]; - return Context.getPipeType(ElementType, ReadOnly); - } - - case TYPE_DEPENDENT_SIZED_VECTOR: { - unsigned Idx = 0; - QualType ElementType = readType(*Loc.F, Record, Idx); - Expr *SizeExpr = ReadExpr(*Loc.F); - SourceLocation AttrLoc = ReadSourceLocation(*Loc.F, Record, Idx); - unsigned VecKind = Record[Idx]; - - return Context.getDependentVectorType(ElementType, SizeExpr, AttrLoc, - (VectorType::VectorKind)VecKind); - } - - case TYPE_DEPENDENT_SIZED_EXT_VECTOR: { - unsigned Idx = 0; - - // DependentSizedExtVectorType - QualType ElementType = readType(*Loc.F, Record, Idx); - Expr *SizeExpr = ReadExpr(*Loc.F); - SourceLocation AttrLoc = ReadSourceLocation(*Loc.F, Record, Idx); - - return Context.getDependentSizedExtVectorType(ElementType, SizeExpr, - AttrLoc); - } - - case TYPE_DEPENDENT_ADDRESS_SPACE: { - unsigned Idx = 0; - - // DependentAddressSpaceType - QualType PointeeType = readType(*Loc.F, Record, Idx); - Expr *AddrSpaceExpr = ReadExpr(*Loc.F); - SourceLocation AttrLoc = ReadSourceLocation(*Loc.F, Record, Idx); - - return Context.getDependentAddressSpaceType(PointeeType, AddrSpaceExpr, - AttrLoc); - } - } - llvm_unreachable("Invalid TypeCode!"); -} - -void ASTReader::readExceptionSpec(ModuleFile &ModuleFile, - SmallVectorImpl<QualType> &Exceptions, - FunctionProtoType::ExceptionSpecInfo &ESI, - const RecordData &Record, unsigned &Idx) { - ExceptionSpecificationType EST = - static_cast<ExceptionSpecificationType>(Record[Idx++]); - ESI.Type = EST; - if (EST == EST_Dynamic) { - for (unsigned I = 0, N = Record[Idx++]; I != N; ++I) - Exceptions.push_back(readType(ModuleFile, Record, Idx)); - ESI.Exceptions = Exceptions; - } else if (isComputedNoexcept(EST)) { - ESI.NoexceptExpr = ReadExpr(ModuleFile); - } else if (EST == EST_Uninstantiated) { - ESI.SourceDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); - ESI.SourceTemplate = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); - } else if (EST == EST_Unevaluated) { - ESI.SourceDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); - } -} - -namespace clang { - -class TypeLocReader : public TypeLocVisitor<TypeLocReader> { - ModuleFile *F; - ASTReader *Reader; - const ASTReader::RecordData &Record; - unsigned &Idx; - - SourceLocation ReadSourceLocation() { - return Reader->ReadSourceLocation(*F, Record, Idx); - } - - TypeSourceInfo *GetTypeSourceInfo() { - return Reader->GetTypeSourceInfo(*F, Record, Idx); - } - - NestedNameSpecifierLoc ReadNestedNameSpecifierLoc() { - return Reader->ReadNestedNameSpecifierLoc(*F, Record, Idx); - } - - Attr *ReadAttr() { - return Reader->ReadAttr(*F, Record, Idx); - } - -public: - TypeLocReader(ModuleFile &F, ASTReader &Reader, - const ASTReader::RecordData &Record, unsigned &Idx) - : F(&F), Reader(&Reader), Record(Record), Idx(Idx) {} - - // We want compile-time assurance that we've enumerated all of - // these, so unfortunately we have to declare them first, then - // define them out-of-line. -#define ABSTRACT_TYPELOC(CLASS, PARENT) -#define TYPELOC(CLASS, PARENT) \ - void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc); -#include "clang/AST/TypeLocNodes.def" - - void VisitFunctionTypeLoc(FunctionTypeLoc); - void VisitArrayTypeLoc(ArrayTypeLoc); -}; - -} // namespace clang - -void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { - // nothing to do -} - -void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { - TL.setBuiltinLoc(ReadSourceLocation()); - if (TL.needsExtraLocalData()) { - TL.setWrittenTypeSpec(static_cast<DeclSpec::TST>(Record[Idx++])); - TL.setWrittenSignSpec(static_cast<DeclSpec::TSS>(Record[Idx++])); - TL.setWrittenWidthSpec(static_cast<DeclSpec::TSW>(Record[Idx++])); - TL.setModeAttr(Record[Idx++]); - } -} - -void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) { - TL.setStarLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitDecayedTypeLoc(DecayedTypeLoc TL) { - // nothing to do -} - -void TypeLocReader::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { - // nothing to do -} - -void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { - TL.setCaretLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { - TL.setAmpLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { - TL.setAmpAmpLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { - TL.setStarLoc(ReadSourceLocation()); - TL.setClassTInfo(GetTypeSourceInfo()); -} - -void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) { - TL.setLBracketLoc(ReadSourceLocation()); - TL.setRBracketLoc(ReadSourceLocation()); - if (Record[Idx++]) - TL.setSizeExpr(Reader->ReadExpr(*F)); - else - TL.setSizeExpr(nullptr); -} - -void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} - -void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} - -void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} - -void TypeLocReader::VisitDependentSizedArrayTypeLoc( - DependentSizedArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} - -void TypeLocReader::VisitDependentAddressSpaceTypeLoc( - DependentAddressSpaceTypeLoc TL) { - - TL.setAttrNameLoc(ReadSourceLocation()); - SourceRange range; - range.setBegin(ReadSourceLocation()); - range.setEnd(ReadSourceLocation()); - TL.setAttrOperandParensRange(range); - TL.setAttrExprOperand(Reader->ReadExpr(*F)); -} - -void TypeLocReader::VisitDependentSizedExtVectorTypeLoc( - DependentSizedExtVectorTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitDependentVectorTypeLoc( - DependentVectorTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) { - TL.setLocalRangeBegin(ReadSourceLocation()); - TL.setLParenLoc(ReadSourceLocation()); - TL.setRParenLoc(ReadSourceLocation()); - TL.setExceptionSpecRange(SourceRange(Reader->ReadSourceLocation(*F, Record, Idx), - Reader->ReadSourceLocation(*F, Record, Idx))); - TL.setLocalRangeEnd(ReadSourceLocation()); - for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i) { - TL.setParam(i, Reader->ReadDeclAs<ParmVarDecl>(*F, Record, Idx)); - } -} - -void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { - VisitFunctionTypeLoc(TL); -} - -void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) { - VisitFunctionTypeLoc(TL); -} - -void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { - TL.setTypeofLoc(ReadSourceLocation()); - TL.setLParenLoc(ReadSourceLocation()); - TL.setRParenLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { - TL.setTypeofLoc(ReadSourceLocation()); - TL.setLParenLoc(ReadSourceLocation()); - TL.setRParenLoc(ReadSourceLocation()); - TL.setUnderlyingTInfo(GetTypeSourceInfo()); -} - -void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) { - TL.setKWLoc(ReadSourceLocation()); - TL.setLParenLoc(ReadSourceLocation()); - TL.setRParenLoc(ReadSourceLocation()); - TL.setUnderlyingTInfo(GetTypeSourceInfo()); -} - -void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitDeducedTemplateSpecializationTypeLoc( - DeducedTemplateSpecializationTypeLoc TL) { - TL.setTemplateNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) { - TL.setAttr(ReadAttr()); -} - -void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc( - SubstTemplateTypeParmTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitSubstTemplateTypeParmPackTypeLoc( - SubstTemplateTypeParmPackTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitTemplateSpecializationTypeLoc( - TemplateSpecializationTypeLoc TL) { - TL.setTemplateKeywordLoc(ReadSourceLocation()); - TL.setTemplateNameLoc(ReadSourceLocation()); - TL.setLAngleLoc(ReadSourceLocation()); - TL.setRAngleLoc(ReadSourceLocation()); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - TL.setArgLocInfo( - i, - Reader->GetTemplateArgumentLocInfo( - *F, TL.getTypePtr()->getArg(i).getKind(), Record, Idx)); -} - -void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) { - TL.setLParenLoc(ReadSourceLocation()); - TL.setRParenLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { - TL.setElaboratedKeywordLoc(ReadSourceLocation()); - TL.setQualifierLoc(ReadNestedNameSpecifierLoc()); -} - -void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { - TL.setElaboratedKeywordLoc(ReadSourceLocation()); - TL.setQualifierLoc(ReadNestedNameSpecifierLoc()); - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc( - DependentTemplateSpecializationTypeLoc TL) { - TL.setElaboratedKeywordLoc(ReadSourceLocation()); - TL.setQualifierLoc(ReadNestedNameSpecifierLoc()); - TL.setTemplateKeywordLoc(ReadSourceLocation()); - TL.setTemplateNameLoc(ReadSourceLocation()); - TL.setLAngleLoc(ReadSourceLocation()); - TL.setRAngleLoc(ReadSourceLocation()); - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) - TL.setArgLocInfo( - I, - Reader->GetTemplateArgumentLocInfo( - *F, TL.getTypePtr()->getArg(I).getKind(), Record, Idx)); -} - -void TypeLocReader::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) { - TL.setEllipsisLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) { - if (TL.getNumProtocols()) { - TL.setProtocolLAngleLoc(ReadSourceLocation()); - TL.setProtocolRAngleLoc(ReadSourceLocation()); - } - for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) - TL.setProtocolLoc(i, ReadSourceLocation()); -} - -void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { - TL.setHasBaseTypeAsWritten(Record[Idx++]); - TL.setTypeArgsLAngleLoc(ReadSourceLocation()); - TL.setTypeArgsRAngleLoc(ReadSourceLocation()); - for (unsigned i = 0, e = TL.getNumTypeArgs(); i != e; ++i) - TL.setTypeArgTInfo(i, GetTypeSourceInfo()); - TL.setProtocolLAngleLoc(ReadSourceLocation()); - TL.setProtocolRAngleLoc(ReadSourceLocation()); - for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) - TL.setProtocolLoc(i, ReadSourceLocation()); -} - -void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { - TL.setStarLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitAtomicTypeLoc(AtomicTypeLoc TL) { - TL.setKWLoc(ReadSourceLocation()); - TL.setLParenLoc(ReadSourceLocation()); - TL.setRParenLoc(ReadSourceLocation()); -} - -void TypeLocReader::VisitPipeTypeLoc(PipeTypeLoc TL) { - TL.setKWLoc(ReadSourceLocation()); -} - -void ASTReader::ReadTypeLoc(ModuleFile &F, const ASTReader::RecordData &Record, - unsigned &Idx, TypeLoc TL) { - TypeLocReader TLR(F, *this, Record, Idx); - for (; !TL.isNull(); TL = TL.getNextTypeLoc()) - TLR.Visit(TL); -} - -TypeSourceInfo * -ASTReader::GetTypeSourceInfo(ModuleFile &F, const ASTReader::RecordData &Record, - unsigned &Idx) { - QualType InfoTy = readType(F, Record, Idx); - if (InfoTy.isNull()) - return nullptr; - - TypeSourceInfo *TInfo = getContext().CreateTypeSourceInfo(InfoTy); - ReadTypeLoc(F, Record, Idx, TInfo->getTypeLoc()); - return TInfo; -} - -QualType ASTReader::GetType(TypeID ID) { - assert(ContextObj && "reading type with no AST context"); - ASTContext &Context = *ContextObj; - - unsigned FastQuals = ID & Qualifiers::FastMask; - unsigned Index = ID >> Qualifiers::FastWidth; - - if (Index < NUM_PREDEF_TYPE_IDS) { - QualType T; - switch ((PredefinedTypeIDs)Index) { - case PREDEF_TYPE_NULL_ID: - return QualType(); - case PREDEF_TYPE_VOID_ID: - T = Context.VoidTy; - break; - case PREDEF_TYPE_BOOL_ID: - T = Context.BoolTy; - break; - case PREDEF_TYPE_CHAR_U_ID: - case PREDEF_TYPE_CHAR_S_ID: - // FIXME: Check that the signedness of CharTy is correct! - T = Context.CharTy; - break; - case PREDEF_TYPE_UCHAR_ID: - T = Context.UnsignedCharTy; - break; - case PREDEF_TYPE_USHORT_ID: - T = Context.UnsignedShortTy; - break; - case PREDEF_TYPE_UINT_ID: - T = Context.UnsignedIntTy; - break; - case PREDEF_TYPE_ULONG_ID: - T = Context.UnsignedLongTy; - break; - case PREDEF_TYPE_ULONGLONG_ID: - T = Context.UnsignedLongLongTy; - break; - case PREDEF_TYPE_UINT128_ID: - T = Context.UnsignedInt128Ty; - break; - case PREDEF_TYPE_SCHAR_ID: - T = Context.SignedCharTy; - break; - case PREDEF_TYPE_WCHAR_ID: - T = Context.WCharTy; - break; - case PREDEF_TYPE_SHORT_ID: - T = Context.ShortTy; - break; - case PREDEF_TYPE_INT_ID: - T = Context.IntTy; - break; - case PREDEF_TYPE_LONG_ID: - T = Context.LongTy; - break; - case PREDEF_TYPE_LONGLONG_ID: - T = Context.LongLongTy; - break; - case PREDEF_TYPE_INT128_ID: - T = Context.Int128Ty; - break; - case PREDEF_TYPE_HALF_ID: - T = Context.HalfTy; - break; - case PREDEF_TYPE_FLOAT_ID: - T = Context.FloatTy; - break; - case PREDEF_TYPE_DOUBLE_ID: - T = Context.DoubleTy; - break; - case PREDEF_TYPE_LONGDOUBLE_ID: - T = Context.LongDoubleTy; - break; - case PREDEF_TYPE_SHORT_ACCUM_ID: - T = Context.ShortAccumTy; - break; - case PREDEF_TYPE_ACCUM_ID: - T = Context.AccumTy; - break; - case PREDEF_TYPE_LONG_ACCUM_ID: - T = Context.LongAccumTy; - break; - case PREDEF_TYPE_USHORT_ACCUM_ID: - T = Context.UnsignedShortAccumTy; - break; - case PREDEF_TYPE_UACCUM_ID: - T = Context.UnsignedAccumTy; - break; - case PREDEF_TYPE_ULONG_ACCUM_ID: - T = Context.UnsignedLongAccumTy; - break; - case PREDEF_TYPE_SHORT_FRACT_ID: - T = Context.ShortFractTy; - break; - case PREDEF_TYPE_FRACT_ID: - T = Context.FractTy; - break; - case PREDEF_TYPE_LONG_FRACT_ID: - T = Context.LongFractTy; - break; - case PREDEF_TYPE_USHORT_FRACT_ID: - T = Context.UnsignedShortFractTy; - break; - case PREDEF_TYPE_UFRACT_ID: - T = Context.UnsignedFractTy; - break; - case PREDEF_TYPE_ULONG_FRACT_ID: - T = Context.UnsignedLongFractTy; - break; - case PREDEF_TYPE_SAT_SHORT_ACCUM_ID: - T = Context.SatShortAccumTy; - break; - case PREDEF_TYPE_SAT_ACCUM_ID: - T = Context.SatAccumTy; - break; - case PREDEF_TYPE_SAT_LONG_ACCUM_ID: - T = Context.SatLongAccumTy; - break; - case PREDEF_TYPE_SAT_USHORT_ACCUM_ID: - T = Context.SatUnsignedShortAccumTy; - break; - case PREDEF_TYPE_SAT_UACCUM_ID: - T = Context.SatUnsignedAccumTy; - break; - case PREDEF_TYPE_SAT_ULONG_ACCUM_ID: - T = Context.SatUnsignedLongAccumTy; - break; - case PREDEF_TYPE_SAT_SHORT_FRACT_ID: - T = Context.SatShortFractTy; - break; - case PREDEF_TYPE_SAT_FRACT_ID: - T = Context.SatFractTy; - break; - case PREDEF_TYPE_SAT_LONG_FRACT_ID: - T = Context.SatLongFractTy; - break; - case PREDEF_TYPE_SAT_USHORT_FRACT_ID: - T = Context.SatUnsignedShortFractTy; - break; - case PREDEF_TYPE_SAT_UFRACT_ID: - T = Context.SatUnsignedFractTy; - break; - case PREDEF_TYPE_SAT_ULONG_FRACT_ID: - T = Context.SatUnsignedLongFractTy; - break; - case PREDEF_TYPE_FLOAT16_ID: - T = Context.Float16Ty; - break; - case PREDEF_TYPE_FLOAT128_ID: - T = Context.Float128Ty; - break; - case PREDEF_TYPE_OVERLOAD_ID: - T = Context.OverloadTy; - break; - case PREDEF_TYPE_BOUND_MEMBER: - T = Context.BoundMemberTy; - break; - case PREDEF_TYPE_PSEUDO_OBJECT: - T = Context.PseudoObjectTy; - break; - case PREDEF_TYPE_DEPENDENT_ID: - T = Context.DependentTy; - break; - case PREDEF_TYPE_UNKNOWN_ANY: - T = Context.UnknownAnyTy; - break; - case PREDEF_TYPE_NULLPTR_ID: - T = Context.NullPtrTy; - break; - case PREDEF_TYPE_CHAR8_ID: - T = Context.Char8Ty; - break; - case PREDEF_TYPE_CHAR16_ID: - T = Context.Char16Ty; - break; - case PREDEF_TYPE_CHAR32_ID: - T = Context.Char32Ty; - break; - case PREDEF_TYPE_OBJC_ID: - T = Context.ObjCBuiltinIdTy; - break; - case PREDEF_TYPE_OBJC_CLASS: - T = Context.ObjCBuiltinClassTy; - break; - case PREDEF_TYPE_OBJC_SEL: - T = Context.ObjCBuiltinSelTy; - break; -#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ - case PREDEF_TYPE_##Id##_ID: \ - T = Context.SingletonId; \ - break; -#include "clang/Basic/OpenCLImageTypes.def" -#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ - case PREDEF_TYPE_##Id##_ID: \ - T = Context.Id##Ty; \ - break; -#include "clang/Basic/OpenCLExtensionTypes.def" - case PREDEF_TYPE_SAMPLER_ID: - T = Context.OCLSamplerTy; - break; - case PREDEF_TYPE_EVENT_ID: - T = Context.OCLEventTy; - break; - case PREDEF_TYPE_CLK_EVENT_ID: - T = Context.OCLClkEventTy; - break; - case PREDEF_TYPE_QUEUE_ID: - T = Context.OCLQueueTy; - break; - case PREDEF_TYPE_RESERVE_ID_ID: - T = Context.OCLReserveIDTy; - break; - case PREDEF_TYPE_AUTO_DEDUCT: - T = Context.getAutoDeductType(); - break; - case PREDEF_TYPE_AUTO_RREF_DEDUCT: - T = Context.getAutoRRefDeductType(); - break; - case PREDEF_TYPE_ARC_UNBRIDGED_CAST: - T = Context.ARCUnbridgedCastTy; - break; - case PREDEF_TYPE_BUILTIN_FN: - T = Context.BuiltinFnTy; - break; - case PREDEF_TYPE_OMP_ARRAY_SECTION: - T = Context.OMPArraySectionTy; - break; - } - - assert(!T.isNull() && "Unknown predefined type"); - return T.withFastQualifiers(FastQuals); - } - - Index -= NUM_PREDEF_TYPE_IDS; - assert(Index < TypesLoaded.size() && "Type index out-of-range"); - if (TypesLoaded[Index].isNull()) { - TypesLoaded[Index] = readTypeRecord(Index); - if (TypesLoaded[Index].isNull()) - return QualType(); - - TypesLoaded[Index]->setFromAST(); - if (DeserializationListener) - DeserializationListener->TypeRead(TypeIdx::fromTypeID(ID), - TypesLoaded[Index]); - } - - return TypesLoaded[Index].withFastQualifiers(FastQuals); -} - -QualType ASTReader::getLocalType(ModuleFile &F, unsigned LocalID) { - return GetType(getGlobalTypeID(F, LocalID)); -} - -serialization::TypeID -ASTReader::getGlobalTypeID(ModuleFile &F, unsigned LocalID) const { - unsigned FastQuals = LocalID & Qualifiers::FastMask; - unsigned LocalIndex = LocalID >> Qualifiers::FastWidth; - - if (LocalIndex < NUM_PREDEF_TYPE_IDS) - return LocalID; - - if (!F.ModuleOffsetMap.empty()) - ReadModuleOffsetMap(F); - - ContinuousRangeMap<uint32_t, int, 2>::iterator I - = F.TypeRemap.find(LocalIndex - NUM_PREDEF_TYPE_IDS); - assert(I != F.TypeRemap.end() && "Invalid index into type index remap"); - - unsigned GlobalIndex = LocalIndex + I->second; - return (GlobalIndex << Qualifiers::FastWidth) | FastQuals; -} - -TemplateArgumentLocInfo -ASTReader::GetTemplateArgumentLocInfo(ModuleFile &F, - TemplateArgument::ArgKind Kind, - const RecordData &Record, - unsigned &Index) { - switch (Kind) { - case TemplateArgument::Expression: - return ReadExpr(F); - case TemplateArgument::Type: - return GetTypeSourceInfo(F, Record, Index); - case TemplateArgument::Template: { - NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, - Index); - SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index); - return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc, - SourceLocation()); - } - case TemplateArgument::TemplateExpansion: { - NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, - Index); - SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index); - SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index); - return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc, - EllipsisLoc); - } - case TemplateArgument::Null: - case TemplateArgument::Integral: - case TemplateArgument::Declaration: - case TemplateArgument::NullPtr: - case TemplateArgument::Pack: - // FIXME: Is this right? - return TemplateArgumentLocInfo(); - } - llvm_unreachable("unexpected template argument loc"); -} - -TemplateArgumentLoc -ASTReader::ReadTemplateArgumentLoc(ModuleFile &F, - const RecordData &Record, unsigned &Index) { - TemplateArgument Arg = ReadTemplateArgument(F, Record, Index); - - if (Arg.getKind() == TemplateArgument::Expression) { - if (Record[Index++]) // bool InfoHasSameExpr. - return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo(Arg.getAsExpr())); - } - return TemplateArgumentLoc(Arg, GetTemplateArgumentLocInfo(F, Arg.getKind(), - Record, Index)); -} - -const ASTTemplateArgumentListInfo* -ASTReader::ReadASTTemplateArgumentListInfo(ModuleFile &F, - const RecordData &Record, - unsigned &Index) { - SourceLocation LAngleLoc = ReadSourceLocation(F, Record, Index); - SourceLocation RAngleLoc = ReadSourceLocation(F, Record, Index); - unsigned NumArgsAsWritten = Record[Index++]; - TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc); - for (unsigned i = 0; i != NumArgsAsWritten; ++i) - TemplArgsInfo.addArgument(ReadTemplateArgumentLoc(F, Record, Index)); - return ASTTemplateArgumentListInfo::Create(getContext(), TemplArgsInfo); -} - -Decl *ASTReader::GetExternalDecl(uint32_t ID) { - return GetDecl(ID); -} - -void ASTReader::CompleteRedeclChain(const Decl *D) { - if (NumCurrentElementsDeserializing) { - // We arrange to not care about the complete redeclaration chain while we're - // deserializing. Just remember that the AST has marked this one as complete - // but that it's not actually complete yet, so we know we still need to - // complete it later. - PendingIncompleteDeclChains.push_back(const_cast<Decl*>(D)); - return; - } - - const DeclContext *DC = D->getDeclContext()->getRedeclContext(); - - // If this is a named declaration, complete it by looking it up - // within its context. - // - // FIXME: Merging a function definition should merge - // all mergeable entities within it. - if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC) || - isa<CXXRecordDecl>(DC) || isa<EnumDecl>(DC)) { - if (DeclarationName Name = cast<NamedDecl>(D)->getDeclName()) { - if (!getContext().getLangOpts().CPlusPlus && - isa<TranslationUnitDecl>(DC)) { - // Outside of C++, we don't have a lookup table for the TU, so update - // the identifier instead. (For C++ modules, we don't store decls - // in the serialized identifier table, so we do the lookup in the TU.) - auto *II = Name.getAsIdentifierInfo(); - assert(II && "non-identifier name in C?"); - if (II->isOutOfDate()) - updateOutOfDateIdentifier(*II); - } else - DC->lookup(Name); - } else if (needsAnonymousDeclarationNumber(cast<NamedDecl>(D))) { - // Find all declarations of this kind from the relevant context. - for (auto *DCDecl : cast<Decl>(D->getLexicalDeclContext())->redecls()) { - auto *DC = cast<DeclContext>(DCDecl); - SmallVector<Decl*, 8> Decls; - FindExternalLexicalDecls( - DC, [&](Decl::Kind K) { return K == D->getKind(); }, Decls); - } - } - } - - if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) - CTSD->getSpecializedTemplate()->LoadLazySpecializations(); - if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D)) - VTSD->getSpecializedTemplate()->LoadLazySpecializations(); - if (auto *FD = dyn_cast<FunctionDecl>(D)) { - if (auto *Template = FD->getPrimaryTemplate()) - Template->LoadLazySpecializations(); - } -} - -CXXCtorInitializer ** -ASTReader::GetExternalCXXCtorInitializers(uint64_t Offset) { - RecordLocation Loc = getLocalBitOffset(Offset); - BitstreamCursor &Cursor = Loc.F->DeclsCursor; - SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(Loc.Offset); - ReadingKindTracker ReadingKind(Read_Decl, *this); - - RecordData Record; - unsigned Code = Cursor.ReadCode(); - unsigned RecCode = Cursor.readRecord(Code, Record); - if (RecCode != DECL_CXX_CTOR_INITIALIZERS) { - Error("malformed AST file: missing C++ ctor initializers"); - return nullptr; - } - - unsigned Idx = 0; - return ReadCXXCtorInitializers(*Loc.F, Record, Idx); -} - -CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { - assert(ContextObj && "reading base specifiers with no AST context"); - ASTContext &Context = *ContextObj; - - RecordLocation Loc = getLocalBitOffset(Offset); - BitstreamCursor &Cursor = Loc.F->DeclsCursor; - SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(Loc.Offset); - ReadingKindTracker ReadingKind(Read_Decl, *this); - RecordData Record; - unsigned Code = Cursor.ReadCode(); - unsigned RecCode = Cursor.readRecord(Code, Record); - if (RecCode != DECL_CXX_BASE_SPECIFIERS) { - Error("malformed AST file: missing C++ base specifiers"); - return nullptr; - } - - unsigned Idx = 0; - unsigned NumBases = Record[Idx++]; - void *Mem = Context.Allocate(sizeof(CXXBaseSpecifier) * NumBases); - CXXBaseSpecifier *Bases = new (Mem) CXXBaseSpecifier [NumBases]; - for (unsigned I = 0; I != NumBases; ++I) - Bases[I] = ReadCXXBaseSpecifier(*Loc.F, Record, Idx); - return Bases; -} - -serialization::DeclID -ASTReader::getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const { - if (LocalID < NUM_PREDEF_DECL_IDS) - return LocalID; - - if (!F.ModuleOffsetMap.empty()) - ReadModuleOffsetMap(F); - - ContinuousRangeMap<uint32_t, int, 2>::iterator I - = F.DeclRemap.find(LocalID - NUM_PREDEF_DECL_IDS); - assert(I != F.DeclRemap.end() && "Invalid index into decl index remap"); - - return LocalID + I->second; -} - -bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID, - ModuleFile &M) const { - // Predefined decls aren't from any module. - if (ID < NUM_PREDEF_DECL_IDS) - return false; - - return ID - NUM_PREDEF_DECL_IDS >= M.BaseDeclID && - ID - NUM_PREDEF_DECL_IDS < M.BaseDeclID + M.LocalNumDecls; -} - -ModuleFile *ASTReader::getOwningModuleFile(const Decl *D) { - if (!D->isFromASTFile()) - return nullptr; - GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(D->getGlobalID()); - assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); - return I->second; -} - -SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) { - if (ID < NUM_PREDEF_DECL_IDS) - return SourceLocation(); - - unsigned Index = ID - NUM_PREDEF_DECL_IDS; - - if (Index > DeclsLoaded.size()) { - Error("declaration ID out-of-range for AST file"); - return SourceLocation(); - } - - if (Decl *D = DeclsLoaded[Index]) - return D->getLocation(); - - SourceLocation Loc; - DeclCursorForID(ID, Loc); - return Loc; -} - -static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) { - switch (ID) { - case PREDEF_DECL_NULL_ID: - return nullptr; - - case PREDEF_DECL_TRANSLATION_UNIT_ID: - return Context.getTranslationUnitDecl(); - - case PREDEF_DECL_OBJC_ID_ID: - return Context.getObjCIdDecl(); - - case PREDEF_DECL_OBJC_SEL_ID: - return Context.getObjCSelDecl(); - - case PREDEF_DECL_OBJC_CLASS_ID: - return Context.getObjCClassDecl(); - - case PREDEF_DECL_OBJC_PROTOCOL_ID: - return Context.getObjCProtocolDecl(); - - case PREDEF_DECL_INT_128_ID: - return Context.getInt128Decl(); - - case PREDEF_DECL_UNSIGNED_INT_128_ID: - return Context.getUInt128Decl(); - - case PREDEF_DECL_OBJC_INSTANCETYPE_ID: - return Context.getObjCInstanceTypeDecl(); - - case PREDEF_DECL_BUILTIN_VA_LIST_ID: - return Context.getBuiltinVaListDecl(); - - case PREDEF_DECL_VA_LIST_TAG: - return Context.getVaListTagDecl(); - - case PREDEF_DECL_BUILTIN_MS_VA_LIST_ID: - return Context.getBuiltinMSVaListDecl(); - - case PREDEF_DECL_EXTERN_C_CONTEXT_ID: - return Context.getExternCContextDecl(); - - case PREDEF_DECL_MAKE_INTEGER_SEQ_ID: - return Context.getMakeIntegerSeqDecl(); - - case PREDEF_DECL_CF_CONSTANT_STRING_ID: - return Context.getCFConstantStringDecl(); - - case PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID: - return Context.getCFConstantStringTagDecl(); - - case PREDEF_DECL_TYPE_PACK_ELEMENT_ID: - return Context.getTypePackElementDecl(); - } - llvm_unreachable("PredefinedDeclIDs unknown enum value"); -} - -Decl *ASTReader::GetExistingDecl(DeclID ID) { - assert(ContextObj && "reading decl with no AST context"); - if (ID < NUM_PREDEF_DECL_IDS) { - Decl *D = getPredefinedDecl(*ContextObj, (PredefinedDeclIDs)ID); - if (D) { - // Track that we have merged the declaration with ID \p ID into the - // pre-existing predefined declaration \p D. - auto &Merged = KeyDecls[D->getCanonicalDecl()]; - if (Merged.empty()) - Merged.push_back(ID); - } - return D; - } - - unsigned Index = ID - NUM_PREDEF_DECL_IDS; - - if (Index >= DeclsLoaded.size()) { - assert(0 && "declaration ID out-of-range for AST file"); - Error("declaration ID out-of-range for AST file"); - return nullptr; - } - - return DeclsLoaded[Index]; -} - -Decl *ASTReader::GetDecl(DeclID ID) { - if (ID < NUM_PREDEF_DECL_IDS) - return GetExistingDecl(ID); - - unsigned Index = ID - NUM_PREDEF_DECL_IDS; - - if (Index >= DeclsLoaded.size()) { - assert(0 && "declaration ID out-of-range for AST file"); - Error("declaration ID out-of-range for AST file"); - return nullptr; - } - - if (!DeclsLoaded[Index]) { - ReadDeclRecord(ID); - if (DeserializationListener) - DeserializationListener->DeclRead(ID, DeclsLoaded[Index]); - } - - return DeclsLoaded[Index]; -} - -DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M, - DeclID GlobalID) { - if (GlobalID < NUM_PREDEF_DECL_IDS) - return GlobalID; - - GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(GlobalID); - assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); - ModuleFile *Owner = I->second; - - llvm::DenseMap<ModuleFile *, serialization::DeclID>::iterator Pos - = M.GlobalToLocalDeclIDs.find(Owner); - if (Pos == M.GlobalToLocalDeclIDs.end()) - return 0; - - return GlobalID - Owner->BaseDeclID + Pos->second; -} - -serialization::DeclID ASTReader::ReadDeclID(ModuleFile &F, - const RecordData &Record, - unsigned &Idx) { - if (Idx >= Record.size()) { - Error("Corrupted AST file"); - return 0; - } - - return getGlobalDeclID(F, Record[Idx++]); -} - -/// Resolve the offset of a statement into a statement. -/// -/// This operation will read a new statement from the external -/// source each time it is called, and is meant to be used via a -/// LazyOffsetPtr (which is used by Decls for the body of functions, etc). -Stmt *ASTReader::GetExternalDeclStmt(uint64_t Offset) { - // Switch case IDs are per Decl. - ClearSwitchCaseIDs(); - - // Offset here is a global offset across the entire chain. - RecordLocation Loc = getLocalBitOffset(Offset); - Loc.F->DeclsCursor.JumpToBit(Loc.Offset); - assert(NumCurrentElementsDeserializing == 0 && - "should not be called while already deserializing"); - Deserializing D(this); - return ReadStmtFromStream(*Loc.F); -} - -void ASTReader::FindExternalLexicalDecls( - const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, - SmallVectorImpl<Decl *> &Decls) { - bool PredefsVisited[NUM_PREDEF_DECL_IDS] = {}; - - auto Visit = [&] (ModuleFile *M, LexicalContents LexicalDecls) { - assert(LexicalDecls.size() % 2 == 0 && "expected an even number of entries"); - for (int I = 0, N = LexicalDecls.size(); I != N; I += 2) { - auto K = (Decl::Kind)+LexicalDecls[I]; - if (!IsKindWeWant(K)) - continue; - - auto ID = (serialization::DeclID)+LexicalDecls[I + 1]; - - // Don't add predefined declarations to the lexical context more - // than once. - if (ID < NUM_PREDEF_DECL_IDS) { - if (PredefsVisited[ID]) - continue; - - PredefsVisited[ID] = true; - } - - if (Decl *D = GetLocalDecl(*M, ID)) { - assert(D->getKind() == K && "wrong kind for lexical decl"); - if (!DC->isDeclInLexicalTraversal(D)) - Decls.push_back(D); - } - } - }; - - if (isa<TranslationUnitDecl>(DC)) { - for (auto Lexical : TULexicalDecls) - Visit(Lexical.first, Lexical.second); - } else { - auto I = LexicalDecls.find(DC); - if (I != LexicalDecls.end()) - Visit(I->second.first, I->second.second); - } - - ++NumLexicalDeclContextsRead; -} - -namespace { - -class DeclIDComp { - ASTReader &Reader; - ModuleFile &Mod; - -public: - DeclIDComp(ASTReader &Reader, ModuleFile &M) : Reader(Reader), Mod(M) {} - - bool operator()(LocalDeclID L, LocalDeclID R) const { - SourceLocation LHS = getLocation(L); - SourceLocation RHS = getLocation(R); - return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); - } - - bool operator()(SourceLocation LHS, LocalDeclID R) const { - SourceLocation RHS = getLocation(R); - return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); - } - - bool operator()(LocalDeclID L, SourceLocation RHS) const { - SourceLocation LHS = getLocation(L); - return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); - } - - SourceLocation getLocation(LocalDeclID ID) const { - return Reader.getSourceManager().getFileLoc( - Reader.getSourceLocationForDeclID(Reader.getGlobalDeclID(Mod, ID))); - } -}; - -} // namespace - -void ASTReader::FindFileRegionDecls(FileID File, - unsigned Offset, unsigned Length, - SmallVectorImpl<Decl *> &Decls) { - SourceManager &SM = getSourceManager(); - - llvm::DenseMap<FileID, FileDeclsInfo>::iterator I = FileDeclIDs.find(File); - if (I == FileDeclIDs.end()) - return; - - FileDeclsInfo &DInfo = I->second; - if (DInfo.Decls.empty()) - return; - - SourceLocation - BeginLoc = SM.getLocForStartOfFile(File).getLocWithOffset(Offset); - SourceLocation EndLoc = BeginLoc.getLocWithOffset(Length); - - DeclIDComp DIDComp(*this, *DInfo.Mod); - ArrayRef<serialization::LocalDeclID>::iterator - BeginIt = std::lower_bound(DInfo.Decls.begin(), DInfo.Decls.end(), - BeginLoc, DIDComp); - if (BeginIt != DInfo.Decls.begin()) - --BeginIt; - - // If we are pointing at a top-level decl inside an objc container, we need - // to backtrack until we find it otherwise we will fail to report that the - // region overlaps with an objc container. - while (BeginIt != DInfo.Decls.begin() && - GetDecl(getGlobalDeclID(*DInfo.Mod, *BeginIt)) - ->isTopLevelDeclInObjCContainer()) - --BeginIt; - - ArrayRef<serialization::LocalDeclID>::iterator - EndIt = std::upper_bound(DInfo.Decls.begin(), DInfo.Decls.end(), - EndLoc, DIDComp); - if (EndIt != DInfo.Decls.end()) - ++EndIt; - - for (ArrayRef<serialization::LocalDeclID>::iterator - DIt = BeginIt; DIt != EndIt; ++DIt) - Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt))); -} - -bool -ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, - DeclarationName Name) { - assert(DC->hasExternalVisibleStorage() && DC == DC->getPrimaryContext() && - "DeclContext has no visible decls in storage"); - if (!Name) - return false; - - auto It = Lookups.find(DC); - if (It == Lookups.end()) - return false; - - Deserializing LookupResults(this); - - // Load the list of declarations. - SmallVector<NamedDecl *, 64> Decls; - for (DeclID ID : It->second.Table.find(Name)) { - NamedDecl *ND = cast<NamedDecl>(GetDecl(ID)); - if (ND->getDeclName() == Name) - Decls.push_back(ND); - } - - ++NumVisibleDeclContextsRead; - SetExternalVisibleDeclsForName(DC, Name, Decls); - return !Decls.empty(); -} - -void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) { - if (!DC->hasExternalVisibleStorage()) - return; - - auto It = Lookups.find(DC); - assert(It != Lookups.end() && - "have external visible storage but no lookup tables"); - - DeclsMap Decls; - - for (DeclID ID : It->second.Table.findAll()) { - NamedDecl *ND = cast<NamedDecl>(GetDecl(ID)); - Decls[ND->getDeclName()].push_back(ND); - } - - ++NumVisibleDeclContextsRead; - - for (DeclsMap::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) { - SetExternalVisibleDeclsForName(DC, I->first, I->second); - } - const_cast<DeclContext *>(DC)->setHasExternalVisibleStorage(false); -} - -const serialization::reader::DeclContextLookupTable * -ASTReader::getLoadedLookupTables(DeclContext *Primary) const { - auto I = Lookups.find(Primary); - return I == Lookups.end() ? nullptr : &I->second; -} - -/// Under non-PCH compilation the consumer receives the objc methods -/// before receiving the implementation, and codegen depends on this. -/// We simulate this by deserializing and passing to consumer the methods of the -/// implementation before passing the deserialized implementation decl. -static void PassObjCImplDeclToConsumer(ObjCImplDecl *ImplD, - ASTConsumer *Consumer) { - assert(ImplD && Consumer); - - for (auto *I : ImplD->methods()) - Consumer->HandleInterestingDecl(DeclGroupRef(I)); - - Consumer->HandleInterestingDecl(DeclGroupRef(ImplD)); -} - -void ASTReader::PassInterestingDeclToConsumer(Decl *D) { - if (ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D)) - PassObjCImplDeclToConsumer(ImplD, Consumer); - else - Consumer->HandleInterestingDecl(DeclGroupRef(D)); -} - -void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) { - this->Consumer = Consumer; - - if (Consumer) - PassInterestingDeclsToConsumer(); - - if (DeserializationListener) - DeserializationListener->ReaderInitialized(this); -} - -void ASTReader::PrintStats() { - std::fprintf(stderr, "*** AST File Statistics:\n"); - - unsigned NumTypesLoaded - = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(), - QualType()); - unsigned NumDeclsLoaded - = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(), - (Decl *)nullptr); - unsigned NumIdentifiersLoaded - = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(), - IdentifiersLoaded.end(), - (IdentifierInfo *)nullptr); - unsigned NumMacrosLoaded - = MacrosLoaded.size() - std::count(MacrosLoaded.begin(), - MacrosLoaded.end(), - (MacroInfo *)nullptr); - unsigned NumSelectorsLoaded - = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(), - SelectorsLoaded.end(), - Selector()); - - if (unsigned TotalNumSLocEntries = getTotalNumSLocs()) - std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n", - NumSLocEntriesRead, TotalNumSLocEntries, - ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100)); - if (!TypesLoaded.empty()) - std::fprintf(stderr, " %u/%u types read (%f%%)\n", - NumTypesLoaded, (unsigned)TypesLoaded.size(), - ((float)NumTypesLoaded/TypesLoaded.size() * 100)); - if (!DeclsLoaded.empty()) - std::fprintf(stderr, " %u/%u declarations read (%f%%)\n", - NumDeclsLoaded, (unsigned)DeclsLoaded.size(), - ((float)NumDeclsLoaded/DeclsLoaded.size() * 100)); - if (!IdentifiersLoaded.empty()) - std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n", - NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(), - ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100)); - if (!MacrosLoaded.empty()) - std::fprintf(stderr, " %u/%u macros read (%f%%)\n", - NumMacrosLoaded, (unsigned)MacrosLoaded.size(), - ((float)NumMacrosLoaded/MacrosLoaded.size() * 100)); - if (!SelectorsLoaded.empty()) - std::fprintf(stderr, " %u/%u selectors read (%f%%)\n", - NumSelectorsLoaded, (unsigned)SelectorsLoaded.size(), - ((float)NumSelectorsLoaded/SelectorsLoaded.size() * 100)); - if (TotalNumStatements) - std::fprintf(stderr, " %u/%u statements read (%f%%)\n", - NumStatementsRead, TotalNumStatements, - ((float)NumStatementsRead/TotalNumStatements * 100)); - if (TotalNumMacros) - std::fprintf(stderr, " %u/%u macros read (%f%%)\n", - NumMacrosRead, TotalNumMacros, - ((float)NumMacrosRead/TotalNumMacros * 100)); - if (TotalLexicalDeclContexts) - std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n", - NumLexicalDeclContextsRead, TotalLexicalDeclContexts, - ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts - * 100)); - if (TotalVisibleDeclContexts) - std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n", - NumVisibleDeclContextsRead, TotalVisibleDeclContexts, - ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts - * 100)); - if (TotalNumMethodPoolEntries) - std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n", - NumMethodPoolEntriesRead, TotalNumMethodPoolEntries, - ((float)NumMethodPoolEntriesRead/TotalNumMethodPoolEntries - * 100)); - if (NumMethodPoolLookups) - std::fprintf(stderr, " %u/%u method pool lookups succeeded (%f%%)\n", - NumMethodPoolHits, NumMethodPoolLookups, - ((float)NumMethodPoolHits/NumMethodPoolLookups * 100.0)); - if (NumMethodPoolTableLookups) - std::fprintf(stderr, " %u/%u method pool table lookups succeeded (%f%%)\n", - NumMethodPoolTableHits, NumMethodPoolTableLookups, - ((float)NumMethodPoolTableHits/NumMethodPoolTableLookups - * 100.0)); - if (NumIdentifierLookupHits) - std::fprintf(stderr, - " %u / %u identifier table lookups succeeded (%f%%)\n", - NumIdentifierLookupHits, NumIdentifierLookups, - (double)NumIdentifierLookupHits*100.0/NumIdentifierLookups); - - if (GlobalIndex) { - std::fprintf(stderr, "\n"); - GlobalIndex->printStats(); - } - - std::fprintf(stderr, "\n"); - dump(); - std::fprintf(stderr, "\n"); -} - -template<typename Key, typename ModuleFile, unsigned InitialCapacity> -LLVM_DUMP_METHOD static void -dumpModuleIDMap(StringRef Name, - const ContinuousRangeMap<Key, ModuleFile *, - InitialCapacity> &Map) { - if (Map.begin() == Map.end()) - return; - - using MapType = ContinuousRangeMap<Key, ModuleFile *, InitialCapacity>; - - llvm::errs() << Name << ":\n"; - for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end(); - I != IEnd; ++I) { - llvm::errs() << " " << I->first << " -> " << I->second->FileName - << "\n"; - } -} - -LLVM_DUMP_METHOD void ASTReader::dump() { - llvm::errs() << "*** PCH/ModuleFile Remappings:\n"; - dumpModuleIDMap("Global bit offset map", GlobalBitOffsetsMap); - dumpModuleIDMap("Global source location entry map", GlobalSLocEntryMap); - dumpModuleIDMap("Global type map", GlobalTypeMap); - dumpModuleIDMap("Global declaration map", GlobalDeclMap); - dumpModuleIDMap("Global identifier map", GlobalIdentifierMap); - dumpModuleIDMap("Global macro map", GlobalMacroMap); - dumpModuleIDMap("Global submodule map", GlobalSubmoduleMap); - dumpModuleIDMap("Global selector map", GlobalSelectorMap); - dumpModuleIDMap("Global preprocessed entity map", - GlobalPreprocessedEntityMap); - - llvm::errs() << "\n*** PCH/Modules Loaded:"; - for (ModuleFile &M : ModuleMgr) - M.dump(); -} - -/// Return the amount of memory used by memory buffers, breaking down -/// by heap-backed versus mmap'ed memory. -void ASTReader::getMemoryBufferSizes(MemoryBufferSizes &sizes) const { - for (ModuleFile &I : ModuleMgr) { - if (llvm::MemoryBuffer *buf = I.Buffer) { - size_t bytes = buf->getBufferSize(); - switch (buf->getBufferKind()) { - case llvm::MemoryBuffer::MemoryBuffer_Malloc: - sizes.malloc_bytes += bytes; - break; - case llvm::MemoryBuffer::MemoryBuffer_MMap: - sizes.mmap_bytes += bytes; - break; - } - } - } -} - -void ASTReader::InitializeSema(Sema &S) { - SemaObj = &S; - S.addExternalSource(this); - - // Makes sure any declarations that were deserialized "too early" - // still get added to the identifier's declaration chains. - for (uint64_t ID : PreloadedDeclIDs) { - NamedDecl *D = cast<NamedDecl>(GetDecl(ID)); - pushExternalDeclIntoScope(D, D->getDeclName()); - } - PreloadedDeclIDs.clear(); - - // FIXME: What happens if these are changed by a module import? - if (!FPPragmaOptions.empty()) { - assert(FPPragmaOptions.size() == 1 && "Wrong number of FP_PRAGMA_OPTIONS"); - SemaObj->FPFeatures = FPOptions(FPPragmaOptions[0]); - } - - SemaObj->OpenCLFeatures.copy(OpenCLExtensions); - SemaObj->OpenCLTypeExtMap = OpenCLTypeExtMap; - SemaObj->OpenCLDeclExtMap = OpenCLDeclExtMap; - - UpdateSema(); -} - -void ASTReader::UpdateSema() { - assert(SemaObj && "no Sema to update"); - - // Load the offsets of the declarations that Sema references. - // They will be lazily deserialized when needed. - if (!SemaDeclRefs.empty()) { - assert(SemaDeclRefs.size() % 3 == 0); - for (unsigned I = 0; I != SemaDeclRefs.size(); I += 3) { - if (!SemaObj->StdNamespace) - SemaObj->StdNamespace = SemaDeclRefs[I]; - if (!SemaObj->StdBadAlloc) - SemaObj->StdBadAlloc = SemaDeclRefs[I+1]; - if (!SemaObj->StdAlignValT) - SemaObj->StdAlignValT = SemaDeclRefs[I+2]; - } - SemaDeclRefs.clear(); - } - - // Update the state of pragmas. Use the same API as if we had encountered the - // pragma in the source. - if(OptimizeOffPragmaLocation.isValid()) - SemaObj->ActOnPragmaOptimize(/* IsOn = */ false, OptimizeOffPragmaLocation); - if (PragmaMSStructState != -1) - SemaObj->ActOnPragmaMSStruct((PragmaMSStructKind)PragmaMSStructState); - if (PointersToMembersPragmaLocation.isValid()) { - SemaObj->ActOnPragmaMSPointersToMembers( - (LangOptions::PragmaMSPointersToMembersKind) - PragmaMSPointersToMembersState, - PointersToMembersPragmaLocation); - } - SemaObj->ForceCUDAHostDeviceDepth = ForceCUDAHostDeviceDepth; - - if (PragmaPackCurrentValue) { - // The bottom of the stack might have a default value. It must be adjusted - // to the current value to ensure that the packing state is preserved after - // popping entries that were included/imported from a PCH/module. - bool DropFirst = false; - if (!PragmaPackStack.empty() && - PragmaPackStack.front().Location.isInvalid()) { - assert(PragmaPackStack.front().Value == SemaObj->PackStack.DefaultValue && - "Expected a default alignment value"); - SemaObj->PackStack.Stack.emplace_back( - PragmaPackStack.front().SlotLabel, SemaObj->PackStack.CurrentValue, - SemaObj->PackStack.CurrentPragmaLocation, - PragmaPackStack.front().PushLocation); - DropFirst = true; - } - for (const auto &Entry : - llvm::makeArrayRef(PragmaPackStack).drop_front(DropFirst ? 1 : 0)) - SemaObj->PackStack.Stack.emplace_back(Entry.SlotLabel, Entry.Value, - Entry.Location, Entry.PushLocation); - if (PragmaPackCurrentLocation.isInvalid()) { - assert(*PragmaPackCurrentValue == SemaObj->PackStack.DefaultValue && - "Expected a default alignment value"); - // Keep the current values. - } else { - SemaObj->PackStack.CurrentValue = *PragmaPackCurrentValue; - SemaObj->PackStack.CurrentPragmaLocation = PragmaPackCurrentLocation; - } - } -} - -IdentifierInfo *ASTReader::get(StringRef Name) { - // Note that we are loading an identifier. - Deserializing AnIdentifier(this); - - IdentifierLookupVisitor Visitor(Name, /*PriorGeneration=*/0, - NumIdentifierLookups, - NumIdentifierLookupHits); - - // We don't need to do identifier table lookups in C++ modules (we preload - // all interesting declarations, and don't need to use the scope for name - // lookups). Perform the lookup in PCH files, though, since we don't build - // a complete initial identifier table if we're carrying on from a PCH. - if (PP.getLangOpts().CPlusPlus) { - for (auto F : ModuleMgr.pch_modules()) - if (Visitor(*F)) - break; - } else { - // If there is a global index, look there first to determine which modules - // provably do not have any results for this identifier. - GlobalModuleIndex::HitSet Hits; - GlobalModuleIndex::HitSet *HitsPtr = nullptr; - if (!loadGlobalIndex()) { - if (GlobalIndex->lookupIdentifier(Name, Hits)) { - HitsPtr = &Hits; - } - } - - ModuleMgr.visit(Visitor, HitsPtr); - } - - IdentifierInfo *II = Visitor.getIdentifierInfo(); - markIdentifierUpToDate(II); - return II; -} - -namespace clang { - - /// An identifier-lookup iterator that enumerates all of the - /// identifiers stored within a set of AST files. - class ASTIdentifierIterator : public IdentifierIterator { - /// The AST reader whose identifiers are being enumerated. - const ASTReader &Reader; - - /// The current index into the chain of AST files stored in - /// the AST reader. - unsigned Index; - - /// The current position within the identifier lookup table - /// of the current AST file. - ASTIdentifierLookupTable::key_iterator Current; - - /// The end position within the identifier lookup table of - /// the current AST file. - ASTIdentifierLookupTable::key_iterator End; - - /// Whether to skip any modules in the ASTReader. - bool SkipModules; - - public: - explicit ASTIdentifierIterator(const ASTReader &Reader, - bool SkipModules = false); - - StringRef Next() override; - }; - -} // namespace clang - -ASTIdentifierIterator::ASTIdentifierIterator(const ASTReader &Reader, - bool SkipModules) - : Reader(Reader), Index(Reader.ModuleMgr.size()), SkipModules(SkipModules) { -} - -StringRef ASTIdentifierIterator::Next() { - while (Current == End) { - // If we have exhausted all of our AST files, we're done. - if (Index == 0) - return StringRef(); - - --Index; - ModuleFile &F = Reader.ModuleMgr[Index]; - if (SkipModules && F.isModule()) - continue; - - ASTIdentifierLookupTable *IdTable = - (ASTIdentifierLookupTable *)F.IdentifierLookupTable; - Current = IdTable->key_begin(); - End = IdTable->key_end(); - } - - // We have any identifiers remaining in the current AST file; return - // the next one. - StringRef Result = *Current; - ++Current; - return Result; -} - -namespace { - -/// A utility for appending two IdentifierIterators. -class ChainedIdentifierIterator : public IdentifierIterator { - std::unique_ptr<IdentifierIterator> Current; - std::unique_ptr<IdentifierIterator> Queued; - -public: - ChainedIdentifierIterator(std::unique_ptr<IdentifierIterator> First, - std::unique_ptr<IdentifierIterator> Second) - : Current(std::move(First)), Queued(std::move(Second)) {} - - StringRef Next() override { - if (!Current) - return StringRef(); - - StringRef result = Current->Next(); - if (!result.empty()) - return result; - - // Try the queued iterator, which may itself be empty. - Current.reset(); - std::swap(Current, Queued); - return Next(); - } -}; - -} // namespace - -IdentifierIterator *ASTReader::getIdentifiers() { - if (!loadGlobalIndex()) { - std::unique_ptr<IdentifierIterator> ReaderIter( - new ASTIdentifierIterator(*this, /*SkipModules=*/true)); - std::unique_ptr<IdentifierIterator> ModulesIter( - GlobalIndex->createIdentifierIterator()); - return new ChainedIdentifierIterator(std::move(ReaderIter), - std::move(ModulesIter)); - } - - return new ASTIdentifierIterator(*this); -} - -namespace clang { -namespace serialization { - - class ReadMethodPoolVisitor { - ASTReader &Reader; - Selector Sel; - unsigned PriorGeneration; - unsigned InstanceBits = 0; - unsigned FactoryBits = 0; - bool InstanceHasMoreThanOneDecl = false; - bool FactoryHasMoreThanOneDecl = false; - SmallVector<ObjCMethodDecl *, 4> InstanceMethods; - SmallVector<ObjCMethodDecl *, 4> FactoryMethods; - - public: - ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel, - unsigned PriorGeneration) - : Reader(Reader), Sel(Sel), PriorGeneration(PriorGeneration) {} - - bool operator()(ModuleFile &M) { - if (!M.SelectorLookupTable) - return false; - - // If we've already searched this module file, skip it now. - if (M.Generation <= PriorGeneration) - return true; - - ++Reader.NumMethodPoolTableLookups; - ASTSelectorLookupTable *PoolTable - = (ASTSelectorLookupTable*)M.SelectorLookupTable; - ASTSelectorLookupTable::iterator Pos = PoolTable->find(Sel); - if (Pos == PoolTable->end()) - return false; - - ++Reader.NumMethodPoolTableHits; - ++Reader.NumSelectorsRead; - // FIXME: Not quite happy with the statistics here. We probably should - // disable this tracking when called via LoadSelector. - // Also, should entries without methods count as misses? - ++Reader.NumMethodPoolEntriesRead; - ASTSelectorLookupTrait::data_type Data = *Pos; - if (Reader.DeserializationListener) - Reader.DeserializationListener->SelectorRead(Data.ID, Sel); - - InstanceMethods.append(Data.Instance.begin(), Data.Instance.end()); - FactoryMethods.append(Data.Factory.begin(), Data.Factory.end()); - InstanceBits = Data.InstanceBits; - FactoryBits = Data.FactoryBits; - InstanceHasMoreThanOneDecl = Data.InstanceHasMoreThanOneDecl; - FactoryHasMoreThanOneDecl = Data.FactoryHasMoreThanOneDecl; - return true; - } - - /// Retrieve the instance methods found by this visitor. - ArrayRef<ObjCMethodDecl *> getInstanceMethods() const { - return InstanceMethods; - } - - /// Retrieve the instance methods found by this visitor. - ArrayRef<ObjCMethodDecl *> getFactoryMethods() const { - return FactoryMethods; - } - - unsigned getInstanceBits() const { return InstanceBits; } - unsigned getFactoryBits() const { return FactoryBits; } - - bool instanceHasMoreThanOneDecl() const { - return InstanceHasMoreThanOneDecl; - } - - bool factoryHasMoreThanOneDecl() const { return FactoryHasMoreThanOneDecl; } - }; - -} // namespace serialization -} // namespace clang - -/// Add the given set of methods to the method list. -static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> Methods, - ObjCMethodList &List) { - for (unsigned I = 0, N = Methods.size(); I != N; ++I) { - S.addMethodToGlobalList(&List, Methods[I]); - } -} - -void ASTReader::ReadMethodPool(Selector Sel) { - // Get the selector generation and update it to the current generation. - unsigned &Generation = SelectorGeneration[Sel]; - unsigned PriorGeneration = Generation; - Generation = getGeneration(); - SelectorOutOfDate[Sel] = false; - - // Search for methods defined with this selector. - ++NumMethodPoolLookups; - ReadMethodPoolVisitor Visitor(*this, Sel, PriorGeneration); - ModuleMgr.visit(Visitor); - - if (Visitor.getInstanceMethods().empty() && - Visitor.getFactoryMethods().empty()) - return; - - ++NumMethodPoolHits; - - if (!getSema()) - return; - - Sema &S = *getSema(); - Sema::GlobalMethodPool::iterator Pos - = S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethods())).first; - - Pos->second.first.setBits(Visitor.getInstanceBits()); - Pos->second.first.setHasMoreThanOneDecl(Visitor.instanceHasMoreThanOneDecl()); - Pos->second.second.setBits(Visitor.getFactoryBits()); - Pos->second.second.setHasMoreThanOneDecl(Visitor.factoryHasMoreThanOneDecl()); - - // Add methods to the global pool *after* setting hasMoreThanOneDecl, since - // when building a module we keep every method individually and may need to - // update hasMoreThanOneDecl as we add the methods. - addMethodsToPool(S, Visitor.getInstanceMethods(), Pos->second.first); - addMethodsToPool(S, Visitor.getFactoryMethods(), Pos->second.second); -} - -void ASTReader::updateOutOfDateSelector(Selector Sel) { - if (SelectorOutOfDate[Sel]) - ReadMethodPool(Sel); -} - -void ASTReader::ReadKnownNamespaces( - SmallVectorImpl<NamespaceDecl *> &Namespaces) { - Namespaces.clear(); - - for (unsigned I = 0, N = KnownNamespaces.size(); I != N; ++I) { - if (NamespaceDecl *Namespace - = dyn_cast_or_null<NamespaceDecl>(GetDecl(KnownNamespaces[I]))) - Namespaces.push_back(Namespace); - } -} - -void ASTReader::ReadUndefinedButUsed( - llvm::MapVector<NamedDecl *, SourceLocation> &Undefined) { - for (unsigned Idx = 0, N = UndefinedButUsed.size(); Idx != N;) { - NamedDecl *D = cast<NamedDecl>(GetDecl(UndefinedButUsed[Idx++])); - SourceLocation Loc = - SourceLocation::getFromRawEncoding(UndefinedButUsed[Idx++]); - Undefined.insert(std::make_pair(D, Loc)); - } -} - -void ASTReader::ReadMismatchingDeleteExpressions(llvm::MapVector< - FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> & - Exprs) { - for (unsigned Idx = 0, N = DelayedDeleteExprs.size(); Idx != N;) { - FieldDecl *FD = cast<FieldDecl>(GetDecl(DelayedDeleteExprs[Idx++])); - uint64_t Count = DelayedDeleteExprs[Idx++]; - for (uint64_t C = 0; C < Count; ++C) { - SourceLocation DeleteLoc = - SourceLocation::getFromRawEncoding(DelayedDeleteExprs[Idx++]); - const bool IsArrayForm = DelayedDeleteExprs[Idx++]; - Exprs[FD].push_back(std::make_pair(DeleteLoc, IsArrayForm)); - } - } -} - -void ASTReader::ReadTentativeDefinitions( - SmallVectorImpl<VarDecl *> &TentativeDefs) { - for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) { - VarDecl *Var = dyn_cast_or_null<VarDecl>(GetDecl(TentativeDefinitions[I])); - if (Var) - TentativeDefs.push_back(Var); - } - TentativeDefinitions.clear(); -} - -void ASTReader::ReadUnusedFileScopedDecls( - SmallVectorImpl<const DeclaratorDecl *> &Decls) { - for (unsigned I = 0, N = UnusedFileScopedDecls.size(); I != N; ++I) { - DeclaratorDecl *D - = dyn_cast_or_null<DeclaratorDecl>(GetDecl(UnusedFileScopedDecls[I])); - if (D) - Decls.push_back(D); - } - UnusedFileScopedDecls.clear(); -} - -void ASTReader::ReadDelegatingConstructors( - SmallVectorImpl<CXXConstructorDecl *> &Decls) { - for (unsigned I = 0, N = DelegatingCtorDecls.size(); I != N; ++I) { - CXXConstructorDecl *D - = dyn_cast_or_null<CXXConstructorDecl>(GetDecl(DelegatingCtorDecls[I])); - if (D) - Decls.push_back(D); - } - DelegatingCtorDecls.clear(); -} - -void ASTReader::ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) { - for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I) { - TypedefNameDecl *D - = dyn_cast_or_null<TypedefNameDecl>(GetDecl(ExtVectorDecls[I])); - if (D) - Decls.push_back(D); - } - ExtVectorDecls.clear(); -} - -void ASTReader::ReadUnusedLocalTypedefNameCandidates( - llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) { - for (unsigned I = 0, N = UnusedLocalTypedefNameCandidates.size(); I != N; - ++I) { - TypedefNameDecl *D = dyn_cast_or_null<TypedefNameDecl>( - GetDecl(UnusedLocalTypedefNameCandidates[I])); - if (D) - Decls.insert(D); - } - UnusedLocalTypedefNameCandidates.clear(); -} - -void ASTReader::ReadReferencedSelectors( - SmallVectorImpl<std::pair<Selector, SourceLocation>> &Sels) { - if (ReferencedSelectorsData.empty()) - return; - - // If there are @selector references added them to its pool. This is for - // implementation of -Wselector. - unsigned int DataSize = ReferencedSelectorsData.size()-1; - unsigned I = 0; - while (I < DataSize) { - Selector Sel = DecodeSelector(ReferencedSelectorsData[I++]); - SourceLocation SelLoc - = SourceLocation::getFromRawEncoding(ReferencedSelectorsData[I++]); - Sels.push_back(std::make_pair(Sel, SelLoc)); - } - ReferencedSelectorsData.clear(); -} - -void ASTReader::ReadWeakUndeclaredIdentifiers( - SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo>> &WeakIDs) { - if (WeakUndeclaredIdentifiers.empty()) - return; - - for (unsigned I = 0, N = WeakUndeclaredIdentifiers.size(); I < N; /*none*/) { - IdentifierInfo *WeakId - = DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]); - IdentifierInfo *AliasId - = DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]); - SourceLocation Loc - = SourceLocation::getFromRawEncoding(WeakUndeclaredIdentifiers[I++]); - bool Used = WeakUndeclaredIdentifiers[I++]; - WeakInfo WI(AliasId, Loc); - WI.setUsed(Used); - WeakIDs.push_back(std::make_pair(WeakId, WI)); - } - WeakUndeclaredIdentifiers.clear(); -} - -void ASTReader::ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) { - for (unsigned Idx = 0, N = VTableUses.size(); Idx < N; /* In loop */) { - ExternalVTableUse VT; - VT.Record = dyn_cast_or_null<CXXRecordDecl>(GetDecl(VTableUses[Idx++])); - VT.Location = SourceLocation::getFromRawEncoding(VTableUses[Idx++]); - VT.DefinitionRequired = VTableUses[Idx++]; - VTables.push_back(VT); - } - - VTableUses.clear(); -} - -void ASTReader::ReadPendingInstantiations( - SmallVectorImpl<std::pair<ValueDecl *, SourceLocation>> &Pending) { - for (unsigned Idx = 0, N = PendingInstantiations.size(); Idx < N;) { - ValueDecl *D = cast<ValueDecl>(GetDecl(PendingInstantiations[Idx++])); - SourceLocation Loc - = SourceLocation::getFromRawEncoding(PendingInstantiations[Idx++]); - - Pending.push_back(std::make_pair(D, Loc)); - } - PendingInstantiations.clear(); -} - -void ASTReader::ReadLateParsedTemplates( - llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>> - &LPTMap) { - for (unsigned Idx = 0, N = LateParsedTemplates.size(); Idx < N; - /* In loop */) { - FunctionDecl *FD = cast<FunctionDecl>(GetDecl(LateParsedTemplates[Idx++])); - - auto LT = llvm::make_unique<LateParsedTemplate>(); - LT->D = GetDecl(LateParsedTemplates[Idx++]); - - ModuleFile *F = getOwningModuleFile(LT->D); - assert(F && "No module"); - - unsigned TokN = LateParsedTemplates[Idx++]; - LT->Toks.reserve(TokN); - for (unsigned T = 0; T < TokN; ++T) - LT->Toks.push_back(ReadToken(*F, LateParsedTemplates, Idx)); - - LPTMap.insert(std::make_pair(FD, std::move(LT))); - } - - LateParsedTemplates.clear(); -} - -void ASTReader::LoadSelector(Selector Sel) { - // It would be complicated to avoid reading the methods anyway. So don't. - ReadMethodPool(Sel); -} - -void ASTReader::SetIdentifierInfo(IdentifierID ID, IdentifierInfo *II) { - assert(ID && "Non-zero identifier ID required"); - assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range"); - IdentifiersLoaded[ID - 1] = II; - if (DeserializationListener) - DeserializationListener->IdentifierRead(ID, II); -} - -/// Set the globally-visible declarations associated with the given -/// identifier. -/// -/// If the AST reader is currently in a state where the given declaration IDs -/// cannot safely be resolved, they are queued until it is safe to resolve -/// them. -/// -/// \param II an IdentifierInfo that refers to one or more globally-visible -/// declarations. -/// -/// \param DeclIDs the set of declaration IDs with the name @p II that are -/// visible at global scope. -/// -/// \param Decls if non-null, this vector will be populated with the set of -/// deserialized declarations. These declarations will not be pushed into -/// scope. -void -ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II, - const SmallVectorImpl<uint32_t> &DeclIDs, - SmallVectorImpl<Decl *> *Decls) { - if (NumCurrentElementsDeserializing && !Decls) { - PendingIdentifierInfos[II].append(DeclIDs.begin(), DeclIDs.end()); - return; - } - - for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) { - if (!SemaObj) { - // Queue this declaration so that it will be added to the - // translation unit scope and identifier's declaration chain - // once a Sema object is known. - PreloadedDeclIDs.push_back(DeclIDs[I]); - continue; - } - - NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I])); - - // If we're simply supposed to record the declarations, do so now. - if (Decls) { - Decls->push_back(D); - continue; - } - - // Introduce this declaration into the translation-unit scope - // and add it to the declaration chain for this identifier, so - // that (unqualified) name lookup will find it. - pushExternalDeclIntoScope(D, II); - } -} - -IdentifierInfo *ASTReader::DecodeIdentifierInfo(IdentifierID ID) { - if (ID == 0) - return nullptr; - - if (IdentifiersLoaded.empty()) { - Error("no identifier table in AST file"); - return nullptr; - } - - ID -= 1; - if (!IdentifiersLoaded[ID]) { - GlobalIdentifierMapType::iterator I = GlobalIdentifierMap.find(ID + 1); - assert(I != GlobalIdentifierMap.end() && "Corrupted global identifier map"); - ModuleFile *M = I->second; - unsigned Index = ID - M->BaseIdentifierID; - const char *Str = M->IdentifierTableData + M->IdentifierOffsets[Index]; - - // All of the strings in the AST file are preceded by a 16-bit length. - // Extract that 16-bit length to avoid having to execute strlen(). - // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as - // unsigned integers. This is important to avoid integer overflow when - // we cast them to 'unsigned'. - const unsigned char *StrLenPtr = (const unsigned char*) Str - 2; - unsigned StrLen = (((unsigned) StrLenPtr[0]) - | (((unsigned) StrLenPtr[1]) << 8)) - 1; - auto &II = PP.getIdentifierTable().get(StringRef(Str, StrLen)); - IdentifiersLoaded[ID] = &II; - markIdentifierFromAST(*this, II); - if (DeserializationListener) - DeserializationListener->IdentifierRead(ID + 1, &II); - } - - return IdentifiersLoaded[ID]; -} - -IdentifierInfo *ASTReader::getLocalIdentifier(ModuleFile &M, unsigned LocalID) { - return DecodeIdentifierInfo(getGlobalIdentifierID(M, LocalID)); -} - -IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, unsigned LocalID) { - if (LocalID < NUM_PREDEF_IDENT_IDS) - return LocalID; - - if (!M.ModuleOffsetMap.empty()) - ReadModuleOffsetMap(M); - - ContinuousRangeMap<uint32_t, int, 2>::iterator I - = M.IdentifierRemap.find(LocalID - NUM_PREDEF_IDENT_IDS); - assert(I != M.IdentifierRemap.end() - && "Invalid index into identifier index remap"); - - return LocalID + I->second; -} - -MacroInfo *ASTReader::getMacro(MacroID ID) { - if (ID == 0) - return nullptr; - - if (MacrosLoaded.empty()) { - Error("no macro table in AST file"); - return nullptr; - } - - ID -= NUM_PREDEF_MACRO_IDS; - if (!MacrosLoaded[ID]) { - GlobalMacroMapType::iterator I - = GlobalMacroMap.find(ID + NUM_PREDEF_MACRO_IDS); - assert(I != GlobalMacroMap.end() && "Corrupted global macro map"); - ModuleFile *M = I->second; - unsigned Index = ID - M->BaseMacroID; - MacrosLoaded[ID] = ReadMacroRecord(*M, M->MacroOffsets[Index]); - - if (DeserializationListener) - DeserializationListener->MacroRead(ID + NUM_PREDEF_MACRO_IDS, - MacrosLoaded[ID]); - } - - return MacrosLoaded[ID]; -} - -MacroID ASTReader::getGlobalMacroID(ModuleFile &M, unsigned LocalID) { - if (LocalID < NUM_PREDEF_MACRO_IDS) - return LocalID; - - if (!M.ModuleOffsetMap.empty()) - ReadModuleOffsetMap(M); - - ContinuousRangeMap<uint32_t, int, 2>::iterator I - = M.MacroRemap.find(LocalID - NUM_PREDEF_MACRO_IDS); - assert(I != M.MacroRemap.end() && "Invalid index into macro index remap"); - - return LocalID + I->second; -} - -serialization::SubmoduleID -ASTReader::getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID) { - if (LocalID < NUM_PREDEF_SUBMODULE_IDS) - return LocalID; - - if (!M.ModuleOffsetMap.empty()) - ReadModuleOffsetMap(M); - - ContinuousRangeMap<uint32_t, int, 2>::iterator I - = M.SubmoduleRemap.find(LocalID - NUM_PREDEF_SUBMODULE_IDS); - assert(I != M.SubmoduleRemap.end() - && "Invalid index into submodule index remap"); - - return LocalID + I->second; -} - -Module *ASTReader::getSubmodule(SubmoduleID GlobalID) { - if (GlobalID < NUM_PREDEF_SUBMODULE_IDS) { - assert(GlobalID == 0 && "Unhandled global submodule ID"); - return nullptr; - } - - if (GlobalID > SubmodulesLoaded.size()) { - Error("submodule ID out of range in AST file"); - return nullptr; - } - - return SubmodulesLoaded[GlobalID - NUM_PREDEF_SUBMODULE_IDS]; -} - -Module *ASTReader::getModule(unsigned ID) { - return getSubmodule(ID); -} - -bool ASTReader::DeclIsFromPCHWithObjectFile(const Decl *D) { - ModuleFile *MF = getOwningModuleFile(D); - return MF && MF->PCHHasObjectFile; -} - -ModuleFile *ASTReader::getLocalModuleFile(ModuleFile &F, unsigned ID) { - if (ID & 1) { - // It's a module, look it up by submodule ID. - auto I = GlobalSubmoduleMap.find(getGlobalSubmoduleID(F, ID >> 1)); - return I == GlobalSubmoduleMap.end() ? nullptr : I->second; - } else { - // It's a prefix (preamble, PCH, ...). Look it up by index. - unsigned IndexFromEnd = ID >> 1; - assert(IndexFromEnd && "got reference to unknown module file"); - return getModuleManager().pch_modules().end()[-IndexFromEnd]; - } -} - -unsigned ASTReader::getModuleFileID(ModuleFile *F) { - if (!F) - return 1; - - // For a file representing a module, use the submodule ID of the top-level - // module as the file ID. For any other kind of file, the number of such - // files loaded beforehand will be the same on reload. - // FIXME: Is this true even if we have an explicit module file and a PCH? - if (F->isModule()) - return ((F->BaseSubmoduleID + NUM_PREDEF_SUBMODULE_IDS) << 1) | 1; - - auto PCHModules = getModuleManager().pch_modules(); - auto I = std::find(PCHModules.begin(), PCHModules.end(), F); - assert(I != PCHModules.end() && "emitting reference to unknown file"); - return (I - PCHModules.end()) << 1; -} - -llvm::Optional<ExternalASTSource::ASTSourceDescriptor> -ASTReader::getSourceDescriptor(unsigned ID) { - if (const Module *M = getSubmodule(ID)) - return ExternalASTSource::ASTSourceDescriptor(*M); - - // If there is only a single PCH, return it instead. - // Chained PCH are not supported. - const auto &PCHChain = ModuleMgr.pch_modules(); - if (std::distance(std::begin(PCHChain), std::end(PCHChain))) { - ModuleFile &MF = ModuleMgr.getPrimaryModule(); - StringRef ModuleName = llvm::sys::path::filename(MF.OriginalSourceFileName); - StringRef FileName = llvm::sys::path::filename(MF.FileName); - return ASTReader::ASTSourceDescriptor(ModuleName, MF.OriginalDir, FileName, - MF.Signature); - } - return None; -} - -ExternalASTSource::ExtKind ASTReader::hasExternalDefinitions(const Decl *FD) { - auto I = DefinitionSource.find(FD); - if (I == DefinitionSource.end()) - return EK_ReplyHazy; - return I->second ? EK_Never : EK_Always; -} - -Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) { - return DecodeSelector(getGlobalSelectorID(M, LocalID)); -} - -Selector ASTReader::DecodeSelector(serialization::SelectorID ID) { - if (ID == 0) - return Selector(); - - if (ID > SelectorsLoaded.size()) { - Error("selector ID out of range in AST file"); - return Selector(); - } - - if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == nullptr) { - // Load this selector from the selector table. - GlobalSelectorMapType::iterator I = GlobalSelectorMap.find(ID); - assert(I != GlobalSelectorMap.end() && "Corrupted global selector map"); - ModuleFile &M = *I->second; - ASTSelectorLookupTrait Trait(*this, M); - unsigned Idx = ID - M.BaseSelectorID - NUM_PREDEF_SELECTOR_IDS; - SelectorsLoaded[ID - 1] = - Trait.ReadKey(M.SelectorLookupTableData + M.SelectorOffsets[Idx], 0); - if (DeserializationListener) - DeserializationListener->SelectorRead(ID, SelectorsLoaded[ID - 1]); - } - - return SelectorsLoaded[ID - 1]; -} - -Selector ASTReader::GetExternalSelector(serialization::SelectorID ID) { - return DecodeSelector(ID); -} - -uint32_t ASTReader::GetNumExternalSelectors() { - // ID 0 (the null selector) is considered an external selector. - return getTotalNumSelectors() + 1; -} - -serialization::SelectorID -ASTReader::getGlobalSelectorID(ModuleFile &M, unsigned LocalID) const { - if (LocalID < NUM_PREDEF_SELECTOR_IDS) - return LocalID; - - if (!M.ModuleOffsetMap.empty()) - ReadModuleOffsetMap(M); - - ContinuousRangeMap<uint32_t, int, 2>::iterator I - = M.SelectorRemap.find(LocalID - NUM_PREDEF_SELECTOR_IDS); - assert(I != M.SelectorRemap.end() - && "Invalid index into selector index remap"); - - return LocalID + I->second; -} - -DeclarationName -ASTReader::ReadDeclarationName(ModuleFile &F, - const RecordData &Record, unsigned &Idx) { - ASTContext &Context = getContext(); - DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++]; - switch (Kind) { - case DeclarationName::Identifier: - return DeclarationName(GetIdentifierInfo(F, Record, Idx)); - - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - return DeclarationName(ReadSelector(F, Record, Idx)); - - case DeclarationName::CXXConstructorName: - return Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(readType(F, Record, Idx))); - - case DeclarationName::CXXDestructorName: - return Context.DeclarationNames.getCXXDestructorName( - Context.getCanonicalType(readType(F, Record, Idx))); - - case DeclarationName::CXXDeductionGuideName: - return Context.DeclarationNames.getCXXDeductionGuideName( - ReadDeclAs<TemplateDecl>(F, Record, Idx)); - - case DeclarationName::CXXConversionFunctionName: - return Context.DeclarationNames.getCXXConversionFunctionName( - Context.getCanonicalType(readType(F, Record, Idx))); - - case DeclarationName::CXXOperatorName: - return Context.DeclarationNames.getCXXOperatorName( - (OverloadedOperatorKind)Record[Idx++]); - - case DeclarationName::CXXLiteralOperatorName: - return Context.DeclarationNames.getCXXLiteralOperatorName( - GetIdentifierInfo(F, Record, Idx)); - - case DeclarationName::CXXUsingDirective: - return DeclarationName::getUsingDirectiveName(); - } - - llvm_unreachable("Invalid NameKind!"); -} - -void ASTReader::ReadDeclarationNameLoc(ModuleFile &F, - DeclarationNameLoc &DNLoc, - DeclarationName Name, - const RecordData &Record, unsigned &Idx) { - switch (Name.getNameKind()) { - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - DNLoc.NamedType.TInfo = GetTypeSourceInfo(F, Record, Idx); - break; - - case DeclarationName::CXXOperatorName: - DNLoc.CXXOperatorName.BeginOpNameLoc - = ReadSourceLocation(F, Record, Idx).getRawEncoding(); - DNLoc.CXXOperatorName.EndOpNameLoc - = ReadSourceLocation(F, Record, Idx).getRawEncoding(); - break; - - case DeclarationName::CXXLiteralOperatorName: - DNLoc.CXXLiteralOperatorName.OpNameLoc - = ReadSourceLocation(F, Record, Idx).getRawEncoding(); - break; - - case DeclarationName::Identifier: - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - case DeclarationName::CXXUsingDirective: - case DeclarationName::CXXDeductionGuideName: - break; - } -} - -void ASTReader::ReadDeclarationNameInfo(ModuleFile &F, - DeclarationNameInfo &NameInfo, - const RecordData &Record, unsigned &Idx) { - NameInfo.setName(ReadDeclarationName(F, Record, Idx)); - NameInfo.setLoc(ReadSourceLocation(F, Record, Idx)); - DeclarationNameLoc DNLoc; - ReadDeclarationNameLoc(F, DNLoc, NameInfo.getName(), Record, Idx); - NameInfo.setInfo(DNLoc); -} - -void ASTReader::ReadQualifierInfo(ModuleFile &F, QualifierInfo &Info, - const RecordData &Record, unsigned &Idx) { - Info.QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, Idx); - unsigned NumTPLists = Record[Idx++]; - Info.NumTemplParamLists = NumTPLists; - if (NumTPLists) { - Info.TemplParamLists = - new (getContext()) TemplateParameterList *[NumTPLists]; - for (unsigned i = 0; i != NumTPLists; ++i) - Info.TemplParamLists[i] = ReadTemplateParameterList(F, Record, Idx); - } -} - -TemplateName -ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record, - unsigned &Idx) { - ASTContext &Context = getContext(); - TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++]; - switch (Kind) { - case TemplateName::Template: - return TemplateName(ReadDeclAs<TemplateDecl>(F, Record, Idx)); - - case TemplateName::OverloadedTemplate: { - unsigned size = Record[Idx++]; - UnresolvedSet<8> Decls; - while (size--) - Decls.addDecl(ReadDeclAs<NamedDecl>(F, Record, Idx)); - - return Context.getOverloadedTemplateName(Decls.begin(), Decls.end()); - } - - case TemplateName::QualifiedTemplate: { - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx); - bool hasTemplKeyword = Record[Idx++]; - TemplateDecl *Template = ReadDeclAs<TemplateDecl>(F, Record, Idx); - return Context.getQualifiedTemplateName(NNS, hasTemplKeyword, Template); - } - - case TemplateName::DependentTemplate: { - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx); - if (Record[Idx++]) // isIdentifier - return Context.getDependentTemplateName(NNS, - GetIdentifierInfo(F, Record, - Idx)); - return Context.getDependentTemplateName(NNS, - (OverloadedOperatorKind)Record[Idx++]); - } - - case TemplateName::SubstTemplateTemplateParm: { - TemplateTemplateParmDecl *param - = ReadDeclAs<TemplateTemplateParmDecl>(F, Record, Idx); - if (!param) return TemplateName(); - TemplateName replacement = ReadTemplateName(F, Record, Idx); - return Context.getSubstTemplateTemplateParm(param, replacement); - } - - case TemplateName::SubstTemplateTemplateParmPack: { - TemplateTemplateParmDecl *Param - = ReadDeclAs<TemplateTemplateParmDecl>(F, Record, Idx); - if (!Param) - return TemplateName(); - - TemplateArgument ArgPack = ReadTemplateArgument(F, Record, Idx); - if (ArgPack.getKind() != TemplateArgument::Pack) - return TemplateName(); - - return Context.getSubstTemplateTemplateParmPack(Param, ArgPack); - } - } - - llvm_unreachable("Unhandled template name kind!"); -} - -TemplateArgument ASTReader::ReadTemplateArgument(ModuleFile &F, - const RecordData &Record, - unsigned &Idx, - bool Canonicalize) { - ASTContext &Context = getContext(); - if (Canonicalize) { - // The caller wants a canonical template argument. Sometimes the AST only - // wants template arguments in canonical form (particularly as the template - // argument lists of template specializations) so ensure we preserve that - // canonical form across serialization. - TemplateArgument Arg = ReadTemplateArgument(F, Record, Idx, false); - return Context.getCanonicalTemplateArgument(Arg); - } - - TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++]; - switch (Kind) { - case TemplateArgument::Null: - return TemplateArgument(); - case TemplateArgument::Type: - return TemplateArgument(readType(F, Record, Idx)); - case TemplateArgument::Declaration: { - ValueDecl *D = ReadDeclAs<ValueDecl>(F, Record, Idx); - return TemplateArgument(D, readType(F, Record, Idx)); - } - case TemplateArgument::NullPtr: - return TemplateArgument(readType(F, Record, Idx), /*isNullPtr*/true); - case TemplateArgument::Integral: { - llvm::APSInt Value = ReadAPSInt(Record, Idx); - QualType T = readType(F, Record, Idx); - return TemplateArgument(Context, Value, T); - } - case TemplateArgument::Template: - return TemplateArgument(ReadTemplateName(F, Record, Idx)); - case TemplateArgument::TemplateExpansion: { - TemplateName Name = ReadTemplateName(F, Record, Idx); - Optional<unsigned> NumTemplateExpansions; - if (unsigned NumExpansions = Record[Idx++]) - NumTemplateExpansions = NumExpansions - 1; - return TemplateArgument(Name, NumTemplateExpansions); - } - case TemplateArgument::Expression: - return TemplateArgument(ReadExpr(F)); - case TemplateArgument::Pack: { - unsigned NumArgs = Record[Idx++]; - TemplateArgument *Args = new (Context) TemplateArgument[NumArgs]; - for (unsigned I = 0; I != NumArgs; ++I) - Args[I] = ReadTemplateArgument(F, Record, Idx); - return TemplateArgument(llvm::makeArrayRef(Args, NumArgs)); - } - } - - llvm_unreachable("Unhandled template argument kind!"); -} - -TemplateParameterList * -ASTReader::ReadTemplateParameterList(ModuleFile &F, - const RecordData &Record, unsigned &Idx) { - SourceLocation TemplateLoc = ReadSourceLocation(F, Record, Idx); - SourceLocation LAngleLoc = ReadSourceLocation(F, Record, Idx); - SourceLocation RAngleLoc = ReadSourceLocation(F, Record, Idx); - - unsigned NumParams = Record[Idx++]; - SmallVector<NamedDecl *, 16> Params; - Params.reserve(NumParams); - while (NumParams--) - Params.push_back(ReadDeclAs<NamedDecl>(F, Record, Idx)); - - // TODO: Concepts - TemplateParameterList *TemplateParams = TemplateParameterList::Create( - getContext(), TemplateLoc, LAngleLoc, Params, RAngleLoc, nullptr); - return TemplateParams; -} - -void -ASTReader:: -ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs, - ModuleFile &F, const RecordData &Record, - unsigned &Idx, bool Canonicalize) { - unsigned NumTemplateArgs = Record[Idx++]; - TemplArgs.reserve(NumTemplateArgs); - while (NumTemplateArgs--) - TemplArgs.push_back(ReadTemplateArgument(F, Record, Idx, Canonicalize)); -} - -/// Read a UnresolvedSet structure. -void ASTReader::ReadUnresolvedSet(ModuleFile &F, LazyASTUnresolvedSet &Set, - const RecordData &Record, unsigned &Idx) { - unsigned NumDecls = Record[Idx++]; - Set.reserve(getContext(), NumDecls); - while (NumDecls--) { - DeclID ID = ReadDeclID(F, Record, Idx); - AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; - Set.addLazyDecl(getContext(), ID, AS); - } -} - -CXXBaseSpecifier -ASTReader::ReadCXXBaseSpecifier(ModuleFile &F, - const RecordData &Record, unsigned &Idx) { - bool isVirtual = static_cast<bool>(Record[Idx++]); - bool isBaseOfClass = static_cast<bool>(Record[Idx++]); - AccessSpecifier AS = static_cast<AccessSpecifier>(Record[Idx++]); - bool inheritConstructors = static_cast<bool>(Record[Idx++]); - TypeSourceInfo *TInfo = GetTypeSourceInfo(F, Record, Idx); - SourceRange Range = ReadSourceRange(F, Record, Idx); - SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Idx); - CXXBaseSpecifier Result(Range, isVirtual, isBaseOfClass, AS, TInfo, - EllipsisLoc); - Result.setInheritConstructors(inheritConstructors); - return Result; -} - -CXXCtorInitializer ** -ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record, - unsigned &Idx) { - ASTContext &Context = getContext(); - unsigned NumInitializers = Record[Idx++]; - assert(NumInitializers && "wrote ctor initializers but have no inits"); - auto **CtorInitializers = new (Context) CXXCtorInitializer*[NumInitializers]; - for (unsigned i = 0; i != NumInitializers; ++i) { - TypeSourceInfo *TInfo = nullptr; - bool IsBaseVirtual = false; - FieldDecl *Member = nullptr; - IndirectFieldDecl *IndirectMember = nullptr; - - CtorInitializerType Type = (CtorInitializerType)Record[Idx++]; - switch (Type) { - case CTOR_INITIALIZER_BASE: - TInfo = GetTypeSourceInfo(F, Record, Idx); - IsBaseVirtual = Record[Idx++]; - break; - - case CTOR_INITIALIZER_DELEGATING: - TInfo = GetTypeSourceInfo(F, Record, Idx); - break; - - case CTOR_INITIALIZER_MEMBER: - Member = ReadDeclAs<FieldDecl>(F, Record, Idx); - break; - - case CTOR_INITIALIZER_INDIRECT_MEMBER: - IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx); - break; - } - - SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx); - Expr *Init = ReadExpr(F); - SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx); - SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx); - - CXXCtorInitializer *BOMInit; - if (Type == CTOR_INITIALIZER_BASE) - BOMInit = new (Context) - CXXCtorInitializer(Context, TInfo, IsBaseVirtual, LParenLoc, Init, - RParenLoc, MemberOrEllipsisLoc); - else if (Type == CTOR_INITIALIZER_DELEGATING) - BOMInit = new (Context) - CXXCtorInitializer(Context, TInfo, LParenLoc, Init, RParenLoc); - else if (Member) - BOMInit = new (Context) - CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc, LParenLoc, - Init, RParenLoc); - else - BOMInit = new (Context) - CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc, - LParenLoc, Init, RParenLoc); - - if (/*IsWritten*/Record[Idx++]) { - unsigned SourceOrder = Record[Idx++]; - BOMInit->setSourceOrder(SourceOrder); - } - - CtorInitializers[i] = BOMInit; - } - - return CtorInitializers; -} - -NestedNameSpecifier * -ASTReader::ReadNestedNameSpecifier(ModuleFile &F, - const RecordData &Record, unsigned &Idx) { - ASTContext &Context = getContext(); - unsigned N = Record[Idx++]; - NestedNameSpecifier *NNS = nullptr, *Prev = nullptr; - for (unsigned I = 0; I != N; ++I) { - NestedNameSpecifier::SpecifierKind Kind - = (NestedNameSpecifier::SpecifierKind)Record[Idx++]; - switch (Kind) { - case NestedNameSpecifier::Identifier: { - IdentifierInfo *II = GetIdentifierInfo(F, Record, Idx); - NNS = NestedNameSpecifier::Create(Context, Prev, II); - break; - } - - case NestedNameSpecifier::Namespace: { - NamespaceDecl *NS = ReadDeclAs<NamespaceDecl>(F, Record, Idx); - NNS = NestedNameSpecifier::Create(Context, Prev, NS); - break; - } - - case NestedNameSpecifier::NamespaceAlias: { - NamespaceAliasDecl *Alias =ReadDeclAs<NamespaceAliasDecl>(F, Record, Idx); - NNS = NestedNameSpecifier::Create(Context, Prev, Alias); - break; - } - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { - const Type *T = readType(F, Record, Idx).getTypePtrOrNull(); - if (!T) - return nullptr; - - bool Template = Record[Idx++]; - NNS = NestedNameSpecifier::Create(Context, Prev, Template, T); - break; - } - - case NestedNameSpecifier::Global: - NNS = NestedNameSpecifier::GlobalSpecifier(Context); - // No associated value, and there can't be a prefix. - break; - - case NestedNameSpecifier::Super: { - CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(F, Record, Idx); - NNS = NestedNameSpecifier::SuperSpecifier(Context, RD); - break; - } - } - Prev = NNS; - } - return NNS; -} - -NestedNameSpecifierLoc -ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record, - unsigned &Idx) { - ASTContext &Context = getContext(); - unsigned N = Record[Idx++]; - NestedNameSpecifierLocBuilder Builder; - for (unsigned I = 0; I != N; ++I) { - NestedNameSpecifier::SpecifierKind Kind - = (NestedNameSpecifier::SpecifierKind)Record[Idx++]; - switch (Kind) { - case NestedNameSpecifier::Identifier: { - IdentifierInfo *II = GetIdentifierInfo(F, Record, Idx); - SourceRange Range = ReadSourceRange(F, Record, Idx); - Builder.Extend(Context, II, Range.getBegin(), Range.getEnd()); - break; - } - - case NestedNameSpecifier::Namespace: { - NamespaceDecl *NS = ReadDeclAs<NamespaceDecl>(F, Record, Idx); - SourceRange Range = ReadSourceRange(F, Record, Idx); - Builder.Extend(Context, NS, Range.getBegin(), Range.getEnd()); - break; - } - - case NestedNameSpecifier::NamespaceAlias: { - NamespaceAliasDecl *Alias =ReadDeclAs<NamespaceAliasDecl>(F, Record, Idx); - SourceRange Range = ReadSourceRange(F, Record, Idx); - Builder.Extend(Context, Alias, Range.getBegin(), Range.getEnd()); - break; - } - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { - bool Template = Record[Idx++]; - TypeSourceInfo *T = GetTypeSourceInfo(F, Record, Idx); - if (!T) - return NestedNameSpecifierLoc(); - SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx); - - // FIXME: 'template' keyword location not saved anywhere, so we fake it. - Builder.Extend(Context, - Template? T->getTypeLoc().getBeginLoc() : SourceLocation(), - T->getTypeLoc(), ColonColonLoc); - break; - } - - case NestedNameSpecifier::Global: { - SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx); - Builder.MakeGlobal(Context, ColonColonLoc); - break; - } - - case NestedNameSpecifier::Super: { - CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(F, Record, Idx); - SourceRange Range = ReadSourceRange(F, Record, Idx); - Builder.MakeSuper(Context, RD, Range.getBegin(), Range.getEnd()); - break; - } - } - } - - return Builder.getWithLocInContext(Context); -} - -SourceRange -ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record, - unsigned &Idx) { - SourceLocation beg = ReadSourceLocation(F, Record, Idx); - SourceLocation end = ReadSourceLocation(F, Record, Idx); - return SourceRange(beg, end); -} - -/// Read an integral value -llvm::APInt ASTReader::ReadAPInt(const RecordData &Record, unsigned &Idx) { - unsigned BitWidth = Record[Idx++]; - unsigned NumWords = llvm::APInt::getNumWords(BitWidth); - llvm::APInt Result(BitWidth, NumWords, &Record[Idx]); - Idx += NumWords; - return Result; -} - -/// Read a signed integral value -llvm::APSInt ASTReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) { - bool isUnsigned = Record[Idx++]; - return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned); -} - -/// Read a floating-point value -llvm::APFloat ASTReader::ReadAPFloat(const RecordData &Record, - const llvm::fltSemantics &Sem, - unsigned &Idx) { - return llvm::APFloat(Sem, ReadAPInt(Record, Idx)); -} - -// Read a string -std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) { - unsigned Len = Record[Idx++]; - std::string Result(Record.data() + Idx, Record.data() + Idx + Len); - Idx += Len; - return Result; -} - -std::string ASTReader::ReadPath(ModuleFile &F, const RecordData &Record, - unsigned &Idx) { - std::string Filename = ReadString(Record, Idx); - ResolveImportedPath(F, Filename); - return Filename; -} - -VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record, - unsigned &Idx) { - unsigned Major = Record[Idx++]; - unsigned Minor = Record[Idx++]; - unsigned Subminor = Record[Idx++]; - if (Minor == 0) - return VersionTuple(Major); - if (Subminor == 0) - return VersionTuple(Major, Minor - 1); - return VersionTuple(Major, Minor - 1, Subminor - 1); -} - -CXXTemporary *ASTReader::ReadCXXTemporary(ModuleFile &F, - const RecordData &Record, - unsigned &Idx) { - CXXDestructorDecl *Decl = ReadDeclAs<CXXDestructorDecl>(F, Record, Idx); - return CXXTemporary::Create(getContext(), Decl); -} - -DiagnosticBuilder ASTReader::Diag(unsigned DiagID) const { - return Diag(CurrentImportLoc, DiagID); -} - -DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) const { - return Diags.Report(Loc, DiagID); -} - -/// Retrieve the identifier table associated with the -/// preprocessor. -IdentifierTable &ASTReader::getIdentifierTable() { - return PP.getIdentifierTable(); -} - -/// Record that the given ID maps to the given switch-case -/// statement. -void ASTReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) { - assert((*CurrSwitchCaseStmts)[ID] == nullptr && - "Already have a SwitchCase with this ID"); - (*CurrSwitchCaseStmts)[ID] = SC; -} - -/// Retrieve the switch-case statement with the given ID. -SwitchCase *ASTReader::getSwitchCaseWithID(unsigned ID) { - assert((*CurrSwitchCaseStmts)[ID] != nullptr && "No SwitchCase with this ID"); - return (*CurrSwitchCaseStmts)[ID]; -} - -void ASTReader::ClearSwitchCaseIDs() { - CurrSwitchCaseStmts->clear(); -} - -void ASTReader::ReadComments() { - ASTContext &Context = getContext(); - std::vector<RawComment *> Comments; - for (SmallVectorImpl<std::pair<BitstreamCursor, - serialization::ModuleFile *>>::iterator - I = CommentsCursors.begin(), - E = CommentsCursors.end(); - I != E; ++I) { - Comments.clear(); - BitstreamCursor &Cursor = I->first; - serialization::ModuleFile &F = *I->second; - SavedStreamPosition SavedPosition(Cursor); - - RecordData Record; - while (true) { - llvm::BitstreamEntry Entry = - Cursor.advanceSkippingSubblocks(BitstreamCursor::AF_DontPopBlockAtEnd); - - switch (Entry.Kind) { - case llvm::BitstreamEntry::SubBlock: // Handled for us already. - case llvm::BitstreamEntry::Error: - Error("malformed block record in AST file"); - return; - case llvm::BitstreamEntry::EndBlock: - goto NextCursor; - case llvm::BitstreamEntry::Record: - // The interesting case. - break; - } - - // Read a record. - Record.clear(); - switch ((CommentRecordTypes)Cursor.readRecord(Entry.ID, Record)) { - case COMMENTS_RAW_COMMENT: { - unsigned Idx = 0; - SourceRange SR = ReadSourceRange(F, Record, Idx); - RawComment::CommentKind Kind = - (RawComment::CommentKind) Record[Idx++]; - bool IsTrailingComment = Record[Idx++]; - bool IsAlmostTrailingComment = Record[Idx++]; - Comments.push_back(new (Context) RawComment( - SR, Kind, IsTrailingComment, IsAlmostTrailingComment)); - break; - } - } - } - NextCursor: - // De-serialized SourceLocations get negative FileIDs for other modules, - // potentially invalidating the original order. Sort it again. - llvm::sort(Comments, BeforeThanCompare<RawComment>(SourceMgr)); - Context.Comments.addDeserializedComments(Comments); - } -} - -void ASTReader::visitInputFiles(serialization::ModuleFile &MF, - bool IncludeSystem, bool Complain, - llvm::function_ref<void(const serialization::InputFile &IF, - bool isSystem)> Visitor) { - unsigned NumUserInputs = MF.NumUserInputFiles; - unsigned NumInputs = MF.InputFilesLoaded.size(); - assert(NumUserInputs <= NumInputs); - unsigned N = IncludeSystem ? NumInputs : NumUserInputs; - for (unsigned I = 0; I < N; ++I) { - bool IsSystem = I >= NumUserInputs; - InputFile IF = getInputFile(MF, I+1, Complain); - Visitor(IF, IsSystem); - } -} - -void ASTReader::visitTopLevelModuleMaps( - serialization::ModuleFile &MF, - llvm::function_ref<void(const FileEntry *FE)> Visitor) { - unsigned NumInputs = MF.InputFilesLoaded.size(); - for (unsigned I = 0; I < NumInputs; ++I) { - InputFileInfo IFI = readInputFileInfo(MF, I + 1); - if (IFI.TopLevelModuleMap) - // FIXME: This unnecessarily re-reads the InputFileInfo. - if (auto *FE = getInputFile(MF, I + 1).getFile()) - Visitor(FE); - } -} - -std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) { - // If we know the owning module, use it. - if (Module *M = D->getImportedOwningModule()) - return M->getFullModuleName(); - - // Otherwise, use the name of the top-level module the decl is within. - if (ModuleFile *M = getOwningModuleFile(D)) - return M->ModuleName; - - // Not from a module. - return {}; -} - -void ASTReader::finishPendingActions() { - while (!PendingIdentifierInfos.empty() || !PendingFunctionTypes.empty() || - !PendingIncompleteDeclChains.empty() || !PendingDeclChains.empty() || - !PendingMacroIDs.empty() || !PendingDeclContextInfos.empty() || - !PendingUpdateRecords.empty()) { - // If any identifiers with corresponding top-level declarations have - // been loaded, load those declarations now. - using TopLevelDeclsMap = - llvm::DenseMap<IdentifierInfo *, SmallVector<Decl *, 2>>; - TopLevelDeclsMap TopLevelDecls; - - while (!PendingIdentifierInfos.empty()) { - IdentifierInfo *II = PendingIdentifierInfos.back().first; - SmallVector<uint32_t, 4> DeclIDs = - std::move(PendingIdentifierInfos.back().second); - PendingIdentifierInfos.pop_back(); - - SetGloballyVisibleDecls(II, DeclIDs, &TopLevelDecls[II]); - } - - // Load each function type that we deferred loading because it was a - // deduced type that might refer to a local type declared within itself. - for (unsigned I = 0; I != PendingFunctionTypes.size(); ++I) { - auto *FD = PendingFunctionTypes[I].first; - FD->setType(GetType(PendingFunctionTypes[I].second)); - - // If we gave a function a deduced return type, remember that we need to - // propagate that along the redeclaration chain. - auto *DT = FD->getReturnType()->getContainedDeducedType(); - if (DT && DT->isDeduced()) - PendingDeducedTypeUpdates.insert( - {FD->getCanonicalDecl(), FD->getReturnType()}); - } - PendingFunctionTypes.clear(); - - // For each decl chain that we wanted to complete while deserializing, mark - // it as "still needs to be completed". - for (unsigned I = 0; I != PendingIncompleteDeclChains.size(); ++I) { - markIncompleteDeclChain(PendingIncompleteDeclChains[I]); - } - PendingIncompleteDeclChains.clear(); - - // Load pending declaration chains. - for (unsigned I = 0; I != PendingDeclChains.size(); ++I) - loadPendingDeclChain(PendingDeclChains[I].first, - PendingDeclChains[I].second); - PendingDeclChains.clear(); - - // Make the most recent of the top-level declarations visible. - for (TopLevelDeclsMap::iterator TLD = TopLevelDecls.begin(), - TLDEnd = TopLevelDecls.end(); TLD != TLDEnd; ++TLD) { - IdentifierInfo *II = TLD->first; - for (unsigned I = 0, N = TLD->second.size(); I != N; ++I) { - pushExternalDeclIntoScope(cast<NamedDecl>(TLD->second[I]), II); - } - } - - // Load any pending macro definitions. - for (unsigned I = 0; I != PendingMacroIDs.size(); ++I) { - IdentifierInfo *II = PendingMacroIDs.begin()[I].first; - SmallVector<PendingMacroInfo, 2> GlobalIDs; - GlobalIDs.swap(PendingMacroIDs.begin()[I].second); - // Initialize the macro history from chained-PCHs ahead of module imports. - for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; - ++IDIdx) { - const PendingMacroInfo &Info = GlobalIDs[IDIdx]; - if (!Info.M->isModule()) - resolvePendingMacro(II, Info); - } - // Handle module imports. - for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; - ++IDIdx) { - const PendingMacroInfo &Info = GlobalIDs[IDIdx]; - if (Info.M->isModule()) - resolvePendingMacro(II, Info); - } - } - PendingMacroIDs.clear(); - - // Wire up the DeclContexts for Decls that we delayed setting until - // recursive loading is completed. - while (!PendingDeclContextInfos.empty()) { - PendingDeclContextInfo Info = PendingDeclContextInfos.front(); - PendingDeclContextInfos.pop_front(); - DeclContext *SemaDC = cast<DeclContext>(GetDecl(Info.SemaDC)); - DeclContext *LexicalDC = cast<DeclContext>(GetDecl(Info.LexicalDC)); - Info.D->setDeclContextsImpl(SemaDC, LexicalDC, getContext()); - } - - // Perform any pending declaration updates. - while (!PendingUpdateRecords.empty()) { - auto Update = PendingUpdateRecords.pop_back_val(); - ReadingKindTracker ReadingKind(Read_Decl, *this); - loadDeclUpdateRecords(Update); - } - } - - // At this point, all update records for loaded decls are in place, so any - // fake class definitions should have become real. - assert(PendingFakeDefinitionData.empty() && - "faked up a class definition but never saw the real one"); - - // If we deserialized any C++ or Objective-C class definitions, any - // Objective-C protocol definitions, or any redeclarable templates, make sure - // that all redeclarations point to the definitions. Note that this can only - // happen now, after the redeclaration chains have been fully wired. - for (Decl *D : PendingDefinitions) { - if (TagDecl *TD = dyn_cast<TagDecl>(D)) { - if (const TagType *TagT = dyn_cast<TagType>(TD->getTypeForDecl())) { - // Make sure that the TagType points at the definition. - const_cast<TagType*>(TagT)->decl = TD; - } - - if (auto RD = dyn_cast<CXXRecordDecl>(D)) { - for (auto *R = getMostRecentExistingDecl(RD); R; - R = R->getPreviousDecl()) { - assert((R == D) == - cast<CXXRecordDecl>(R)->isThisDeclarationADefinition() && - "declaration thinks it's the definition but it isn't"); - cast<CXXRecordDecl>(R)->DefinitionData = RD->DefinitionData; - } - } - - continue; - } - - if (auto ID = dyn_cast<ObjCInterfaceDecl>(D)) { - // Make sure that the ObjCInterfaceType points at the definition. - const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl)) - ->Decl = ID; - - for (auto *R = getMostRecentExistingDecl(ID); R; R = R->getPreviousDecl()) - cast<ObjCInterfaceDecl>(R)->Data = ID->Data; - - continue; - } - - if (auto PD = dyn_cast<ObjCProtocolDecl>(D)) { - for (auto *R = getMostRecentExistingDecl(PD); R; R = R->getPreviousDecl()) - cast<ObjCProtocolDecl>(R)->Data = PD->Data; - - continue; - } - - auto RTD = cast<RedeclarableTemplateDecl>(D)->getCanonicalDecl(); - for (auto *R = getMostRecentExistingDecl(RTD); R; R = R->getPreviousDecl()) - cast<RedeclarableTemplateDecl>(R)->Common = RTD->Common; - } - PendingDefinitions.clear(); - - // Load the bodies of any functions or methods we've encountered. We do - // this now (delayed) so that we can be sure that the declaration chains - // have been fully wired up (hasBody relies on this). - // FIXME: We shouldn't require complete redeclaration chains here. - for (PendingBodiesMap::iterator PB = PendingBodies.begin(), - PBEnd = PendingBodies.end(); - PB != PBEnd; ++PB) { - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(PB->first)) { - // For a function defined inline within a class template, force the - // canonical definition to be the one inside the canonical definition of - // the template. This ensures that we instantiate from a correct view - // of the template. - // - // Sadly we can't do this more generally: we can't be sure that all - // copies of an arbitrary class definition will have the same members - // defined (eg, some member functions may not be instantiated, and some - // special members may or may not have been implicitly defined). - if (auto *RD = dyn_cast<CXXRecordDecl>(FD->getLexicalParent())) - if (RD->isDependentContext() && !RD->isThisDeclarationADefinition()) - continue; - - // FIXME: Check for =delete/=default? - // FIXME: Complain about ODR violations here? - const FunctionDecl *Defn = nullptr; - if (!getContext().getLangOpts().Modules || !FD->hasBody(Defn)) { - FD->setLazyBody(PB->second); - } else { - auto *NonConstDefn = const_cast<FunctionDecl*>(Defn); - mergeDefinitionVisibility(NonConstDefn, FD); - - if (!FD->isLateTemplateParsed() && - !NonConstDefn->isLateTemplateParsed() && - FD->getODRHash() != NonConstDefn->getODRHash()) { - if (!isa<CXXMethodDecl>(FD)) { - PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn); - } else if (FD->getLexicalParent()->isFileContext() && - NonConstDefn->getLexicalParent()->isFileContext()) { - // Only diagnose out-of-line method definitions. If they are - // in class definitions, then an error will be generated when - // processing the class bodies. - PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn); - } - } - } - continue; - } - - ObjCMethodDecl *MD = cast<ObjCMethodDecl>(PB->first); - if (!getContext().getLangOpts().Modules || !MD->hasBody()) - MD->setLazyBody(PB->second); - } - PendingBodies.clear(); - - // Do some cleanup. - for (auto *ND : PendingMergedDefinitionsToDeduplicate) - getContext().deduplicateMergedDefinitonsFor(ND); - PendingMergedDefinitionsToDeduplicate.clear(); -} - -void ASTReader::diagnoseOdrViolations() { - if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty() && - PendingFunctionOdrMergeFailures.empty() && - PendingEnumOdrMergeFailures.empty()) - return; - - // Trigger the import of the full definition of each class that had any - // odr-merging problems, so we can produce better diagnostics for them. - // These updates may in turn find and diagnose some ODR failures, so take - // ownership of the set first. - auto OdrMergeFailures = std::move(PendingOdrMergeFailures); - PendingOdrMergeFailures.clear(); - for (auto &Merge : OdrMergeFailures) { - Merge.first->buildLookup(); - Merge.first->decls_begin(); - Merge.first->bases_begin(); - Merge.first->vbases_begin(); - for (auto &RecordPair : Merge.second) { - auto *RD = RecordPair.first; - RD->decls_begin(); - RD->bases_begin(); - RD->vbases_begin(); - } - } - - // Trigger the import of functions. - auto FunctionOdrMergeFailures = std::move(PendingFunctionOdrMergeFailures); - PendingFunctionOdrMergeFailures.clear(); - for (auto &Merge : FunctionOdrMergeFailures) { - Merge.first->buildLookup(); - Merge.first->decls_begin(); - Merge.first->getBody(); - for (auto &FD : Merge.second) { - FD->buildLookup(); - FD->decls_begin(); - FD->getBody(); - } - } - - // Trigger the import of enums. - auto EnumOdrMergeFailures = std::move(PendingEnumOdrMergeFailures); - PendingEnumOdrMergeFailures.clear(); - for (auto &Merge : EnumOdrMergeFailures) { - Merge.first->decls_begin(); - for (auto &Enum : Merge.second) { - Enum->decls_begin(); - } - } - - // For each declaration from a merged context, check that the canonical - // definition of that context also contains a declaration of the same - // entity. - // - // Caution: this loop does things that might invalidate iterators into - // PendingOdrMergeChecks. Don't turn this into a range-based for loop! - while (!PendingOdrMergeChecks.empty()) { - NamedDecl *D = PendingOdrMergeChecks.pop_back_val(); - - // FIXME: Skip over implicit declarations for now. This matters for things - // like implicitly-declared special member functions. This isn't entirely - // correct; we can end up with multiple unmerged declarations of the same - // implicit entity. - if (D->isImplicit()) - continue; - - DeclContext *CanonDef = D->getDeclContext(); - - bool Found = false; - const Decl *DCanon = D->getCanonicalDecl(); - - for (auto RI : D->redecls()) { - if (RI->getLexicalDeclContext() == CanonDef) { - Found = true; - break; - } - } - if (Found) - continue; - - // Quick check failed, time to do the slow thing. Note, we can't just - // look up the name of D in CanonDef here, because the member that is - // in CanonDef might not be found by name lookup (it might have been - // replaced by a more recent declaration in the lookup table), and we - // can't necessarily find it in the redeclaration chain because it might - // be merely mergeable, not redeclarable. - llvm::SmallVector<const NamedDecl*, 4> Candidates; - for (auto *CanonMember : CanonDef->decls()) { - if (CanonMember->getCanonicalDecl() == DCanon) { - // This can happen if the declaration is merely mergeable and not - // actually redeclarable (we looked for redeclarations earlier). - // - // FIXME: We should be able to detect this more efficiently, without - // pulling in all of the members of CanonDef. - Found = true; - break; - } - if (auto *ND = dyn_cast<NamedDecl>(CanonMember)) - if (ND->getDeclName() == D->getDeclName()) - Candidates.push_back(ND); - } - - if (!Found) { - // The AST doesn't like TagDecls becoming invalid after they've been - // completed. We only really need to mark FieldDecls as invalid here. - if (!isa<TagDecl>(D)) - D->setInvalidDecl(); - - // Ensure we don't accidentally recursively enter deserialization while - // we're producing our diagnostic. - Deserializing RecursionGuard(this); - - std::string CanonDefModule = - getOwningModuleNameForDiagnostic(cast<Decl>(CanonDef)); - Diag(D->getLocation(), diag::err_module_odr_violation_missing_decl) - << D << getOwningModuleNameForDiagnostic(D) - << CanonDef << CanonDefModule.empty() << CanonDefModule; - - if (Candidates.empty()) - Diag(cast<Decl>(CanonDef)->getLocation(), - diag::note_module_odr_violation_no_possible_decls) << D; - else { - for (unsigned I = 0, N = Candidates.size(); I != N; ++I) - Diag(Candidates[I]->getLocation(), - diag::note_module_odr_violation_possible_decl) - << Candidates[I]; - } - - DiagnosedOdrMergeFailures.insert(CanonDef); - } - } - - if (OdrMergeFailures.empty() && FunctionOdrMergeFailures.empty() && - EnumOdrMergeFailures.empty()) - return; - - // Ensure we don't accidentally recursively enter deserialization while - // we're producing our diagnostics. - Deserializing RecursionGuard(this); - - // Common code for hashing helpers. - ODRHash Hash; - auto ComputeQualTypeODRHash = [&Hash](QualType Ty) { - Hash.clear(); - Hash.AddQualType(Ty); - return Hash.CalculateHash(); - }; - - auto ComputeODRHash = [&Hash](const Stmt *S) { - assert(S); - Hash.clear(); - Hash.AddStmt(S); - return Hash.CalculateHash(); - }; - - auto ComputeSubDeclODRHash = [&Hash](const Decl *D) { - assert(D); - Hash.clear(); - Hash.AddSubDecl(D); - return Hash.CalculateHash(); - }; - - auto ComputeTemplateArgumentODRHash = [&Hash](const TemplateArgument &TA) { - Hash.clear(); - Hash.AddTemplateArgument(TA); - return Hash.CalculateHash(); - }; - - auto ComputeTemplateParameterListODRHash = - [&Hash](const TemplateParameterList *TPL) { - assert(TPL); - Hash.clear(); - Hash.AddTemplateParameterList(TPL); - return Hash.CalculateHash(); - }; - - // Issue any pending ODR-failure diagnostics. - for (auto &Merge : OdrMergeFailures) { - // If we've already pointed out a specific problem with this class, don't - // bother issuing a general "something's different" diagnostic. - if (!DiagnosedOdrMergeFailures.insert(Merge.first).second) - continue; - - bool Diagnosed = false; - CXXRecordDecl *FirstRecord = Merge.first; - std::string FirstModule = getOwningModuleNameForDiagnostic(FirstRecord); - for (auto &RecordPair : Merge.second) { - CXXRecordDecl *SecondRecord = RecordPair.first; - // Multiple different declarations got merged together; tell the user - // where they came from. - if (FirstRecord == SecondRecord) - continue; - - std::string SecondModule = getOwningModuleNameForDiagnostic(SecondRecord); - - auto *FirstDD = FirstRecord->DefinitionData; - auto *SecondDD = RecordPair.second; - - assert(FirstDD && SecondDD && "Definitions without DefinitionData"); - - // Diagnostics from DefinitionData are emitted here. - if (FirstDD != SecondDD) { - enum ODRDefinitionDataDifference { - NumBases, - NumVBases, - BaseType, - BaseVirtual, - BaseAccess, - }; - auto ODRDiagError = [FirstRecord, &FirstModule, - this](SourceLocation Loc, SourceRange Range, - ODRDefinitionDataDifference DiffType) { - return Diag(Loc, diag::err_module_odr_violation_definition_data) - << FirstRecord << FirstModule.empty() << FirstModule << Range - << DiffType; - }; - auto ODRDiagNote = [&SecondModule, - this](SourceLocation Loc, SourceRange Range, - ODRDefinitionDataDifference DiffType) { - return Diag(Loc, diag::note_module_odr_violation_definition_data) - << SecondModule << Range << DiffType; - }; - - unsigned FirstNumBases = FirstDD->NumBases; - unsigned FirstNumVBases = FirstDD->NumVBases; - unsigned SecondNumBases = SecondDD->NumBases; - unsigned SecondNumVBases = SecondDD->NumVBases; - - auto GetSourceRange = [](struct CXXRecordDecl::DefinitionData *DD) { - unsigned NumBases = DD->NumBases; - if (NumBases == 0) return SourceRange(); - auto bases = DD->bases(); - return SourceRange(bases[0].getBeginLoc(), - bases[NumBases - 1].getEndLoc()); - }; - - if (FirstNumBases != SecondNumBases) { - ODRDiagError(FirstRecord->getLocation(), GetSourceRange(FirstDD), - NumBases) - << FirstNumBases; - ODRDiagNote(SecondRecord->getLocation(), GetSourceRange(SecondDD), - NumBases) - << SecondNumBases; - Diagnosed = true; - break; - } - - if (FirstNumVBases != SecondNumVBases) { - ODRDiagError(FirstRecord->getLocation(), GetSourceRange(FirstDD), - NumVBases) - << FirstNumVBases; - ODRDiagNote(SecondRecord->getLocation(), GetSourceRange(SecondDD), - NumVBases) - << SecondNumVBases; - Diagnosed = true; - break; - } - - auto FirstBases = FirstDD->bases(); - auto SecondBases = SecondDD->bases(); - unsigned i = 0; - for (i = 0; i < FirstNumBases; ++i) { - auto FirstBase = FirstBases[i]; - auto SecondBase = SecondBases[i]; - if (ComputeQualTypeODRHash(FirstBase.getType()) != - ComputeQualTypeODRHash(SecondBase.getType())) { - ODRDiagError(FirstRecord->getLocation(), FirstBase.getSourceRange(), - BaseType) - << (i + 1) << FirstBase.getType(); - ODRDiagNote(SecondRecord->getLocation(), - SecondBase.getSourceRange(), BaseType) - << (i + 1) << SecondBase.getType(); - break; - } - - if (FirstBase.isVirtual() != SecondBase.isVirtual()) { - ODRDiagError(FirstRecord->getLocation(), FirstBase.getSourceRange(), - BaseVirtual) - << (i + 1) << FirstBase.isVirtual() << FirstBase.getType(); - ODRDiagNote(SecondRecord->getLocation(), - SecondBase.getSourceRange(), BaseVirtual) - << (i + 1) << SecondBase.isVirtual() << SecondBase.getType(); - break; - } - - if (FirstBase.getAccessSpecifierAsWritten() != - SecondBase.getAccessSpecifierAsWritten()) { - ODRDiagError(FirstRecord->getLocation(), FirstBase.getSourceRange(), - BaseAccess) - << (i + 1) << FirstBase.getType() - << (int)FirstBase.getAccessSpecifierAsWritten(); - ODRDiagNote(SecondRecord->getLocation(), - SecondBase.getSourceRange(), BaseAccess) - << (i + 1) << SecondBase.getType() - << (int)SecondBase.getAccessSpecifierAsWritten(); - break; - } - } - - if (i != FirstNumBases) { - Diagnosed = true; - break; - } - } - - using DeclHashes = llvm::SmallVector<std::pair<Decl *, unsigned>, 4>; - - const ClassTemplateDecl *FirstTemplate = - FirstRecord->getDescribedClassTemplate(); - const ClassTemplateDecl *SecondTemplate = - SecondRecord->getDescribedClassTemplate(); - - assert(!FirstTemplate == !SecondTemplate && - "Both pointers should be null or non-null"); - - enum ODRTemplateDifference { - ParamEmptyName, - ParamName, - ParamSingleDefaultArgument, - ParamDifferentDefaultArgument, - }; - - if (FirstTemplate && SecondTemplate) { - DeclHashes FirstTemplateHashes; - DeclHashes SecondTemplateHashes; - - auto PopulateTemplateParameterHashs = - [&ComputeSubDeclODRHash](DeclHashes &Hashes, - const ClassTemplateDecl *TD) { - for (auto *D : TD->getTemplateParameters()->asArray()) { - Hashes.emplace_back(D, ComputeSubDeclODRHash(D)); - } - }; - - PopulateTemplateParameterHashs(FirstTemplateHashes, FirstTemplate); - PopulateTemplateParameterHashs(SecondTemplateHashes, SecondTemplate); - - assert(FirstTemplateHashes.size() == SecondTemplateHashes.size() && - "Number of template parameters should be equal."); - - auto FirstIt = FirstTemplateHashes.begin(); - auto FirstEnd = FirstTemplateHashes.end(); - auto SecondIt = SecondTemplateHashes.begin(); - for (; FirstIt != FirstEnd; ++FirstIt, ++SecondIt) { - if (FirstIt->second == SecondIt->second) - continue; - - auto ODRDiagError = [FirstRecord, &FirstModule, - this](SourceLocation Loc, SourceRange Range, - ODRTemplateDifference DiffType) { - return Diag(Loc, diag::err_module_odr_violation_template_parameter) - << FirstRecord << FirstModule.empty() << FirstModule << Range - << DiffType; - }; - auto ODRDiagNote = [&SecondModule, - this](SourceLocation Loc, SourceRange Range, - ODRTemplateDifference DiffType) { - return Diag(Loc, diag::note_module_odr_violation_template_parameter) - << SecondModule << Range << DiffType; - }; - - const NamedDecl* FirstDecl = cast<NamedDecl>(FirstIt->first); - const NamedDecl* SecondDecl = cast<NamedDecl>(SecondIt->first); - - assert(FirstDecl->getKind() == SecondDecl->getKind() && - "Parameter Decl's should be the same kind."); - - DeclarationName FirstName = FirstDecl->getDeclName(); - DeclarationName SecondName = SecondDecl->getDeclName(); - - if (FirstName != SecondName) { - const bool FirstNameEmpty = - FirstName.isIdentifier() && !FirstName.getAsIdentifierInfo(); - const bool SecondNameEmpty = - SecondName.isIdentifier() && !SecondName.getAsIdentifierInfo(); - assert((!FirstNameEmpty || !SecondNameEmpty) && - "Both template parameters cannot be unnamed."); - ODRDiagError(FirstDecl->getLocation(), FirstDecl->getSourceRange(), - FirstNameEmpty ? ParamEmptyName : ParamName) - << FirstName; - ODRDiagNote(SecondDecl->getLocation(), SecondDecl->getSourceRange(), - SecondNameEmpty ? ParamEmptyName : ParamName) - << SecondName; - break; - } - - switch (FirstDecl->getKind()) { - default: - llvm_unreachable("Invalid template parameter type."); - case Decl::TemplateTypeParm: { - const auto *FirstParam = cast<TemplateTypeParmDecl>(FirstDecl); - const auto *SecondParam = cast<TemplateTypeParmDecl>(SecondDecl); - const bool HasFirstDefaultArgument = - FirstParam->hasDefaultArgument() && - !FirstParam->defaultArgumentWasInherited(); - const bool HasSecondDefaultArgument = - SecondParam->hasDefaultArgument() && - !SecondParam->defaultArgumentWasInherited(); - - if (HasFirstDefaultArgument != HasSecondDefaultArgument) { - ODRDiagError(FirstDecl->getLocation(), - FirstDecl->getSourceRange(), - ParamSingleDefaultArgument) - << HasFirstDefaultArgument; - ODRDiagNote(SecondDecl->getLocation(), - SecondDecl->getSourceRange(), - ParamSingleDefaultArgument) - << HasSecondDefaultArgument; - break; - } - - assert(HasFirstDefaultArgument && HasSecondDefaultArgument && - "Expecting default arguments."); - - ODRDiagError(FirstDecl->getLocation(), FirstDecl->getSourceRange(), - ParamDifferentDefaultArgument); - ODRDiagNote(SecondDecl->getLocation(), SecondDecl->getSourceRange(), - ParamDifferentDefaultArgument); - - break; - } - case Decl::NonTypeTemplateParm: { - const auto *FirstParam = cast<NonTypeTemplateParmDecl>(FirstDecl); - const auto *SecondParam = cast<NonTypeTemplateParmDecl>(SecondDecl); - const bool HasFirstDefaultArgument = - FirstParam->hasDefaultArgument() && - !FirstParam->defaultArgumentWasInherited(); - const bool HasSecondDefaultArgument = - SecondParam->hasDefaultArgument() && - !SecondParam->defaultArgumentWasInherited(); - - if (HasFirstDefaultArgument != HasSecondDefaultArgument) { - ODRDiagError(FirstDecl->getLocation(), - FirstDecl->getSourceRange(), - ParamSingleDefaultArgument) - << HasFirstDefaultArgument; - ODRDiagNote(SecondDecl->getLocation(), - SecondDecl->getSourceRange(), - ParamSingleDefaultArgument) - << HasSecondDefaultArgument; - break; - } - - assert(HasFirstDefaultArgument && HasSecondDefaultArgument && - "Expecting default arguments."); - - ODRDiagError(FirstDecl->getLocation(), FirstDecl->getSourceRange(), - ParamDifferentDefaultArgument); - ODRDiagNote(SecondDecl->getLocation(), SecondDecl->getSourceRange(), - ParamDifferentDefaultArgument); - - break; - } - case Decl::TemplateTemplateParm: { - const auto *FirstParam = cast<TemplateTemplateParmDecl>(FirstDecl); - const auto *SecondParam = - cast<TemplateTemplateParmDecl>(SecondDecl); - const bool HasFirstDefaultArgument = - FirstParam->hasDefaultArgument() && - !FirstParam->defaultArgumentWasInherited(); - const bool HasSecondDefaultArgument = - SecondParam->hasDefaultArgument() && - !SecondParam->defaultArgumentWasInherited(); - - if (HasFirstDefaultArgument != HasSecondDefaultArgument) { - ODRDiagError(FirstDecl->getLocation(), - FirstDecl->getSourceRange(), - ParamSingleDefaultArgument) - << HasFirstDefaultArgument; - ODRDiagNote(SecondDecl->getLocation(), - SecondDecl->getSourceRange(), - ParamSingleDefaultArgument) - << HasSecondDefaultArgument; - break; - } - - assert(HasFirstDefaultArgument && HasSecondDefaultArgument && - "Expecting default arguments."); - - ODRDiagError(FirstDecl->getLocation(), FirstDecl->getSourceRange(), - ParamDifferentDefaultArgument); - ODRDiagNote(SecondDecl->getLocation(), SecondDecl->getSourceRange(), - ParamDifferentDefaultArgument); - - break; - } - } - - break; - } - - if (FirstIt != FirstEnd) { - Diagnosed = true; - break; - } - } - - DeclHashes FirstHashes; - DeclHashes SecondHashes; - - auto PopulateHashes = [&ComputeSubDeclODRHash, FirstRecord]( - DeclHashes &Hashes, CXXRecordDecl *Record) { - for (auto *D : Record->decls()) { - // Due to decl merging, the first CXXRecordDecl is the parent of - // Decls in both records. - if (!ODRHash::isWhitelistedDecl(D, FirstRecord)) - continue; - Hashes.emplace_back(D, ComputeSubDeclODRHash(D)); - } - }; - PopulateHashes(FirstHashes, FirstRecord); - PopulateHashes(SecondHashes, SecondRecord); - - // Used with err_module_odr_violation_mismatch_decl and - // note_module_odr_violation_mismatch_decl - // This list should be the same Decl's as in ODRHash::isWhiteListedDecl - enum { - EndOfClass, - PublicSpecifer, - PrivateSpecifer, - ProtectedSpecifer, - StaticAssert, - Field, - CXXMethod, - TypeAlias, - TypeDef, - Var, - Friend, - FunctionTemplate, - Other - } FirstDiffType = Other, - SecondDiffType = Other; - - auto DifferenceSelector = [](Decl *D) { - assert(D && "valid Decl required"); - switch (D->getKind()) { - default: - return Other; - case Decl::AccessSpec: - switch (D->getAccess()) { - case AS_public: - return PublicSpecifer; - case AS_private: - return PrivateSpecifer; - case AS_protected: - return ProtectedSpecifer; - case AS_none: - break; - } - llvm_unreachable("Invalid access specifier"); - case Decl::StaticAssert: - return StaticAssert; - case Decl::Field: - return Field; - case Decl::CXXMethod: - case Decl::CXXConstructor: - case Decl::CXXDestructor: - return CXXMethod; - case Decl::TypeAlias: - return TypeAlias; - case Decl::Typedef: - return TypeDef; - case Decl::Var: - return Var; - case Decl::Friend: - return Friend; - case Decl::FunctionTemplate: - return FunctionTemplate; - } - }; - - Decl *FirstDecl = nullptr; - Decl *SecondDecl = nullptr; - auto FirstIt = FirstHashes.begin(); - auto SecondIt = SecondHashes.begin(); - - // If there is a diagnoseable difference, FirstDiffType and - // SecondDiffType will not be Other and FirstDecl and SecondDecl will be - // filled in if not EndOfClass. - while (FirstIt != FirstHashes.end() || SecondIt != SecondHashes.end()) { - if (FirstIt != FirstHashes.end() && SecondIt != SecondHashes.end() && - FirstIt->second == SecondIt->second) { - ++FirstIt; - ++SecondIt; - continue; - } - - FirstDecl = FirstIt == FirstHashes.end() ? nullptr : FirstIt->first; - SecondDecl = SecondIt == SecondHashes.end() ? nullptr : SecondIt->first; - - FirstDiffType = FirstDecl ? DifferenceSelector(FirstDecl) : EndOfClass; - SecondDiffType = - SecondDecl ? DifferenceSelector(SecondDecl) : EndOfClass; - - break; - } - - if (FirstDiffType == Other || SecondDiffType == Other) { - // Reaching this point means an unexpected Decl was encountered - // or no difference was detected. This causes a generic error - // message to be emitted. - Diag(FirstRecord->getLocation(), - diag::err_module_odr_violation_different_definitions) - << FirstRecord << FirstModule.empty() << FirstModule; - - if (FirstDecl) { - Diag(FirstDecl->getLocation(), diag::note_first_module_difference) - << FirstRecord << FirstDecl->getSourceRange(); - } - - Diag(SecondRecord->getLocation(), - diag::note_module_odr_violation_different_definitions) - << SecondModule; - - if (SecondDecl) { - Diag(SecondDecl->getLocation(), diag::note_second_module_difference) - << SecondDecl->getSourceRange(); - } - - Diagnosed = true; - break; - } - - if (FirstDiffType != SecondDiffType) { - SourceLocation FirstLoc; - SourceRange FirstRange; - if (FirstDiffType == EndOfClass) { - FirstLoc = FirstRecord->getBraceRange().getEnd(); - } else { - FirstLoc = FirstIt->first->getLocation(); - FirstRange = FirstIt->first->getSourceRange(); - } - Diag(FirstLoc, diag::err_module_odr_violation_mismatch_decl) - << FirstRecord << FirstModule.empty() << FirstModule << FirstRange - << FirstDiffType; - - SourceLocation SecondLoc; - SourceRange SecondRange; - if (SecondDiffType == EndOfClass) { - SecondLoc = SecondRecord->getBraceRange().getEnd(); - } else { - SecondLoc = SecondDecl->getLocation(); - SecondRange = SecondDecl->getSourceRange(); - } - Diag(SecondLoc, diag::note_module_odr_violation_mismatch_decl) - << SecondModule << SecondRange << SecondDiffType; - Diagnosed = true; - break; - } - - assert(FirstDiffType == SecondDiffType); - - // Used with err_module_odr_violation_mismatch_decl_diff and - // note_module_odr_violation_mismatch_decl_diff - enum ODRDeclDifference { - StaticAssertCondition, - StaticAssertMessage, - StaticAssertOnlyMessage, - FieldName, - FieldTypeName, - FieldSingleBitField, - FieldDifferentWidthBitField, - FieldSingleMutable, - FieldSingleInitializer, - FieldDifferentInitializers, - MethodName, - MethodDeleted, - MethodDefaulted, - MethodVirtual, - MethodStatic, - MethodVolatile, - MethodConst, - MethodInline, - MethodNumberParameters, - MethodParameterType, - MethodParameterName, - MethodParameterSingleDefaultArgument, - MethodParameterDifferentDefaultArgument, - MethodNoTemplateArguments, - MethodDifferentNumberTemplateArguments, - MethodDifferentTemplateArgument, - MethodSingleBody, - MethodDifferentBody, - TypedefName, - TypedefType, - VarName, - VarType, - VarSingleInitializer, - VarDifferentInitializer, - VarConstexpr, - FriendTypeFunction, - FriendType, - FriendFunction, - FunctionTemplateDifferentNumberParameters, - FunctionTemplateParameterDifferentKind, - FunctionTemplateParameterName, - FunctionTemplateParameterSingleDefaultArgument, - FunctionTemplateParameterDifferentDefaultArgument, - FunctionTemplateParameterDifferentType, - FunctionTemplatePackParameter, - }; - - // These lambdas have the common portions of the ODR diagnostics. This - // has the same return as Diag(), so addition parameters can be passed - // in with operator<< - auto ODRDiagError = [FirstRecord, &FirstModule, this]( - SourceLocation Loc, SourceRange Range, ODRDeclDifference DiffType) { - return Diag(Loc, diag::err_module_odr_violation_mismatch_decl_diff) - << FirstRecord << FirstModule.empty() << FirstModule << Range - << DiffType; - }; - auto ODRDiagNote = [&SecondModule, this]( - SourceLocation Loc, SourceRange Range, ODRDeclDifference DiffType) { - return Diag(Loc, diag::note_module_odr_violation_mismatch_decl_diff) - << SecondModule << Range << DiffType; - }; - - switch (FirstDiffType) { - case Other: - case EndOfClass: - case PublicSpecifer: - case PrivateSpecifer: - case ProtectedSpecifer: - llvm_unreachable("Invalid diff type"); - - case StaticAssert: { - StaticAssertDecl *FirstSA = cast<StaticAssertDecl>(FirstDecl); - StaticAssertDecl *SecondSA = cast<StaticAssertDecl>(SecondDecl); - - Expr *FirstExpr = FirstSA->getAssertExpr(); - Expr *SecondExpr = SecondSA->getAssertExpr(); - unsigned FirstODRHash = ComputeODRHash(FirstExpr); - unsigned SecondODRHash = ComputeODRHash(SecondExpr); - if (FirstODRHash != SecondODRHash) { - ODRDiagError(FirstExpr->getBeginLoc(), FirstExpr->getSourceRange(), - StaticAssertCondition); - ODRDiagNote(SecondExpr->getBeginLoc(), SecondExpr->getSourceRange(), - StaticAssertCondition); - Diagnosed = true; - break; - } - - StringLiteral *FirstStr = FirstSA->getMessage(); - StringLiteral *SecondStr = SecondSA->getMessage(); - assert((FirstStr || SecondStr) && "Both messages cannot be empty"); - if ((FirstStr && !SecondStr) || (!FirstStr && SecondStr)) { - SourceLocation FirstLoc, SecondLoc; - SourceRange FirstRange, SecondRange; - if (FirstStr) { - FirstLoc = FirstStr->getBeginLoc(); - FirstRange = FirstStr->getSourceRange(); - } else { - FirstLoc = FirstSA->getBeginLoc(); - FirstRange = FirstSA->getSourceRange(); - } - if (SecondStr) { - SecondLoc = SecondStr->getBeginLoc(); - SecondRange = SecondStr->getSourceRange(); - } else { - SecondLoc = SecondSA->getBeginLoc(); - SecondRange = SecondSA->getSourceRange(); - } - ODRDiagError(FirstLoc, FirstRange, StaticAssertOnlyMessage) - << (FirstStr == nullptr); - ODRDiagNote(SecondLoc, SecondRange, StaticAssertOnlyMessage) - << (SecondStr == nullptr); - Diagnosed = true; - break; - } - - if (FirstStr && SecondStr && - FirstStr->getString() != SecondStr->getString()) { - ODRDiagError(FirstStr->getBeginLoc(), FirstStr->getSourceRange(), - StaticAssertMessage); - ODRDiagNote(SecondStr->getBeginLoc(), SecondStr->getSourceRange(), - StaticAssertMessage); - Diagnosed = true; - break; - } - break; - } - case Field: { - FieldDecl *FirstField = cast<FieldDecl>(FirstDecl); - FieldDecl *SecondField = cast<FieldDecl>(SecondDecl); - IdentifierInfo *FirstII = FirstField->getIdentifier(); - IdentifierInfo *SecondII = SecondField->getIdentifier(); - if (FirstII->getName() != SecondII->getName()) { - ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(), - FieldName) - << FirstII; - ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(), - FieldName) - << SecondII; - - Diagnosed = true; - break; - } - - assert(getContext().hasSameType(FirstField->getType(), - SecondField->getType())); - - QualType FirstType = FirstField->getType(); - QualType SecondType = SecondField->getType(); - if (ComputeQualTypeODRHash(FirstType) != - ComputeQualTypeODRHash(SecondType)) { - ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(), - FieldTypeName) - << FirstII << FirstType; - ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(), - FieldTypeName) - << SecondII << SecondType; - - Diagnosed = true; - break; - } - - const bool IsFirstBitField = FirstField->isBitField(); - const bool IsSecondBitField = SecondField->isBitField(); - if (IsFirstBitField != IsSecondBitField) { - ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(), - FieldSingleBitField) - << FirstII << IsFirstBitField; - ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(), - FieldSingleBitField) - << SecondII << IsSecondBitField; - Diagnosed = true; - break; - } - - if (IsFirstBitField && IsSecondBitField) { - ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(), - FieldDifferentWidthBitField) - << FirstII << FirstField->getBitWidth()->getSourceRange(); - ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(), - FieldDifferentWidthBitField) - << SecondII << SecondField->getBitWidth()->getSourceRange(); - Diagnosed = true; - break; - } - - const bool IsFirstMutable = FirstField->isMutable(); - const bool IsSecondMutable = SecondField->isMutable(); - if (IsFirstMutable != IsSecondMutable) { - ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(), - FieldSingleMutable) - << FirstII << IsFirstMutable; - ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(), - FieldSingleMutable) - << SecondII << IsSecondMutable; - Diagnosed = true; - break; - } - - const Expr *FirstInitializer = FirstField->getInClassInitializer(); - const Expr *SecondInitializer = SecondField->getInClassInitializer(); - if ((!FirstInitializer && SecondInitializer) || - (FirstInitializer && !SecondInitializer)) { - ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(), - FieldSingleInitializer) - << FirstII << (FirstInitializer != nullptr); - ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(), - FieldSingleInitializer) - << SecondII << (SecondInitializer != nullptr); - Diagnosed = true; - break; - } - - if (FirstInitializer && SecondInitializer) { - unsigned FirstInitHash = ComputeODRHash(FirstInitializer); - unsigned SecondInitHash = ComputeODRHash(SecondInitializer); - if (FirstInitHash != SecondInitHash) { - ODRDiagError(FirstField->getLocation(), - FirstField->getSourceRange(), - FieldDifferentInitializers) - << FirstII << FirstInitializer->getSourceRange(); - ODRDiagNote(SecondField->getLocation(), - SecondField->getSourceRange(), - FieldDifferentInitializers) - << SecondII << SecondInitializer->getSourceRange(); - Diagnosed = true; - break; - } - } - - break; - } - case CXXMethod: { - enum { - DiagMethod, - DiagConstructor, - DiagDestructor, - } FirstMethodType, - SecondMethodType; - auto GetMethodTypeForDiagnostics = [](const CXXMethodDecl* D) { - if (isa<CXXConstructorDecl>(D)) return DiagConstructor; - if (isa<CXXDestructorDecl>(D)) return DiagDestructor; - return DiagMethod; - }; - const CXXMethodDecl *FirstMethod = cast<CXXMethodDecl>(FirstDecl); - const CXXMethodDecl *SecondMethod = cast<CXXMethodDecl>(SecondDecl); - FirstMethodType = GetMethodTypeForDiagnostics(FirstMethod); - SecondMethodType = GetMethodTypeForDiagnostics(SecondMethod); - auto FirstName = FirstMethod->getDeclName(); - auto SecondName = SecondMethod->getDeclName(); - if (FirstMethodType != SecondMethodType || FirstName != SecondName) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), MethodName) - << FirstMethodType << FirstName; - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), MethodName) - << SecondMethodType << SecondName; - - Diagnosed = true; - break; - } - - const bool FirstDeleted = FirstMethod->isDeletedAsWritten(); - const bool SecondDeleted = SecondMethod->isDeletedAsWritten(); - if (FirstDeleted != SecondDeleted) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), MethodDeleted) - << FirstMethodType << FirstName << FirstDeleted; - - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), MethodDeleted) - << SecondMethodType << SecondName << SecondDeleted; - Diagnosed = true; - break; - } - - const bool FirstDefaulted = FirstMethod->isExplicitlyDefaulted(); - const bool SecondDefaulted = SecondMethod->isExplicitlyDefaulted(); - if (FirstDefaulted != SecondDefaulted) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), MethodDefaulted) - << FirstMethodType << FirstName << FirstDefaulted; - - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), MethodDefaulted) - << SecondMethodType << SecondName << SecondDefaulted; - Diagnosed = true; - break; - } - - const bool FirstVirtual = FirstMethod->isVirtualAsWritten(); - const bool SecondVirtual = SecondMethod->isVirtualAsWritten(); - const bool FirstPure = FirstMethod->isPure(); - const bool SecondPure = SecondMethod->isPure(); - if ((FirstVirtual || SecondVirtual) && - (FirstVirtual != SecondVirtual || FirstPure != SecondPure)) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), MethodVirtual) - << FirstMethodType << FirstName << FirstPure << FirstVirtual; - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), MethodVirtual) - << SecondMethodType << SecondName << SecondPure << SecondVirtual; - Diagnosed = true; - break; - } - - // CXXMethodDecl::isStatic uses the canonical Decl. With Decl merging, - // FirstDecl is the canonical Decl of SecondDecl, so the storage - // class needs to be checked instead. - const auto FirstStorage = FirstMethod->getStorageClass(); - const auto SecondStorage = SecondMethod->getStorageClass(); - const bool FirstStatic = FirstStorage == SC_Static; - const bool SecondStatic = SecondStorage == SC_Static; - if (FirstStatic != SecondStatic) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), MethodStatic) - << FirstMethodType << FirstName << FirstStatic; - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), MethodStatic) - << SecondMethodType << SecondName << SecondStatic; - Diagnosed = true; - break; - } - - const bool FirstVolatile = FirstMethod->isVolatile(); - const bool SecondVolatile = SecondMethod->isVolatile(); - if (FirstVolatile != SecondVolatile) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), MethodVolatile) - << FirstMethodType << FirstName << FirstVolatile; - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), MethodVolatile) - << SecondMethodType << SecondName << SecondVolatile; - Diagnosed = true; - break; - } - - const bool FirstConst = FirstMethod->isConst(); - const bool SecondConst = SecondMethod->isConst(); - if (FirstConst != SecondConst) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), MethodConst) - << FirstMethodType << FirstName << FirstConst; - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), MethodConst) - << SecondMethodType << SecondName << SecondConst; - Diagnosed = true; - break; - } - - const bool FirstInline = FirstMethod->isInlineSpecified(); - const bool SecondInline = SecondMethod->isInlineSpecified(); - if (FirstInline != SecondInline) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), MethodInline) - << FirstMethodType << FirstName << FirstInline; - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), MethodInline) - << SecondMethodType << SecondName << SecondInline; - Diagnosed = true; - break; - } - - const unsigned FirstNumParameters = FirstMethod->param_size(); - const unsigned SecondNumParameters = SecondMethod->param_size(); - if (FirstNumParameters != SecondNumParameters) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), MethodNumberParameters) - << FirstMethodType << FirstName << FirstNumParameters; - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), MethodNumberParameters) - << SecondMethodType << SecondName << SecondNumParameters; - Diagnosed = true; - break; - } - - // Need this status boolean to know when break out of the switch. - bool ParameterMismatch = false; - for (unsigned I = 0; I < FirstNumParameters; ++I) { - const ParmVarDecl *FirstParam = FirstMethod->getParamDecl(I); - const ParmVarDecl *SecondParam = SecondMethod->getParamDecl(I); - - QualType FirstParamType = FirstParam->getType(); - QualType SecondParamType = SecondParam->getType(); - if (FirstParamType != SecondParamType && - ComputeQualTypeODRHash(FirstParamType) != - ComputeQualTypeODRHash(SecondParamType)) { - if (const DecayedType *ParamDecayedType = - FirstParamType->getAs<DecayedType>()) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), MethodParameterType) - << FirstMethodType << FirstName << (I + 1) << FirstParamType - << true << ParamDecayedType->getOriginalType(); - } else { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), MethodParameterType) - << FirstMethodType << FirstName << (I + 1) << FirstParamType - << false; - } - - if (const DecayedType *ParamDecayedType = - SecondParamType->getAs<DecayedType>()) { - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), MethodParameterType) - << SecondMethodType << SecondName << (I + 1) - << SecondParamType << true - << ParamDecayedType->getOriginalType(); - } else { - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), MethodParameterType) - << SecondMethodType << SecondName << (I + 1) - << SecondParamType << false; - } - ParameterMismatch = true; - break; - } - - DeclarationName FirstParamName = FirstParam->getDeclName(); - DeclarationName SecondParamName = SecondParam->getDeclName(); - if (FirstParamName != SecondParamName) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), MethodParameterName) - << FirstMethodType << FirstName << (I + 1) << FirstParamName; - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), MethodParameterName) - << SecondMethodType << SecondName << (I + 1) << SecondParamName; - ParameterMismatch = true; - break; - } - - const Expr *FirstInit = FirstParam->getInit(); - const Expr *SecondInit = SecondParam->getInit(); - if ((FirstInit == nullptr) != (SecondInit == nullptr)) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), - MethodParameterSingleDefaultArgument) - << FirstMethodType << FirstName << (I + 1) - << (FirstInit == nullptr) - << (FirstInit ? FirstInit->getSourceRange() : SourceRange()); - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), - MethodParameterSingleDefaultArgument) - << SecondMethodType << SecondName << (I + 1) - << (SecondInit == nullptr) - << (SecondInit ? SecondInit->getSourceRange() : SourceRange()); - ParameterMismatch = true; - break; - } - - if (FirstInit && SecondInit && - ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), - MethodParameterDifferentDefaultArgument) - << FirstMethodType << FirstName << (I + 1) - << FirstInit->getSourceRange(); - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), - MethodParameterDifferentDefaultArgument) - << SecondMethodType << SecondName << (I + 1) - << SecondInit->getSourceRange(); - ParameterMismatch = true; - break; - - } - } - - if (ParameterMismatch) { - Diagnosed = true; - break; - } - - const auto *FirstTemplateArgs = - FirstMethod->getTemplateSpecializationArgs(); - const auto *SecondTemplateArgs = - SecondMethod->getTemplateSpecializationArgs(); - - if ((FirstTemplateArgs && !SecondTemplateArgs) || - (!FirstTemplateArgs && SecondTemplateArgs)) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), MethodNoTemplateArguments) - << FirstMethodType << FirstName << (FirstTemplateArgs != nullptr); - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), MethodNoTemplateArguments) - << SecondMethodType << SecondName - << (SecondTemplateArgs != nullptr); - - Diagnosed = true; - break; - } - - if (FirstTemplateArgs && SecondTemplateArgs) { - // Remove pack expansions from argument list. - auto ExpandTemplateArgumentList = - [](const TemplateArgumentList *TAL) { - llvm::SmallVector<const TemplateArgument *, 8> ExpandedList; - for (const TemplateArgument &TA : TAL->asArray()) { - if (TA.getKind() != TemplateArgument::Pack) { - ExpandedList.push_back(&TA); - continue; - } - for (const TemplateArgument &PackTA : TA.getPackAsArray()) { - ExpandedList.push_back(&PackTA); - } - } - return ExpandedList; - }; - llvm::SmallVector<const TemplateArgument *, 8> FirstExpandedList = - ExpandTemplateArgumentList(FirstTemplateArgs); - llvm::SmallVector<const TemplateArgument *, 8> SecondExpandedList = - ExpandTemplateArgumentList(SecondTemplateArgs); - - if (FirstExpandedList.size() != SecondExpandedList.size()) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), - MethodDifferentNumberTemplateArguments) - << FirstMethodType << FirstName - << (unsigned)FirstExpandedList.size(); - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), - MethodDifferentNumberTemplateArguments) - << SecondMethodType << SecondName - << (unsigned)SecondExpandedList.size(); - - Diagnosed = true; - break; - } - - bool TemplateArgumentMismatch = false; - for (unsigned i = 0, e = FirstExpandedList.size(); i != e; ++i) { - const TemplateArgument &FirstTA = *FirstExpandedList[i], - &SecondTA = *SecondExpandedList[i]; - if (ComputeTemplateArgumentODRHash(FirstTA) == - ComputeTemplateArgumentODRHash(SecondTA)) { - continue; - } - - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), - MethodDifferentTemplateArgument) - << FirstMethodType << FirstName << FirstTA << i + 1; - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), - MethodDifferentTemplateArgument) - << SecondMethodType << SecondName << SecondTA << i + 1; - - TemplateArgumentMismatch = true; - break; - } - - if (TemplateArgumentMismatch) { - Diagnosed = true; - break; - } - } - - // Compute the hash of the method as if it has no body. - auto ComputeCXXMethodODRHash = [&Hash](const CXXMethodDecl *D) { - Hash.clear(); - Hash.AddFunctionDecl(D, true /*SkipBody*/); - return Hash.CalculateHash(); - }; - - // Compare the hash generated to the hash stored. A difference means - // that a body was present in the original source. Due to merging, - // the stardard way of detecting a body will not work. - const bool HasFirstBody = - ComputeCXXMethodODRHash(FirstMethod) != FirstMethod->getODRHash(); - const bool HasSecondBody = - ComputeCXXMethodODRHash(SecondMethod) != SecondMethod->getODRHash(); - - if (HasFirstBody != HasSecondBody) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), MethodSingleBody) - << FirstMethodType << FirstName << HasFirstBody; - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), MethodSingleBody) - << SecondMethodType << SecondName << HasSecondBody; - Diagnosed = true; - break; - } - - if (HasFirstBody && HasSecondBody) { - ODRDiagError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), MethodDifferentBody) - << FirstMethodType << FirstName; - ODRDiagNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), MethodDifferentBody) - << SecondMethodType << SecondName; - Diagnosed = true; - break; - } - - break; - } - case TypeAlias: - case TypeDef: { - TypedefNameDecl *FirstTD = cast<TypedefNameDecl>(FirstDecl); - TypedefNameDecl *SecondTD = cast<TypedefNameDecl>(SecondDecl); - auto FirstName = FirstTD->getDeclName(); - auto SecondName = SecondTD->getDeclName(); - if (FirstName != SecondName) { - ODRDiagError(FirstTD->getLocation(), FirstTD->getSourceRange(), - TypedefName) - << (FirstDiffType == TypeAlias) << FirstName; - ODRDiagNote(SecondTD->getLocation(), SecondTD->getSourceRange(), - TypedefName) - << (FirstDiffType == TypeAlias) << SecondName; - Diagnosed = true; - break; - } - - QualType FirstType = FirstTD->getUnderlyingType(); - QualType SecondType = SecondTD->getUnderlyingType(); - if (ComputeQualTypeODRHash(FirstType) != - ComputeQualTypeODRHash(SecondType)) { - ODRDiagError(FirstTD->getLocation(), FirstTD->getSourceRange(), - TypedefType) - << (FirstDiffType == TypeAlias) << FirstName << FirstType; - ODRDiagNote(SecondTD->getLocation(), SecondTD->getSourceRange(), - TypedefType) - << (FirstDiffType == TypeAlias) << SecondName << SecondType; - Diagnosed = true; - break; - } - break; - } - case Var: { - VarDecl *FirstVD = cast<VarDecl>(FirstDecl); - VarDecl *SecondVD = cast<VarDecl>(SecondDecl); - auto FirstName = FirstVD->getDeclName(); - auto SecondName = SecondVD->getDeclName(); - if (FirstName != SecondName) { - ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(), - VarName) - << FirstName; - ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(), - VarName) - << SecondName; - Diagnosed = true; - break; - } - - QualType FirstType = FirstVD->getType(); - QualType SecondType = SecondVD->getType(); - if (ComputeQualTypeODRHash(FirstType) != - ComputeQualTypeODRHash(SecondType)) { - ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(), - VarType) - << FirstName << FirstType; - ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(), - VarType) - << SecondName << SecondType; - Diagnosed = true; - break; - } - - const Expr *FirstInit = FirstVD->getInit(); - const Expr *SecondInit = SecondVD->getInit(); - if ((FirstInit == nullptr) != (SecondInit == nullptr)) { - ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(), - VarSingleInitializer) - << FirstName << (FirstInit == nullptr) - << (FirstInit ? FirstInit->getSourceRange(): SourceRange()); - ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(), - VarSingleInitializer) - << SecondName << (SecondInit == nullptr) - << (SecondInit ? SecondInit->getSourceRange() : SourceRange()); - Diagnosed = true; - break; - } - - if (FirstInit && SecondInit && - ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) { - ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(), - VarDifferentInitializer) - << FirstName << FirstInit->getSourceRange(); - ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(), - VarDifferentInitializer) - << SecondName << SecondInit->getSourceRange(); - Diagnosed = true; - break; - } - - const bool FirstIsConstexpr = FirstVD->isConstexpr(); - const bool SecondIsConstexpr = SecondVD->isConstexpr(); - if (FirstIsConstexpr != SecondIsConstexpr) { - ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(), - VarConstexpr) - << FirstName << FirstIsConstexpr; - ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(), - VarConstexpr) - << SecondName << SecondIsConstexpr; - Diagnosed = true; - break; - } - break; - } - case Friend: { - FriendDecl *FirstFriend = cast<FriendDecl>(FirstDecl); - FriendDecl *SecondFriend = cast<FriendDecl>(SecondDecl); - - NamedDecl *FirstND = FirstFriend->getFriendDecl(); - NamedDecl *SecondND = SecondFriend->getFriendDecl(); - - TypeSourceInfo *FirstTSI = FirstFriend->getFriendType(); - TypeSourceInfo *SecondTSI = SecondFriend->getFriendType(); - - if (FirstND && SecondND) { - ODRDiagError(FirstFriend->getFriendLoc(), - FirstFriend->getSourceRange(), FriendFunction) - << FirstND; - ODRDiagNote(SecondFriend->getFriendLoc(), - SecondFriend->getSourceRange(), FriendFunction) - << SecondND; - - Diagnosed = true; - break; - } - - if (FirstTSI && SecondTSI) { - QualType FirstFriendType = FirstTSI->getType(); - QualType SecondFriendType = SecondTSI->getType(); - assert(ComputeQualTypeODRHash(FirstFriendType) != - ComputeQualTypeODRHash(SecondFriendType)); - ODRDiagError(FirstFriend->getFriendLoc(), - FirstFriend->getSourceRange(), FriendType) - << FirstFriendType; - ODRDiagNote(SecondFriend->getFriendLoc(), - SecondFriend->getSourceRange(), FriendType) - << SecondFriendType; - Diagnosed = true; - break; - } - - ODRDiagError(FirstFriend->getFriendLoc(), FirstFriend->getSourceRange(), - FriendTypeFunction) - << (FirstTSI == nullptr); - ODRDiagNote(SecondFriend->getFriendLoc(), - SecondFriend->getSourceRange(), FriendTypeFunction) - << (SecondTSI == nullptr); - - Diagnosed = true; - break; - } - case FunctionTemplate: { - FunctionTemplateDecl *FirstTemplate = - cast<FunctionTemplateDecl>(FirstDecl); - FunctionTemplateDecl *SecondTemplate = - cast<FunctionTemplateDecl>(SecondDecl); - - TemplateParameterList *FirstTPL = - FirstTemplate->getTemplateParameters(); - TemplateParameterList *SecondTPL = - SecondTemplate->getTemplateParameters(); - - if (FirstTPL->size() != SecondTPL->size()) { - ODRDiagError(FirstTemplate->getLocation(), - FirstTemplate->getSourceRange(), - FunctionTemplateDifferentNumberParameters) - << FirstTemplate << FirstTPL->size(); - ODRDiagNote(SecondTemplate->getLocation(), - SecondTemplate->getSourceRange(), - FunctionTemplateDifferentNumberParameters) - << SecondTemplate << SecondTPL->size(); - - Diagnosed = true; - break; - } - - bool ParameterMismatch = false; - for (unsigned i = 0, e = FirstTPL->size(); i != e; ++i) { - NamedDecl *FirstParam = FirstTPL->getParam(i); - NamedDecl *SecondParam = SecondTPL->getParam(i); - - if (FirstParam->getKind() != SecondParam->getKind()) { - enum { - TemplateTypeParameter, - NonTypeTemplateParameter, - TemplateTemplateParameter, - }; - auto GetParamType = [](NamedDecl *D) { - switch (D->getKind()) { - default: - llvm_unreachable("Unexpected template parameter type"); - case Decl::TemplateTypeParm: - return TemplateTypeParameter; - case Decl::NonTypeTemplateParm: - return NonTypeTemplateParameter; - case Decl::TemplateTemplateParm: - return TemplateTemplateParameter; - } - }; - - ODRDiagError(FirstTemplate->getLocation(), - FirstTemplate->getSourceRange(), - FunctionTemplateParameterDifferentKind) - << FirstTemplate << (i + 1) << GetParamType(FirstParam); - ODRDiagNote(SecondTemplate->getLocation(), - SecondTemplate->getSourceRange(), - FunctionTemplateParameterDifferentKind) - << SecondTemplate << (i + 1) << GetParamType(SecondParam); - - ParameterMismatch = true; - break; - } - - if (FirstParam->getName() != SecondParam->getName()) { - ODRDiagError(FirstTemplate->getLocation(), - FirstTemplate->getSourceRange(), - FunctionTemplateParameterName) - << FirstTemplate << (i + 1) << (bool)FirstParam->getIdentifier() - << FirstParam; - ODRDiagNote(SecondTemplate->getLocation(), - SecondTemplate->getSourceRange(), - FunctionTemplateParameterName) - << SecondTemplate << (i + 1) - << (bool)SecondParam->getIdentifier() << SecondParam; - ParameterMismatch = true; - break; - } - - if (isa<TemplateTypeParmDecl>(FirstParam) && - isa<TemplateTypeParmDecl>(SecondParam)) { - TemplateTypeParmDecl *FirstTTPD = - cast<TemplateTypeParmDecl>(FirstParam); - TemplateTypeParmDecl *SecondTTPD = - cast<TemplateTypeParmDecl>(SecondParam); - bool HasFirstDefaultArgument = - FirstTTPD->hasDefaultArgument() && - !FirstTTPD->defaultArgumentWasInherited(); - bool HasSecondDefaultArgument = - SecondTTPD->hasDefaultArgument() && - !SecondTTPD->defaultArgumentWasInherited(); - if (HasFirstDefaultArgument != HasSecondDefaultArgument) { - ODRDiagError(FirstTemplate->getLocation(), - FirstTemplate->getSourceRange(), - FunctionTemplateParameterSingleDefaultArgument) - << FirstTemplate << (i + 1) << HasFirstDefaultArgument; - ODRDiagNote(SecondTemplate->getLocation(), - SecondTemplate->getSourceRange(), - FunctionTemplateParameterSingleDefaultArgument) - << SecondTemplate << (i + 1) << HasSecondDefaultArgument; - ParameterMismatch = true; - break; - } - - if (HasFirstDefaultArgument && HasSecondDefaultArgument) { - QualType FirstType = FirstTTPD->getDefaultArgument(); - QualType SecondType = SecondTTPD->getDefaultArgument(); - if (ComputeQualTypeODRHash(FirstType) != - ComputeQualTypeODRHash(SecondType)) { - ODRDiagError(FirstTemplate->getLocation(), - FirstTemplate->getSourceRange(), - FunctionTemplateParameterDifferentDefaultArgument) - << FirstTemplate << (i + 1) << FirstType; - ODRDiagNote(SecondTemplate->getLocation(), - SecondTemplate->getSourceRange(), - FunctionTemplateParameterDifferentDefaultArgument) - << SecondTemplate << (i + 1) << SecondType; - ParameterMismatch = true; - break; - } - } - - if (FirstTTPD->isParameterPack() != - SecondTTPD->isParameterPack()) { - ODRDiagError(FirstTemplate->getLocation(), - FirstTemplate->getSourceRange(), - FunctionTemplatePackParameter) - << FirstTemplate << (i + 1) << FirstTTPD->isParameterPack(); - ODRDiagNote(SecondTemplate->getLocation(), - SecondTemplate->getSourceRange(), - FunctionTemplatePackParameter) - << SecondTemplate << (i + 1) << SecondTTPD->isParameterPack(); - ParameterMismatch = true; - break; - } - } - - if (isa<TemplateTemplateParmDecl>(FirstParam) && - isa<TemplateTemplateParmDecl>(SecondParam)) { - TemplateTemplateParmDecl *FirstTTPD = - cast<TemplateTemplateParmDecl>(FirstParam); - TemplateTemplateParmDecl *SecondTTPD = - cast<TemplateTemplateParmDecl>(SecondParam); - - TemplateParameterList *FirstTPL = - FirstTTPD->getTemplateParameters(); - TemplateParameterList *SecondTPL = - SecondTTPD->getTemplateParameters(); - - if (ComputeTemplateParameterListODRHash(FirstTPL) != - ComputeTemplateParameterListODRHash(SecondTPL)) { - ODRDiagError(FirstTemplate->getLocation(), - FirstTemplate->getSourceRange(), - FunctionTemplateParameterDifferentType) - << FirstTemplate << (i + 1); - ODRDiagNote(SecondTemplate->getLocation(), - SecondTemplate->getSourceRange(), - FunctionTemplateParameterDifferentType) - << SecondTemplate << (i + 1); - ParameterMismatch = true; - break; - } - - bool HasFirstDefaultArgument = - FirstTTPD->hasDefaultArgument() && - !FirstTTPD->defaultArgumentWasInherited(); - bool HasSecondDefaultArgument = - SecondTTPD->hasDefaultArgument() && - !SecondTTPD->defaultArgumentWasInherited(); - if (HasFirstDefaultArgument != HasSecondDefaultArgument) { - ODRDiagError(FirstTemplate->getLocation(), - FirstTemplate->getSourceRange(), - FunctionTemplateParameterSingleDefaultArgument) - << FirstTemplate << (i + 1) << HasFirstDefaultArgument; - ODRDiagNote(SecondTemplate->getLocation(), - SecondTemplate->getSourceRange(), - FunctionTemplateParameterSingleDefaultArgument) - << SecondTemplate << (i + 1) << HasSecondDefaultArgument; - ParameterMismatch = true; - break; - } - - if (HasFirstDefaultArgument && HasSecondDefaultArgument) { - TemplateArgument FirstTA = - FirstTTPD->getDefaultArgument().getArgument(); - TemplateArgument SecondTA = - SecondTTPD->getDefaultArgument().getArgument(); - if (ComputeTemplateArgumentODRHash(FirstTA) != - ComputeTemplateArgumentODRHash(SecondTA)) { - ODRDiagError(FirstTemplate->getLocation(), - FirstTemplate->getSourceRange(), - FunctionTemplateParameterDifferentDefaultArgument) - << FirstTemplate << (i + 1) << FirstTA; - ODRDiagNote(SecondTemplate->getLocation(), - SecondTemplate->getSourceRange(), - FunctionTemplateParameterDifferentDefaultArgument) - << SecondTemplate << (i + 1) << SecondTA; - ParameterMismatch = true; - break; - } - } - - if (FirstTTPD->isParameterPack() != - SecondTTPD->isParameterPack()) { - ODRDiagError(FirstTemplate->getLocation(), - FirstTemplate->getSourceRange(), - FunctionTemplatePackParameter) - << FirstTemplate << (i + 1) << FirstTTPD->isParameterPack(); - ODRDiagNote(SecondTemplate->getLocation(), - SecondTemplate->getSourceRange(), - FunctionTemplatePackParameter) - << SecondTemplate << (i + 1) << SecondTTPD->isParameterPack(); - ParameterMismatch = true; - break; - } - } - - if (isa<NonTypeTemplateParmDecl>(FirstParam) && - isa<NonTypeTemplateParmDecl>(SecondParam)) { - NonTypeTemplateParmDecl *FirstNTTPD = - cast<NonTypeTemplateParmDecl>(FirstParam); - NonTypeTemplateParmDecl *SecondNTTPD = - cast<NonTypeTemplateParmDecl>(SecondParam); - - QualType FirstType = FirstNTTPD->getType(); - QualType SecondType = SecondNTTPD->getType(); - if (ComputeQualTypeODRHash(FirstType) != - ComputeQualTypeODRHash(SecondType)) { - ODRDiagError(FirstTemplate->getLocation(), - FirstTemplate->getSourceRange(), - FunctionTemplateParameterDifferentType) - << FirstTemplate << (i + 1); - ODRDiagNote(SecondTemplate->getLocation(), - SecondTemplate->getSourceRange(), - FunctionTemplateParameterDifferentType) - << SecondTemplate << (i + 1); - ParameterMismatch = true; - break; - } - - bool HasFirstDefaultArgument = - FirstNTTPD->hasDefaultArgument() && - !FirstNTTPD->defaultArgumentWasInherited(); - bool HasSecondDefaultArgument = - SecondNTTPD->hasDefaultArgument() && - !SecondNTTPD->defaultArgumentWasInherited(); - if (HasFirstDefaultArgument != HasSecondDefaultArgument) { - ODRDiagError(FirstTemplate->getLocation(), - FirstTemplate->getSourceRange(), - FunctionTemplateParameterSingleDefaultArgument) - << FirstTemplate << (i + 1) << HasFirstDefaultArgument; - ODRDiagNote(SecondTemplate->getLocation(), - SecondTemplate->getSourceRange(), - FunctionTemplateParameterSingleDefaultArgument) - << SecondTemplate << (i + 1) << HasSecondDefaultArgument; - ParameterMismatch = true; - break; - } - - if (HasFirstDefaultArgument && HasSecondDefaultArgument) { - Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument(); - Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument(); - if (ComputeODRHash(FirstDefaultArgument) != - ComputeODRHash(SecondDefaultArgument)) { - ODRDiagError(FirstTemplate->getLocation(), - FirstTemplate->getSourceRange(), - FunctionTemplateParameterDifferentDefaultArgument) - << FirstTemplate << (i + 1) << FirstDefaultArgument; - ODRDiagNote(SecondTemplate->getLocation(), - SecondTemplate->getSourceRange(), - FunctionTemplateParameterDifferentDefaultArgument) - << SecondTemplate << (i + 1) << SecondDefaultArgument; - ParameterMismatch = true; - break; - } - } - - if (FirstNTTPD->isParameterPack() != - SecondNTTPD->isParameterPack()) { - ODRDiagError(FirstTemplate->getLocation(), - FirstTemplate->getSourceRange(), - FunctionTemplatePackParameter) - << FirstTemplate << (i + 1) << FirstNTTPD->isParameterPack(); - ODRDiagNote(SecondTemplate->getLocation(), - SecondTemplate->getSourceRange(), - FunctionTemplatePackParameter) - << SecondTemplate << (i + 1) - << SecondNTTPD->isParameterPack(); - ParameterMismatch = true; - break; - } - } - } - - if (ParameterMismatch) { - Diagnosed = true; - break; - } - - break; - } - } - - if (Diagnosed) - continue; - - Diag(FirstDecl->getLocation(), - diag::err_module_odr_violation_mismatch_decl_unknown) - << FirstRecord << FirstModule.empty() << FirstModule << FirstDiffType - << FirstDecl->getSourceRange(); - Diag(SecondDecl->getLocation(), - diag::note_module_odr_violation_mismatch_decl_unknown) - << SecondModule << FirstDiffType << SecondDecl->getSourceRange(); - Diagnosed = true; - } - - if (!Diagnosed) { - // All definitions are updates to the same declaration. This happens if a - // module instantiates the declaration of a class template specialization - // and two or more other modules instantiate its definition. - // - // FIXME: Indicate which modules had instantiations of this definition. - // FIXME: How can this even happen? - Diag(Merge.first->getLocation(), - diag::err_module_odr_violation_different_instantiations) - << Merge.first; - } - } - - // Issue ODR failures diagnostics for functions. - for (auto &Merge : FunctionOdrMergeFailures) { - enum ODRFunctionDifference { - ReturnType, - ParameterName, - ParameterType, - ParameterSingleDefaultArgument, - ParameterDifferentDefaultArgument, - FunctionBody, - }; - - FunctionDecl *FirstFunction = Merge.first; - std::string FirstModule = getOwningModuleNameForDiagnostic(FirstFunction); - - bool Diagnosed = false; - for (auto &SecondFunction : Merge.second) { - - if (FirstFunction == SecondFunction) - continue; - - std::string SecondModule = - getOwningModuleNameForDiagnostic(SecondFunction); - - auto ODRDiagError = [FirstFunction, &FirstModule, - this](SourceLocation Loc, SourceRange Range, - ODRFunctionDifference DiffType) { - return Diag(Loc, diag::err_module_odr_violation_function) - << FirstFunction << FirstModule.empty() << FirstModule << Range - << DiffType; - }; - auto ODRDiagNote = [&SecondModule, this](SourceLocation Loc, - SourceRange Range, - ODRFunctionDifference DiffType) { - return Diag(Loc, diag::note_module_odr_violation_function) - << SecondModule << Range << DiffType; - }; - - if (ComputeQualTypeODRHash(FirstFunction->getReturnType()) != - ComputeQualTypeODRHash(SecondFunction->getReturnType())) { - ODRDiagError(FirstFunction->getReturnTypeSourceRange().getBegin(), - FirstFunction->getReturnTypeSourceRange(), ReturnType) - << FirstFunction->getReturnType(); - ODRDiagNote(SecondFunction->getReturnTypeSourceRange().getBegin(), - SecondFunction->getReturnTypeSourceRange(), ReturnType) - << SecondFunction->getReturnType(); - Diagnosed = true; - break; - } - - assert(FirstFunction->param_size() == SecondFunction->param_size() && - "Merged functions with different number of parameters"); - - auto ParamSize = FirstFunction->param_size(); - bool ParameterMismatch = false; - for (unsigned I = 0; I < ParamSize; ++I) { - auto *FirstParam = FirstFunction->getParamDecl(I); - auto *SecondParam = SecondFunction->getParamDecl(I); - - assert(getContext().hasSameType(FirstParam->getType(), - SecondParam->getType()) && - "Merged function has different parameter types."); - - if (FirstParam->getDeclName() != SecondParam->getDeclName()) { - ODRDiagError(FirstParam->getLocation(), FirstParam->getSourceRange(), - ParameterName) - << I + 1 << FirstParam->getDeclName(); - ODRDiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(), - ParameterName) - << I + 1 << SecondParam->getDeclName(); - ParameterMismatch = true; - break; - }; - - QualType FirstParamType = FirstParam->getType(); - QualType SecondParamType = SecondParam->getType(); - if (FirstParamType != SecondParamType && - ComputeQualTypeODRHash(FirstParamType) != - ComputeQualTypeODRHash(SecondParamType)) { - if (const DecayedType *ParamDecayedType = - FirstParamType->getAs<DecayedType>()) { - ODRDiagError(FirstParam->getLocation(), - FirstParam->getSourceRange(), ParameterType) - << (I + 1) << FirstParamType << true - << ParamDecayedType->getOriginalType(); - } else { - ODRDiagError(FirstParam->getLocation(), - FirstParam->getSourceRange(), ParameterType) - << (I + 1) << FirstParamType << false; - } - - if (const DecayedType *ParamDecayedType = - SecondParamType->getAs<DecayedType>()) { - ODRDiagNote(SecondParam->getLocation(), - SecondParam->getSourceRange(), ParameterType) - << (I + 1) << SecondParamType << true - << ParamDecayedType->getOriginalType(); - } else { - ODRDiagNote(SecondParam->getLocation(), - SecondParam->getSourceRange(), ParameterType) - << (I + 1) << SecondParamType << false; - } - ParameterMismatch = true; - break; - } - - const Expr *FirstInit = FirstParam->getInit(); - const Expr *SecondInit = SecondParam->getInit(); - if ((FirstInit == nullptr) != (SecondInit == nullptr)) { - ODRDiagError(FirstParam->getLocation(), FirstParam->getSourceRange(), - ParameterSingleDefaultArgument) - << (I + 1) << (FirstInit == nullptr) - << (FirstInit ? FirstInit->getSourceRange() : SourceRange()); - ODRDiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(), - ParameterSingleDefaultArgument) - << (I + 1) << (SecondInit == nullptr) - << (SecondInit ? SecondInit->getSourceRange() : SourceRange()); - ParameterMismatch = true; - break; - } - - if (FirstInit && SecondInit && - ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) { - ODRDiagError(FirstParam->getLocation(), FirstParam->getSourceRange(), - ParameterDifferentDefaultArgument) - << (I + 1) << FirstInit->getSourceRange(); - ODRDiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(), - ParameterDifferentDefaultArgument) - << (I + 1) << SecondInit->getSourceRange(); - ParameterMismatch = true; - break; - } - - assert(ComputeSubDeclODRHash(FirstParam) == - ComputeSubDeclODRHash(SecondParam) && - "Undiagnosed parameter difference."); - } - - if (ParameterMismatch) { - Diagnosed = true; - break; - } - - // If no error has been generated before now, assume the problem is in - // the body and generate a message. - ODRDiagError(FirstFunction->getLocation(), - FirstFunction->getSourceRange(), FunctionBody); - ODRDiagNote(SecondFunction->getLocation(), - SecondFunction->getSourceRange(), FunctionBody); - Diagnosed = true; - break; - } - (void)Diagnosed; - assert(Diagnosed && "Unable to emit ODR diagnostic."); - } - - // Issue ODR failures diagnostics for enums. - for (auto &Merge : EnumOdrMergeFailures) { - enum ODREnumDifference { - SingleScopedEnum, - EnumTagKeywordMismatch, - SingleSpecifiedType, - DifferentSpecifiedTypes, - DifferentNumberEnumConstants, - EnumConstantName, - EnumConstantSingleInitilizer, - EnumConstantDifferentInitilizer, - }; - - // If we've already pointed out a specific problem with this enum, don't - // bother issuing a general "something's different" diagnostic. - if (!DiagnosedOdrMergeFailures.insert(Merge.first).second) - continue; - - EnumDecl *FirstEnum = Merge.first; - std::string FirstModule = getOwningModuleNameForDiagnostic(FirstEnum); - - using DeclHashes = - llvm::SmallVector<std::pair<EnumConstantDecl *, unsigned>, 4>; - auto PopulateHashes = [&ComputeSubDeclODRHash, FirstEnum]( - DeclHashes &Hashes, EnumDecl *Enum) { - for (auto *D : Enum->decls()) { - // Due to decl merging, the first EnumDecl is the parent of - // Decls in both records. - if (!ODRHash::isWhitelistedDecl(D, FirstEnum)) - continue; - assert(isa<EnumConstantDecl>(D) && "Unexpected Decl kind"); - Hashes.emplace_back(cast<EnumConstantDecl>(D), - ComputeSubDeclODRHash(D)); - } - }; - DeclHashes FirstHashes; - PopulateHashes(FirstHashes, FirstEnum); - bool Diagnosed = false; - for (auto &SecondEnum : Merge.second) { - - if (FirstEnum == SecondEnum) - continue; - - std::string SecondModule = - getOwningModuleNameForDiagnostic(SecondEnum); - - auto ODRDiagError = [FirstEnum, &FirstModule, - this](SourceLocation Loc, SourceRange Range, - ODREnumDifference DiffType) { - return Diag(Loc, diag::err_module_odr_violation_enum) - << FirstEnum << FirstModule.empty() << FirstModule << Range - << DiffType; - }; - auto ODRDiagNote = [&SecondModule, this](SourceLocation Loc, - SourceRange Range, - ODREnumDifference DiffType) { - return Diag(Loc, diag::note_module_odr_violation_enum) - << SecondModule << Range << DiffType; - }; - - if (FirstEnum->isScoped() != SecondEnum->isScoped()) { - ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(), - SingleScopedEnum) - << FirstEnum->isScoped(); - ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(), - SingleScopedEnum) - << SecondEnum->isScoped(); - Diagnosed = true; - continue; - } - - if (FirstEnum->isScoped() && SecondEnum->isScoped()) { - if (FirstEnum->isScopedUsingClassTag() != - SecondEnum->isScopedUsingClassTag()) { - ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(), - EnumTagKeywordMismatch) - << FirstEnum->isScopedUsingClassTag(); - ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(), - EnumTagKeywordMismatch) - << SecondEnum->isScopedUsingClassTag(); - Diagnosed = true; - continue; - } - } - - QualType FirstUnderlyingType = - FirstEnum->getIntegerTypeSourceInfo() - ? FirstEnum->getIntegerTypeSourceInfo()->getType() - : QualType(); - QualType SecondUnderlyingType = - SecondEnum->getIntegerTypeSourceInfo() - ? SecondEnum->getIntegerTypeSourceInfo()->getType() - : QualType(); - if (FirstUnderlyingType.isNull() != SecondUnderlyingType.isNull()) { - ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(), - SingleSpecifiedType) - << !FirstUnderlyingType.isNull(); - ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(), - SingleSpecifiedType) - << !SecondUnderlyingType.isNull(); - Diagnosed = true; - continue; - } - - if (!FirstUnderlyingType.isNull() && !SecondUnderlyingType.isNull()) { - if (ComputeQualTypeODRHash(FirstUnderlyingType) != - ComputeQualTypeODRHash(SecondUnderlyingType)) { - ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(), - DifferentSpecifiedTypes) - << FirstUnderlyingType; - ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(), - DifferentSpecifiedTypes) - << SecondUnderlyingType; - Diagnosed = true; - continue; - } - } - - DeclHashes SecondHashes; - PopulateHashes(SecondHashes, SecondEnum); - - if (FirstHashes.size() != SecondHashes.size()) { - ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(), - DifferentNumberEnumConstants) - << (int)FirstHashes.size(); - ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(), - DifferentNumberEnumConstants) - << (int)SecondHashes.size(); - Diagnosed = true; - continue; - } - - for (unsigned I = 0; I < FirstHashes.size(); ++I) { - if (FirstHashes[I].second == SecondHashes[I].second) - continue; - const EnumConstantDecl *FirstEnumConstant = FirstHashes[I].first; - const EnumConstantDecl *SecondEnumConstant = SecondHashes[I].first; - - if (FirstEnumConstant->getDeclName() != - SecondEnumConstant->getDeclName()) { - - ODRDiagError(FirstEnumConstant->getLocation(), - FirstEnumConstant->getSourceRange(), EnumConstantName) - << I + 1 << FirstEnumConstant; - ODRDiagNote(SecondEnumConstant->getLocation(), - SecondEnumConstant->getSourceRange(), EnumConstantName) - << I + 1 << SecondEnumConstant; - Diagnosed = true; - break; - } - - const Expr *FirstInit = FirstEnumConstant->getInitExpr(); - const Expr *SecondInit = SecondEnumConstant->getInitExpr(); - if (!FirstInit && !SecondInit) - continue; - - if (!FirstInit || !SecondInit) { - ODRDiagError(FirstEnumConstant->getLocation(), - FirstEnumConstant->getSourceRange(), - EnumConstantSingleInitilizer) - << I + 1 << FirstEnumConstant << (FirstInit != nullptr); - ODRDiagNote(SecondEnumConstant->getLocation(), - SecondEnumConstant->getSourceRange(), - EnumConstantSingleInitilizer) - << I + 1 << SecondEnumConstant << (SecondInit != nullptr); - Diagnosed = true; - break; - } - - if (ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) { - ODRDiagError(FirstEnumConstant->getLocation(), - FirstEnumConstant->getSourceRange(), - EnumConstantDifferentInitilizer) - << I + 1 << FirstEnumConstant; - ODRDiagNote(SecondEnumConstant->getLocation(), - SecondEnumConstant->getSourceRange(), - EnumConstantDifferentInitilizer) - << I + 1 << SecondEnumConstant; - Diagnosed = true; - break; - } - } - } - - (void)Diagnosed; - assert(Diagnosed && "Unable to emit ODR diagnostic."); - } -} - -void ASTReader::StartedDeserializing() { - if (++NumCurrentElementsDeserializing == 1 && ReadTimer.get()) - ReadTimer->startTimer(); -} - -void ASTReader::FinishedDeserializing() { - assert(NumCurrentElementsDeserializing && - "FinishedDeserializing not paired with StartedDeserializing"); - if (NumCurrentElementsDeserializing == 1) { - // We decrease NumCurrentElementsDeserializing only after pending actions - // are finished, to avoid recursively re-calling finishPendingActions(). - finishPendingActions(); - } - --NumCurrentElementsDeserializing; - - if (NumCurrentElementsDeserializing == 0) { - // Propagate exception specification and deduced type updates along - // redeclaration chains. - // - // We do this now rather than in finishPendingActions because we want to - // be able to walk the complete redeclaration chains of the updated decls. - while (!PendingExceptionSpecUpdates.empty() || - !PendingDeducedTypeUpdates.empty()) { - auto ESUpdates = std::move(PendingExceptionSpecUpdates); - PendingExceptionSpecUpdates.clear(); - for (auto Update : ESUpdates) { - ProcessingUpdatesRAIIObj ProcessingUpdates(*this); - auto *FPT = Update.second->getType()->castAs<FunctionProtoType>(); - auto ESI = FPT->getExtProtoInfo().ExceptionSpec; - if (auto *Listener = getContext().getASTMutationListener()) - Listener->ResolvedExceptionSpec(cast<FunctionDecl>(Update.second)); - for (auto *Redecl : Update.second->redecls()) - getContext().adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI); - } - - auto DTUpdates = std::move(PendingDeducedTypeUpdates); - PendingDeducedTypeUpdates.clear(); - for (auto Update : DTUpdates) { - ProcessingUpdatesRAIIObj ProcessingUpdates(*this); - // FIXME: If the return type is already deduced, check that it matches. - getContext().adjustDeducedFunctionResultType(Update.first, - Update.second); - } - } - - if (ReadTimer) - ReadTimer->stopTimer(); - - diagnoseOdrViolations(); - - // We are not in recursive loading, so it's safe to pass the "interesting" - // decls to the consumer. - if (Consumer) - PassInterestingDeclsToConsumer(); - } -} - -void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { - if (IdentifierInfo *II = Name.getAsIdentifierInfo()) { - // Remove any fake results before adding any real ones. - auto It = PendingFakeLookupResults.find(II); - if (It != PendingFakeLookupResults.end()) { - for (auto *ND : It->second) - SemaObj->IdResolver.RemoveDecl(ND); - // FIXME: this works around module+PCH performance issue. - // Rather than erase the result from the map, which is O(n), just clear - // the vector of NamedDecls. - It->second.clear(); - } - } - - if (SemaObj->IdResolver.tryAddTopLevelDecl(D, Name) && SemaObj->TUScope) { - SemaObj->TUScope->AddDecl(D); - } else if (SemaObj->TUScope) { - // Adding the decl to IdResolver may have failed because it was already in - // (even though it was not added in scope). If it is already in, make sure - // it gets in the scope as well. - if (std::find(SemaObj->IdResolver.begin(Name), - SemaObj->IdResolver.end(), D) != SemaObj->IdResolver.end()) - SemaObj->TUScope->AddDecl(D); - } -} - -ASTReader::ASTReader(Preprocessor &PP, ASTContext *Context, - const PCHContainerReader &PCHContainerRdr, - ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, - StringRef isysroot, bool DisableValidation, - bool AllowASTWithCompilerErrors, - bool AllowConfigurationMismatch, bool ValidateSystemInputs, - bool UseGlobalIndex, - std::unique_ptr<llvm::Timer> ReadTimer) - : Listener(DisableValidation - ? cast<ASTReaderListener>(new SimpleASTReaderListener(PP)) - : cast<ASTReaderListener>(new PCHValidator(PP, *this))), - SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), - PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()), PP(PP), - ContextObj(Context), - ModuleMgr(PP.getFileManager(), PP.getPCMCache(), PCHContainerRdr, - PP.getHeaderSearchInfo()), - PCMCache(PP.getPCMCache()), DummyIdResolver(PP), - ReadTimer(std::move(ReadTimer)), isysroot(isysroot), - DisableValidation(DisableValidation), - AllowASTWithCompilerErrors(AllowASTWithCompilerErrors), - AllowConfigurationMismatch(AllowConfigurationMismatch), - ValidateSystemInputs(ValidateSystemInputs), - UseGlobalIndex(UseGlobalIndex), CurrSwitchCaseStmts(&SwitchCaseStmts) { - SourceMgr.setExternalSLocEntrySource(this); - - for (const auto &Ext : Extensions) { - auto BlockName = Ext->getExtensionMetadata().BlockName; - auto Known = ModuleFileExtensions.find(BlockName); - if (Known != ModuleFileExtensions.end()) { - Diags.Report(diag::warn_duplicate_module_file_extension) - << BlockName; - continue; - } - - ModuleFileExtensions.insert({BlockName, Ext}); - } -} - -ASTReader::~ASTReader() { - if (OwnsDeserializationListener) - delete DeserializationListener; -} - -IdentifierResolver &ASTReader::getIdResolver() { - return SemaObj ? SemaObj->IdResolver : DummyIdResolver; -} - -unsigned ASTRecordReader::readRecord(llvm::BitstreamCursor &Cursor, - unsigned AbbrevID) { - Idx = 0; - Record.clear(); - return Cursor.readRecord(AbbrevID, Record); -} -//===----------------------------------------------------------------------===// -//// OMPClauseReader implementation -////===----------------------------------------------------------------------===// - -OMPClause *OMPClauseReader::readClause() { - OMPClause *C; - switch (Record.readInt()) { - case OMPC_if: - C = new (Context) OMPIfClause(); - break; - case OMPC_final: - C = new (Context) OMPFinalClause(); - break; - case OMPC_num_threads: - C = new (Context) OMPNumThreadsClause(); - break; - case OMPC_safelen: - C = new (Context) OMPSafelenClause(); - break; - case OMPC_simdlen: - C = new (Context) OMPSimdlenClause(); - break; - case OMPC_collapse: - C = new (Context) OMPCollapseClause(); - break; - case OMPC_default: - C = new (Context) OMPDefaultClause(); - break; - case OMPC_proc_bind: - C = new (Context) OMPProcBindClause(); - break; - case OMPC_schedule: - C = new (Context) OMPScheduleClause(); - break; - case OMPC_ordered: - C = OMPOrderedClause::CreateEmpty(Context, Record.readInt()); - break; - case OMPC_nowait: - C = new (Context) OMPNowaitClause(); - break; - case OMPC_untied: - C = new (Context) OMPUntiedClause(); - break; - case OMPC_mergeable: - C = new (Context) OMPMergeableClause(); - break; - case OMPC_read: - C = new (Context) OMPReadClause(); - break; - case OMPC_write: - C = new (Context) OMPWriteClause(); - break; - case OMPC_update: - C = new (Context) OMPUpdateClause(); - break; - case OMPC_capture: - C = new (Context) OMPCaptureClause(); - break; - case OMPC_seq_cst: - C = new (Context) OMPSeqCstClause(); - break; - case OMPC_threads: - C = new (Context) OMPThreadsClause(); - break; - case OMPC_simd: - C = new (Context) OMPSIMDClause(); - break; - case OMPC_nogroup: - C = new (Context) OMPNogroupClause(); - break; - case OMPC_unified_address: - C = new (Context) OMPUnifiedAddressClause(); - break; - case OMPC_unified_shared_memory: - C = new (Context) OMPUnifiedSharedMemoryClause(); - break; - case OMPC_reverse_offload: - C = new (Context) OMPReverseOffloadClause(); - break; - case OMPC_dynamic_allocators: - C = new (Context) OMPDynamicAllocatorsClause(); - break; - case OMPC_atomic_default_mem_order: - C = new (Context) OMPAtomicDefaultMemOrderClause(); - break; - case OMPC_private: - C = OMPPrivateClause::CreateEmpty(Context, Record.readInt()); - break; - case OMPC_firstprivate: - C = OMPFirstprivateClause::CreateEmpty(Context, Record.readInt()); - break; - case OMPC_lastprivate: - C = OMPLastprivateClause::CreateEmpty(Context, Record.readInt()); - break; - case OMPC_shared: - C = OMPSharedClause::CreateEmpty(Context, Record.readInt()); - break; - case OMPC_reduction: - C = OMPReductionClause::CreateEmpty(Context, Record.readInt()); - break; - case OMPC_task_reduction: - C = OMPTaskReductionClause::CreateEmpty(Context, Record.readInt()); - break; - case OMPC_in_reduction: - C = OMPInReductionClause::CreateEmpty(Context, Record.readInt()); - break; - case OMPC_linear: - C = OMPLinearClause::CreateEmpty(Context, Record.readInt()); - break; - case OMPC_aligned: - C = OMPAlignedClause::CreateEmpty(Context, Record.readInt()); - break; - case OMPC_copyin: - C = OMPCopyinClause::CreateEmpty(Context, Record.readInt()); - break; - case OMPC_copyprivate: - C = OMPCopyprivateClause::CreateEmpty(Context, Record.readInt()); - break; - case OMPC_flush: - C = OMPFlushClause::CreateEmpty(Context, Record.readInt()); - break; - case OMPC_depend: { - unsigned NumVars = Record.readInt(); - unsigned NumLoops = Record.readInt(); - C = OMPDependClause::CreateEmpty(Context, NumVars, NumLoops); - break; - } - case OMPC_device: - C = new (Context) OMPDeviceClause(); - break; - case OMPC_map: { - unsigned NumVars = Record.readInt(); - unsigned NumDeclarations = Record.readInt(); - unsigned NumLists = Record.readInt(); - unsigned NumComponents = Record.readInt(); - C = OMPMapClause::CreateEmpty(Context, NumVars, NumDeclarations, NumLists, - NumComponents); - break; - } - case OMPC_num_teams: - C = new (Context) OMPNumTeamsClause(); - break; - case OMPC_thread_limit: - C = new (Context) OMPThreadLimitClause(); - break; - case OMPC_priority: - C = new (Context) OMPPriorityClause(); - break; - case OMPC_grainsize: - C = new (Context) OMPGrainsizeClause(); - break; - case OMPC_num_tasks: - C = new (Context) OMPNumTasksClause(); - break; - case OMPC_hint: - C = new (Context) OMPHintClause(); - break; - case OMPC_dist_schedule: - C = new (Context) OMPDistScheduleClause(); - break; - case OMPC_defaultmap: - C = new (Context) OMPDefaultmapClause(); - break; - case OMPC_to: { - unsigned NumVars = Record.readInt(); - unsigned NumDeclarations = Record.readInt(); - unsigned NumLists = Record.readInt(); - unsigned NumComponents = Record.readInt(); - C = OMPToClause::CreateEmpty(Context, NumVars, NumDeclarations, NumLists, - NumComponents); - break; - } - case OMPC_from: { - unsigned NumVars = Record.readInt(); - unsigned NumDeclarations = Record.readInt(); - unsigned NumLists = Record.readInt(); - unsigned NumComponents = Record.readInt(); - C = OMPFromClause::CreateEmpty(Context, NumVars, NumDeclarations, NumLists, - NumComponents); - break; - } - case OMPC_use_device_ptr: { - unsigned NumVars = Record.readInt(); - unsigned NumDeclarations = Record.readInt(); - unsigned NumLists = Record.readInt(); - unsigned NumComponents = Record.readInt(); - C = OMPUseDevicePtrClause::CreateEmpty(Context, NumVars, NumDeclarations, - NumLists, NumComponents); - break; - } - case OMPC_is_device_ptr: { - unsigned NumVars = Record.readInt(); - unsigned NumDeclarations = Record.readInt(); - unsigned NumLists = Record.readInt(); - unsigned NumComponents = Record.readInt(); - C = OMPIsDevicePtrClause::CreateEmpty(Context, NumVars, NumDeclarations, - NumLists, NumComponents); - break; - } - } - Visit(C); - C->setLocStart(Record.readSourceLocation()); - C->setLocEnd(Record.readSourceLocation()); - - return C; -} - -void OMPClauseReader::VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C) { - C->setPreInitStmt(Record.readSubStmt(), - static_cast<OpenMPDirectiveKind>(Record.readInt())); -} - -void OMPClauseReader::VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C) { - VisitOMPClauseWithPreInit(C); - C->setPostUpdateExpr(Record.readSubExpr()); -} - -void OMPClauseReader::VisitOMPIfClause(OMPIfClause *C) { - VisitOMPClauseWithPreInit(C); - C->setNameModifier(static_cast<OpenMPDirectiveKind>(Record.readInt())); - C->setNameModifierLoc(Record.readSourceLocation()); - C->setColonLoc(Record.readSourceLocation()); - C->setCondition(Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPFinalClause(OMPFinalClause *C) { - C->setCondition(Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { - VisitOMPClauseWithPreInit(C); - C->setNumThreads(Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPSafelenClause(OMPSafelenClause *C) { - C->setSafelen(Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPSimdlenClause(OMPSimdlenClause *C) { - C->setSimdlen(Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPCollapseClause(OMPCollapseClause *C) { - C->setNumForLoops(Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) { - C->setDefaultKind( - static_cast<OpenMPDefaultClauseKind>(Record.readInt())); - C->setLParenLoc(Record.readSourceLocation()); - C->setDefaultKindKwLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPProcBindClause(OMPProcBindClause *C) { - C->setProcBindKind( - static_cast<OpenMPProcBindClauseKind>(Record.readInt())); - C->setLParenLoc(Record.readSourceLocation()); - C->setProcBindKindKwLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPScheduleClause(OMPScheduleClause *C) { - VisitOMPClauseWithPreInit(C); - C->setScheduleKind( - static_cast<OpenMPScheduleClauseKind>(Record.readInt())); - C->setFirstScheduleModifier( - static_cast<OpenMPScheduleClauseModifier>(Record.readInt())); - C->setSecondScheduleModifier( - static_cast<OpenMPScheduleClauseModifier>(Record.readInt())); - C->setChunkSize(Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); - C->setFirstScheduleModifierLoc(Record.readSourceLocation()); - C->setSecondScheduleModifierLoc(Record.readSourceLocation()); - C->setScheduleKindLoc(Record.readSourceLocation()); - C->setCommaLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPOrderedClause(OMPOrderedClause *C) { - C->setNumForLoops(Record.readSubExpr()); - for (unsigned I = 0, E = C->NumberOfLoops; I < E; ++I) - C->setLoopNumIterations(I, Record.readSubExpr()); - for (unsigned I = 0, E = C->NumberOfLoops; I < E; ++I) - C->setLoopCounter(I, Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPNowaitClause(OMPNowaitClause *) {} - -void OMPClauseReader::VisitOMPUntiedClause(OMPUntiedClause *) {} - -void OMPClauseReader::VisitOMPMergeableClause(OMPMergeableClause *) {} - -void OMPClauseReader::VisitOMPReadClause(OMPReadClause *) {} - -void OMPClauseReader::VisitOMPWriteClause(OMPWriteClause *) {} - -void OMPClauseReader::VisitOMPUpdateClause(OMPUpdateClause *) {} - -void OMPClauseReader::VisitOMPCaptureClause(OMPCaptureClause *) {} - -void OMPClauseReader::VisitOMPSeqCstClause(OMPSeqCstClause *) {} - -void OMPClauseReader::VisitOMPThreadsClause(OMPThreadsClause *) {} - -void OMPClauseReader::VisitOMPSIMDClause(OMPSIMDClause *) {} - -void OMPClauseReader::VisitOMPNogroupClause(OMPNogroupClause *) {} - -void OMPClauseReader::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) {} - -void OMPClauseReader::VisitOMPUnifiedSharedMemoryClause( - OMPUnifiedSharedMemoryClause *) {} - -void OMPClauseReader::VisitOMPReverseOffloadClause(OMPReverseOffloadClause *) {} - -void -OMPClauseReader::VisitOMPDynamicAllocatorsClause(OMPDynamicAllocatorsClause *) { -} - -void OMPClauseReader::VisitOMPAtomicDefaultMemOrderClause( - OMPAtomicDefaultMemOrderClause *C) { - C->setAtomicDefaultMemOrderKind( - static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Record.readInt())); - C->setLParenLoc(Record.readSourceLocation()); - C->setAtomicDefaultMemOrderKindKwLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) { - C->setLParenLoc(Record.readSourceLocation()); - unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setPrivateCopies(Vars); -} - -void OMPClauseReader::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) { - VisitOMPClauseWithPreInit(C); - C->setLParenLoc(Record.readSourceLocation()); - unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setPrivateCopies(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setInits(Vars); -} - -void OMPClauseReader::VisitOMPLastprivateClause(OMPLastprivateClause *C) { - VisitOMPClauseWithPostUpdate(C); - C->setLParenLoc(Record.readSourceLocation()); - unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setPrivateCopies(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setSourceExprs(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setDestinationExprs(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setAssignmentOps(Vars); -} - -void OMPClauseReader::VisitOMPSharedClause(OMPSharedClause *C) { - C->setLParenLoc(Record.readSourceLocation()); - unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); -} - -void OMPClauseReader::VisitOMPReductionClause(OMPReductionClause *C) { - VisitOMPClauseWithPostUpdate(C); - C->setLParenLoc(Record.readSourceLocation()); - C->setColonLoc(Record.readSourceLocation()); - NestedNameSpecifierLoc NNSL = Record.readNestedNameSpecifierLoc(); - DeclarationNameInfo DNI; - Record.readDeclarationNameInfo(DNI); - C->setQualifierLoc(NNSL); - C->setNameInfo(DNI); - - unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setPrivates(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setLHSExprs(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setRHSExprs(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setReductionOps(Vars); -} - -void OMPClauseReader::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) { - VisitOMPClauseWithPostUpdate(C); - C->setLParenLoc(Record.readSourceLocation()); - C->setColonLoc(Record.readSourceLocation()); - NestedNameSpecifierLoc NNSL = Record.readNestedNameSpecifierLoc(); - DeclarationNameInfo DNI; - Record.readDeclarationNameInfo(DNI); - C->setQualifierLoc(NNSL); - C->setNameInfo(DNI); - - unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned I = 0; I != NumVars; ++I) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); - Vars.clear(); - for (unsigned I = 0; I != NumVars; ++I) - Vars.push_back(Record.readSubExpr()); - C->setPrivates(Vars); - Vars.clear(); - for (unsigned I = 0; I != NumVars; ++I) - Vars.push_back(Record.readSubExpr()); - C->setLHSExprs(Vars); - Vars.clear(); - for (unsigned I = 0; I != NumVars; ++I) - Vars.push_back(Record.readSubExpr()); - C->setRHSExprs(Vars); - Vars.clear(); - for (unsigned I = 0; I != NumVars; ++I) - Vars.push_back(Record.readSubExpr()); - C->setReductionOps(Vars); -} - -void OMPClauseReader::VisitOMPInReductionClause(OMPInReductionClause *C) { - VisitOMPClauseWithPostUpdate(C); - C->setLParenLoc(Record.readSourceLocation()); - C->setColonLoc(Record.readSourceLocation()); - NestedNameSpecifierLoc NNSL = Record.readNestedNameSpecifierLoc(); - DeclarationNameInfo DNI; - Record.readDeclarationNameInfo(DNI); - C->setQualifierLoc(NNSL); - C->setNameInfo(DNI); - - unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned I = 0; I != NumVars; ++I) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); - Vars.clear(); - for (unsigned I = 0; I != NumVars; ++I) - Vars.push_back(Record.readSubExpr()); - C->setPrivates(Vars); - Vars.clear(); - for (unsigned I = 0; I != NumVars; ++I) - Vars.push_back(Record.readSubExpr()); - C->setLHSExprs(Vars); - Vars.clear(); - for (unsigned I = 0; I != NumVars; ++I) - Vars.push_back(Record.readSubExpr()); - C->setRHSExprs(Vars); - Vars.clear(); - for (unsigned I = 0; I != NumVars; ++I) - Vars.push_back(Record.readSubExpr()); - C->setReductionOps(Vars); - Vars.clear(); - for (unsigned I = 0; I != NumVars; ++I) - Vars.push_back(Record.readSubExpr()); - C->setTaskgroupDescriptors(Vars); -} - -void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) { - VisitOMPClauseWithPostUpdate(C); - C->setLParenLoc(Record.readSourceLocation()); - C->setColonLoc(Record.readSourceLocation()); - C->setModifier(static_cast<OpenMPLinearClauseKind>(Record.readInt())); - C->setModifierLoc(Record.readSourceLocation()); - unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setPrivates(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setInits(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setUpdates(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setFinals(Vars); - C->setStep(Record.readSubExpr()); - C->setCalcStep(Record.readSubExpr()); -} - -void OMPClauseReader::VisitOMPAlignedClause(OMPAlignedClause *C) { - C->setLParenLoc(Record.readSourceLocation()); - C->setColonLoc(Record.readSourceLocation()); - unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); - C->setAlignment(Record.readSubExpr()); -} - -void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) { - C->setLParenLoc(Record.readSourceLocation()); - unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Exprs; - Exprs.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) - Exprs.push_back(Record.readSubExpr()); - C->setVarRefs(Exprs); - Exprs.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Exprs.push_back(Record.readSubExpr()); - C->setSourceExprs(Exprs); - Exprs.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Exprs.push_back(Record.readSubExpr()); - C->setDestinationExprs(Exprs); - Exprs.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Exprs.push_back(Record.readSubExpr()); - C->setAssignmentOps(Exprs); -} - -void OMPClauseReader::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) { - C->setLParenLoc(Record.readSourceLocation()); - unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Exprs; - Exprs.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) - Exprs.push_back(Record.readSubExpr()); - C->setVarRefs(Exprs); - Exprs.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Exprs.push_back(Record.readSubExpr()); - C->setSourceExprs(Exprs); - Exprs.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Exprs.push_back(Record.readSubExpr()); - C->setDestinationExprs(Exprs); - Exprs.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Exprs.push_back(Record.readSubExpr()); - C->setAssignmentOps(Exprs); -} - -void OMPClauseReader::VisitOMPFlushClause(OMPFlushClause *C) { - C->setLParenLoc(Record.readSourceLocation()); - unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); -} - -void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) { - C->setLParenLoc(Record.readSourceLocation()); - C->setDependencyKind( - static_cast<OpenMPDependClauseKind>(Record.readInt())); - C->setDependencyLoc(Record.readSourceLocation()); - C->setColonLoc(Record.readSourceLocation()); - unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned I = 0; I != NumVars; ++I) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); - for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) - C->setLoopData(I, Record.readSubExpr()); -} - -void OMPClauseReader::VisitOMPDeviceClause(OMPDeviceClause *C) { - VisitOMPClauseWithPreInit(C); - C->setDevice(Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) { - C->setLParenLoc(Record.readSourceLocation()); - for (unsigned I = 0; I < OMPMapClause::NumberOfModifiers; ++I) { - C->setMapTypeModifier( - I, static_cast<OpenMPMapModifierKind>(Record.readInt())); - C->setMapTypeModifierLoc(I, Record.readSourceLocation()); - } - C->setMapType( - static_cast<OpenMPMapClauseKind>(Record.readInt())); - C->setMapLoc(Record.readSourceLocation()); - C->setColonLoc(Record.readSourceLocation()); - auto NumVars = C->varlist_size(); - auto UniqueDecls = C->getUniqueDeclarationsNum(); - auto TotalLists = C->getTotalComponentListNum(); - auto TotalComponents = C->getTotalComponentsNum(); - - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); - - SmallVector<ValueDecl *, 16> Decls; - Decls.reserve(UniqueDecls); - for (unsigned i = 0; i < UniqueDecls; ++i) - Decls.push_back(Record.readDeclAs<ValueDecl>()); - C->setUniqueDecls(Decls); - - SmallVector<unsigned, 16> ListsPerDecl; - ListsPerDecl.reserve(UniqueDecls); - for (unsigned i = 0; i < UniqueDecls; ++i) - ListsPerDecl.push_back(Record.readInt()); - C->setDeclNumLists(ListsPerDecl); - - SmallVector<unsigned, 32> ListSizes; - ListSizes.reserve(TotalLists); - for (unsigned i = 0; i < TotalLists; ++i) - ListSizes.push_back(Record.readInt()); - C->setComponentListSizes(ListSizes); - - SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components; - Components.reserve(TotalComponents); - for (unsigned i = 0; i < TotalComponents; ++i) { - Expr *AssociatedExpr = Record.readSubExpr(); - auto *AssociatedDecl = Record.readDeclAs<ValueDecl>(); - Components.push_back(OMPClauseMappableExprCommon::MappableComponent( - AssociatedExpr, AssociatedDecl)); - } - C->setComponents(Components, ListSizes); -} - -void OMPClauseReader::VisitOMPNumTeamsClause(OMPNumTeamsClause *C) { - VisitOMPClauseWithPreInit(C); - C->setNumTeams(Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPThreadLimitClause(OMPThreadLimitClause *C) { - VisitOMPClauseWithPreInit(C); - C->setThreadLimit(Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPPriorityClause(OMPPriorityClause *C) { - C->setPriority(Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) { - C->setGrainsize(Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPNumTasksClause(OMPNumTasksClause *C) { - C->setNumTasks(Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPHintClause(OMPHintClause *C) { - C->setHint(Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) { - VisitOMPClauseWithPreInit(C); - C->setDistScheduleKind( - static_cast<OpenMPDistScheduleClauseKind>(Record.readInt())); - C->setChunkSize(Record.readSubExpr()); - C->setLParenLoc(Record.readSourceLocation()); - C->setDistScheduleKindLoc(Record.readSourceLocation()); - C->setCommaLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPDefaultmapClause(OMPDefaultmapClause *C) { - C->setDefaultmapKind( - static_cast<OpenMPDefaultmapClauseKind>(Record.readInt())); - C->setDefaultmapModifier( - static_cast<OpenMPDefaultmapClauseModifier>(Record.readInt())); - C->setLParenLoc(Record.readSourceLocation()); - C->setDefaultmapModifierLoc(Record.readSourceLocation()); - C->setDefaultmapKindLoc(Record.readSourceLocation()); -} - -void OMPClauseReader::VisitOMPToClause(OMPToClause *C) { - C->setLParenLoc(Record.readSourceLocation()); - auto NumVars = C->varlist_size(); - auto UniqueDecls = C->getUniqueDeclarationsNum(); - auto TotalLists = C->getTotalComponentListNum(); - auto TotalComponents = C->getTotalComponentsNum(); - - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); - - SmallVector<ValueDecl *, 16> Decls; - Decls.reserve(UniqueDecls); - for (unsigned i = 0; i < UniqueDecls; ++i) - Decls.push_back(Record.readDeclAs<ValueDecl>()); - C->setUniqueDecls(Decls); - - SmallVector<unsigned, 16> ListsPerDecl; - ListsPerDecl.reserve(UniqueDecls); - for (unsigned i = 0; i < UniqueDecls; ++i) - ListsPerDecl.push_back(Record.readInt()); - C->setDeclNumLists(ListsPerDecl); - - SmallVector<unsigned, 32> ListSizes; - ListSizes.reserve(TotalLists); - for (unsigned i = 0; i < TotalLists; ++i) - ListSizes.push_back(Record.readInt()); - C->setComponentListSizes(ListSizes); - - SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components; - Components.reserve(TotalComponents); - for (unsigned i = 0; i < TotalComponents; ++i) { - Expr *AssociatedExpr = Record.readSubExpr(); - auto *AssociatedDecl = Record.readDeclAs<ValueDecl>(); - Components.push_back(OMPClauseMappableExprCommon::MappableComponent( - AssociatedExpr, AssociatedDecl)); - } - C->setComponents(Components, ListSizes); -} - -void OMPClauseReader::VisitOMPFromClause(OMPFromClause *C) { - C->setLParenLoc(Record.readSourceLocation()); - auto NumVars = C->varlist_size(); - auto UniqueDecls = C->getUniqueDeclarationsNum(); - auto TotalLists = C->getTotalComponentListNum(); - auto TotalComponents = C->getTotalComponentsNum(); - - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); - - SmallVector<ValueDecl *, 16> Decls; - Decls.reserve(UniqueDecls); - for (unsigned i = 0; i < UniqueDecls; ++i) - Decls.push_back(Record.readDeclAs<ValueDecl>()); - C->setUniqueDecls(Decls); - - SmallVector<unsigned, 16> ListsPerDecl; - ListsPerDecl.reserve(UniqueDecls); - for (unsigned i = 0; i < UniqueDecls; ++i) - ListsPerDecl.push_back(Record.readInt()); - C->setDeclNumLists(ListsPerDecl); - - SmallVector<unsigned, 32> ListSizes; - ListSizes.reserve(TotalLists); - for (unsigned i = 0; i < TotalLists; ++i) - ListSizes.push_back(Record.readInt()); - C->setComponentListSizes(ListSizes); - - SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components; - Components.reserve(TotalComponents); - for (unsigned i = 0; i < TotalComponents; ++i) { - Expr *AssociatedExpr = Record.readSubExpr(); - auto *AssociatedDecl = Record.readDeclAs<ValueDecl>(); - Components.push_back(OMPClauseMappableExprCommon::MappableComponent( - AssociatedExpr, AssociatedDecl)); - } - C->setComponents(Components, ListSizes); -} - -void OMPClauseReader::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *C) { - C->setLParenLoc(Record.readSourceLocation()); - auto NumVars = C->varlist_size(); - auto UniqueDecls = C->getUniqueDeclarationsNum(); - auto TotalLists = C->getTotalComponentListNum(); - auto TotalComponents = C->getTotalComponentsNum(); - - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setPrivateCopies(Vars); - Vars.clear(); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setInits(Vars); - - SmallVector<ValueDecl *, 16> Decls; - Decls.reserve(UniqueDecls); - for (unsigned i = 0; i < UniqueDecls; ++i) - Decls.push_back(Record.readDeclAs<ValueDecl>()); - C->setUniqueDecls(Decls); - - SmallVector<unsigned, 16> ListsPerDecl; - ListsPerDecl.reserve(UniqueDecls); - for (unsigned i = 0; i < UniqueDecls; ++i) - ListsPerDecl.push_back(Record.readInt()); - C->setDeclNumLists(ListsPerDecl); - - SmallVector<unsigned, 32> ListSizes; - ListSizes.reserve(TotalLists); - for (unsigned i = 0; i < TotalLists; ++i) - ListSizes.push_back(Record.readInt()); - C->setComponentListSizes(ListSizes); - - SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components; - Components.reserve(TotalComponents); - for (unsigned i = 0; i < TotalComponents; ++i) { - Expr *AssociatedExpr = Record.readSubExpr(); - auto *AssociatedDecl = Record.readDeclAs<ValueDecl>(); - Components.push_back(OMPClauseMappableExprCommon::MappableComponent( - AssociatedExpr, AssociatedDecl)); - } - C->setComponents(Components, ListSizes); -} - -void OMPClauseReader::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) { - C->setLParenLoc(Record.readSourceLocation()); - auto NumVars = C->varlist_size(); - auto UniqueDecls = C->getUniqueDeclarationsNum(); - auto TotalLists = C->getTotalComponentListNum(); - auto TotalComponents = C->getTotalComponentsNum(); - - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Record.readSubExpr()); - C->setVarRefs(Vars); - Vars.clear(); - - SmallVector<ValueDecl *, 16> Decls; - Decls.reserve(UniqueDecls); - for (unsigned i = 0; i < UniqueDecls; ++i) - Decls.push_back(Record.readDeclAs<ValueDecl>()); - C->setUniqueDecls(Decls); - - SmallVector<unsigned, 16> ListsPerDecl; - ListsPerDecl.reserve(UniqueDecls); - for (unsigned i = 0; i < UniqueDecls; ++i) - ListsPerDecl.push_back(Record.readInt()); - C->setDeclNumLists(ListsPerDecl); - - SmallVector<unsigned, 32> ListSizes; - ListSizes.reserve(TotalLists); - for (unsigned i = 0; i < TotalLists; ++i) - ListSizes.push_back(Record.readInt()); - C->setComponentListSizes(ListSizes); - - SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components; - Components.reserve(TotalComponents); - for (unsigned i = 0; i < TotalComponents; ++i) { - Expr *AssociatedExpr = Record.readSubExpr(); - auto *AssociatedDecl = Record.readDeclAs<ValueDecl>(); - Components.push_back(OMPClauseMappableExprCommon::MappableComponent( - AssociatedExpr, AssociatedDecl)); - } - C->setComponents(Components, ListSizes); -} diff --git a/gnu/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/gnu/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp deleted file mode 100644 index 763ab527570..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp +++ /dev/null @@ -1,4471 +0,0 @@ -//===- ASTReaderDecl.cpp - Decl Deserialization ---------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the ASTReader::ReadDeclRecord method, which is the -// entrypoint for loading a decl. -// -//===----------------------------------------------------------------------===// - -#include "ASTCommon.h" -#include "ASTReaderInternals.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Attr.h" -#include "clang/AST/AttrIterator.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclBase.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclFriend.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclOpenMP.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/DeclVisitor.h" -#include "clang/AST/DeclarationName.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExternalASTSource.h" -#include "clang/AST/LambdaCapture.h" -#include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/OpenMPClause.h" -#include "clang/AST/Redeclarable.h" -#include "clang/AST/Stmt.h" -#include "clang/AST/TemplateBase.h" -#include "clang/AST/Type.h" -#include "clang/AST/UnresolvedSet.h" -#include "clang/Basic/AttrKinds.h" -#include "clang/Basic/ExceptionSpecificationType.h" -#include "clang/Basic/IdentifierTable.h" -#include "clang/Basic/LLVM.h" -#include "clang/Basic/Lambda.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/Linkage.h" -#include "clang/Basic/Module.h" -#include "clang/Basic/PragmaKinds.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Basic/Specifiers.h" -#include "clang/Sema/IdentifierResolver.h" -#include "clang/Serialization/ASTBitCodes.h" -#include "clang/Serialization/ASTReader.h" -#include "clang/Serialization/ContinuousRangeMap.h" -#include "clang/Serialization/Module.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/Bitcode/BitstreamReader.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/SaveAndRestore.h" -#include <algorithm> -#include <cassert> -#include <cstdint> -#include <cstring> -#include <string> -#include <utility> - -using namespace clang; -using namespace serialization; - -//===----------------------------------------------------------------------===// -// Declaration deserialization -//===----------------------------------------------------------------------===// - -namespace clang { - - class ASTDeclReader : public DeclVisitor<ASTDeclReader, void> { - ASTReader &Reader; - ASTRecordReader &Record; - ASTReader::RecordLocation Loc; - const DeclID ThisDeclID; - const SourceLocation ThisDeclLoc; - - using RecordData = ASTReader::RecordData; - - TypeID DeferredTypeID = 0; - unsigned AnonymousDeclNumber; - GlobalDeclID NamedDeclForTagDecl = 0; - IdentifierInfo *TypedefNameForLinkage = nullptr; - - bool HasPendingBody = false; - - ///A flag to carry the information for a decl from the entity is - /// used. We use it to delay the marking of the canonical decl as used until - /// the entire declaration is deserialized and merged. - bool IsDeclMarkedUsed = false; - - uint64_t GetCurrentCursorOffset(); - - uint64_t ReadLocalOffset() { - uint64_t LocalOffset = Record.readInt(); - assert(LocalOffset < Loc.Offset && "offset point after current record"); - return LocalOffset ? Loc.Offset - LocalOffset : 0; - } - - uint64_t ReadGlobalOffset() { - uint64_t Local = ReadLocalOffset(); - return Local ? Record.getGlobalBitOffset(Local) : 0; - } - - SourceLocation ReadSourceLocation() { - return Record.readSourceLocation(); - } - - SourceRange ReadSourceRange() { - return Record.readSourceRange(); - } - - TypeSourceInfo *GetTypeSourceInfo() { - return Record.getTypeSourceInfo(); - } - - serialization::DeclID ReadDeclID() { - return Record.readDeclID(); - } - - std::string ReadString() { - return Record.readString(); - } - - void ReadDeclIDList(SmallVectorImpl<DeclID> &IDs) { - for (unsigned I = 0, Size = Record.readInt(); I != Size; ++I) - IDs.push_back(ReadDeclID()); - } - - Decl *ReadDecl() { - return Record.readDecl(); - } - - template<typename T> - T *ReadDeclAs() { - return Record.readDeclAs<T>(); - } - - void ReadQualifierInfo(QualifierInfo &Info) { - Record.readQualifierInfo(Info); - } - - void ReadDeclarationNameLoc(DeclarationNameLoc &DNLoc, DeclarationName Name) { - Record.readDeclarationNameLoc(DNLoc, Name); - } - - serialization::SubmoduleID readSubmoduleID() { - if (Record.getIdx() == Record.size()) - return 0; - - return Record.getGlobalSubmoduleID(Record.readInt()); - } - - Module *readModule() { - return Record.getSubmodule(readSubmoduleID()); - } - - void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update); - void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data, - const CXXRecordDecl *D); - void MergeDefinitionData(CXXRecordDecl *D, - struct CXXRecordDecl::DefinitionData &&NewDD); - void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data); - void MergeDefinitionData(ObjCInterfaceDecl *D, - struct ObjCInterfaceDecl::DefinitionData &&NewDD); - void ReadObjCDefinitionData(struct ObjCProtocolDecl::DefinitionData &Data); - void MergeDefinitionData(ObjCProtocolDecl *D, - struct ObjCProtocolDecl::DefinitionData &&NewDD); - - static DeclContext *getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC); - - static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader, - DeclContext *DC, - unsigned Index); - static void setAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, - unsigned Index, NamedDecl *D); - - /// Results from loading a RedeclarableDecl. - class RedeclarableResult { - Decl *MergeWith; - GlobalDeclID FirstID; - bool IsKeyDecl; - - public: - RedeclarableResult(Decl *MergeWith, GlobalDeclID FirstID, bool IsKeyDecl) - : MergeWith(MergeWith), FirstID(FirstID), IsKeyDecl(IsKeyDecl) {} - - /// Retrieve the first ID. - GlobalDeclID getFirstID() const { return FirstID; } - - /// Is this declaration a key declaration? - bool isKeyDecl() const { return IsKeyDecl; } - - /// Get a known declaration that this should be merged with, if - /// any. - Decl *getKnownMergeTarget() const { return MergeWith; } - }; - - /// 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 = nullptr; - NamedDecl *Existing = nullptr; - bool AddResult = false; - unsigned AnonymousDeclNumber = 0; - IdentifierInfo *TypedefNameForLinkage = nullptr; - - public: - FindExistingResult(ASTReader &Reader) : Reader(Reader) {} - - FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing, - unsigned AnonymousDeclNumber, - IdentifierInfo *TypedefNameForLinkage) - : Reader(Reader), New(New), Existing(Existing), AddResult(true), - AnonymousDeclNumber(AnonymousDeclNumber), - TypedefNameForLinkage(TypedefNameForLinkage) {} - - FindExistingResult(FindExistingResult &&Other) - : Reader(Other.Reader), New(Other.New), Existing(Other.Existing), - AddResult(Other.AddResult), - AnonymousDeclNumber(Other.AnonymousDeclNumber), - TypedefNameForLinkage(Other.TypedefNameForLinkage) { - Other.AddResult = false; - } - - FindExistingResult &operator=(FindExistingResult &&) = delete; - ~FindExistingResult(); - - /// Suppress the addition of this result into the known set of - /// names. - void suppress() { AddResult = false; } - - operator NamedDecl*() const { return Existing; } - - template<typename T> - operator T*() const { return dyn_cast_or_null<T>(Existing); } - }; - - static DeclContext *getPrimaryContextForMerging(ASTReader &Reader, - DeclContext *DC); - FindExistingResult findExisting(NamedDecl *D); - - public: - ASTDeclReader(ASTReader &Reader, ASTRecordReader &Record, - ASTReader::RecordLocation Loc, - DeclID thisDeclID, SourceLocation ThisDeclLoc) - : Reader(Reader), Record(Record), Loc(Loc), ThisDeclID(thisDeclID), - ThisDeclLoc(ThisDeclLoc) {} - - template <typename T> static - void AddLazySpecializations(T *D, - SmallVectorImpl<serialization::DeclID>& IDs) { - if (IDs.empty()) - return; - - // FIXME: We should avoid this pattern of getting the ASTContext. - ASTContext &C = D->getASTContext(); - - auto *&LazySpecializations = D->getCommonPtr()->LazySpecializations; - - if (auto &Old = LazySpecializations) { - IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]); - llvm::sort(IDs); - IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end()); - } - - auto *Result = new (C) serialization::DeclID[1 + IDs.size()]; - *Result = IDs.size(); - std::copy(IDs.begin(), IDs.end(), Result + 1); - - LazySpecializations = Result; - } - - template <typename DeclT> - static Decl *getMostRecentDeclImpl(Redeclarable<DeclT> *D); - static Decl *getMostRecentDeclImpl(...); - static Decl *getMostRecentDecl(Decl *D); - - template <typename DeclT> - static void attachPreviousDeclImpl(ASTReader &Reader, - Redeclarable<DeclT> *D, Decl *Previous, - Decl *Canon); - static void attachPreviousDeclImpl(ASTReader &Reader, ...); - static void attachPreviousDecl(ASTReader &Reader, Decl *D, Decl *Previous, - Decl *Canon); - - template <typename DeclT> - static void attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest); - static void attachLatestDeclImpl(...); - static void attachLatestDecl(Decl *D, Decl *latest); - - template <typename DeclT> - static void markIncompleteDeclChainImpl(Redeclarable<DeclT> *D); - static void markIncompleteDeclChainImpl(...); - - /// Determine whether this declaration has a pending body. - bool hasPendingBody() const { return HasPendingBody; } - - void ReadFunctionDefinition(FunctionDecl *FD); - void Visit(Decl *D); - - void UpdateDecl(Decl *D, SmallVectorImpl<serialization::DeclID> &); - - static void setNextObjCCategory(ObjCCategoryDecl *Cat, - ObjCCategoryDecl *Next) { - Cat->NextClassCategory = Next; - } - - void VisitDecl(Decl *D); - void VisitPragmaCommentDecl(PragmaCommentDecl *D); - void VisitPragmaDetectMismatchDecl(PragmaDetectMismatchDecl *D); - void VisitTranslationUnitDecl(TranslationUnitDecl *TU); - void VisitNamedDecl(NamedDecl *ND); - void VisitLabelDecl(LabelDecl *LD); - void VisitNamespaceDecl(NamespaceDecl *D); - void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); - void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); - void VisitTypeDecl(TypeDecl *TD); - RedeclarableResult VisitTypedefNameDecl(TypedefNameDecl *TD); - void VisitTypedefDecl(TypedefDecl *TD); - void VisitTypeAliasDecl(TypeAliasDecl *TD); - void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); - RedeclarableResult VisitTagDecl(TagDecl *TD); - void VisitEnumDecl(EnumDecl *ED); - RedeclarableResult VisitRecordDeclImpl(RecordDecl *RD); - void VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); } - RedeclarableResult VisitCXXRecordDeclImpl(CXXRecordDecl *D); - void VisitCXXRecordDecl(CXXRecordDecl *D) { VisitCXXRecordDeclImpl(D); } - RedeclarableResult VisitClassTemplateSpecializationDeclImpl( - ClassTemplateSpecializationDecl *D); - - void VisitClassTemplateSpecializationDecl( - ClassTemplateSpecializationDecl *D) { - VisitClassTemplateSpecializationDeclImpl(D); - } - - void VisitClassTemplatePartialSpecializationDecl( - ClassTemplatePartialSpecializationDecl *D); - void VisitClassScopeFunctionSpecializationDecl( - ClassScopeFunctionSpecializationDecl *D); - RedeclarableResult - VisitVarTemplateSpecializationDeclImpl(VarTemplateSpecializationDecl *D); - - void VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) { - VisitVarTemplateSpecializationDeclImpl(D); - } - - void VisitVarTemplatePartialSpecializationDecl( - VarTemplatePartialSpecializationDecl *D); - void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); - void VisitValueDecl(ValueDecl *VD); - void VisitEnumConstantDecl(EnumConstantDecl *ECD); - void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); - void VisitDeclaratorDecl(DeclaratorDecl *DD); - void VisitFunctionDecl(FunctionDecl *FD); - void VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *GD); - void VisitCXXMethodDecl(CXXMethodDecl *D); - void VisitCXXConstructorDecl(CXXConstructorDecl *D); - void VisitCXXDestructorDecl(CXXDestructorDecl *D); - void VisitCXXConversionDecl(CXXConversionDecl *D); - void VisitFieldDecl(FieldDecl *FD); - void VisitMSPropertyDecl(MSPropertyDecl *FD); - void VisitIndirectFieldDecl(IndirectFieldDecl *FD); - RedeclarableResult VisitVarDeclImpl(VarDecl *D); - void VisitVarDecl(VarDecl *VD) { VisitVarDeclImpl(VD); } - void VisitImplicitParamDecl(ImplicitParamDecl *PD); - void VisitParmVarDecl(ParmVarDecl *PD); - void VisitDecompositionDecl(DecompositionDecl *DD); - void VisitBindingDecl(BindingDecl *BD); - void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); - DeclID VisitTemplateDecl(TemplateDecl *D); - RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); - void VisitClassTemplateDecl(ClassTemplateDecl *D); - void VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D); - void VisitVarTemplateDecl(VarTemplateDecl *D); - void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); - void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); - void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); - void VisitUsingDecl(UsingDecl *D); - void VisitUsingPackDecl(UsingPackDecl *D); - void VisitUsingShadowDecl(UsingShadowDecl *D); - void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D); - void VisitLinkageSpecDecl(LinkageSpecDecl *D); - void VisitExportDecl(ExportDecl *D); - void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD); - void VisitImportDecl(ImportDecl *D); - void VisitAccessSpecDecl(AccessSpecDecl *D); - void VisitFriendDecl(FriendDecl *D); - void VisitFriendTemplateDecl(FriendTemplateDecl *D); - void VisitStaticAssertDecl(StaticAssertDecl *D); - void VisitBlockDecl(BlockDecl *BD); - void VisitCapturedDecl(CapturedDecl *CD); - void VisitEmptyDecl(EmptyDecl *D); - - std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC); - - template<typename T> - RedeclarableResult VisitRedeclarable(Redeclarable<T> *D); - - template<typename T> - void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl, - DeclID TemplatePatternID = 0); - - template<typename T> - void mergeRedeclarable(Redeclarable<T> *D, T *Existing, - RedeclarableResult &Redecl, - DeclID TemplatePatternID = 0); - - template<typename T> - void mergeMergeable(Mergeable<T> *D); - - void mergeTemplatePattern(RedeclarableTemplateDecl *D, - RedeclarableTemplateDecl *Existing, - DeclID DsID, bool IsKeyDecl); - - ObjCTypeParamList *ReadObjCTypeParamList(); - - // FIXME: Reorder according to DeclNodes.td? - void VisitObjCMethodDecl(ObjCMethodDecl *D); - void VisitObjCTypeParamDecl(ObjCTypeParamDecl *D); - void VisitObjCContainerDecl(ObjCContainerDecl *D); - void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); - void VisitObjCIvarDecl(ObjCIvarDecl *D); - void VisitObjCProtocolDecl(ObjCProtocolDecl *D); - void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D); - void VisitObjCCategoryDecl(ObjCCategoryDecl *D); - void VisitObjCImplDecl(ObjCImplDecl *D); - void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); - void VisitObjCImplementationDecl(ObjCImplementationDecl *D); - void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); - void VisitObjCPropertyDecl(ObjCPropertyDecl *D); - void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); - void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); - void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D); - void VisitOMPRequiresDecl(OMPRequiresDecl *D); - void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D); - }; - -} // namespace clang - -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; - DeclT *Canonical = nullptr; - DeclT *Current = nullptr; - -public: - MergedRedeclIterator() = default; - MergedRedeclIterator(DeclT *Start) : Start(Start), 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; - } -}; - -} // namespace - -template <typename DeclT> -static llvm::iterator_range<MergedRedeclIterator<DeclT>> -merged_redecls(DeclT *D) { - return llvm::make_range(MergedRedeclIterator<DeclT>(D), - MergedRedeclIterator<DeclT>()); -} - -uint64_t ASTDeclReader::GetCurrentCursorOffset() { - return Loc.F->DeclsCursor.GetCurrentBitNo() + Loc.F->GlobalBitOffset; -} - -void ASTDeclReader::ReadFunctionDefinition(FunctionDecl *FD) { - if (Record.readInt()) - Reader.DefinitionSource[FD] = Loc.F->Kind == ModuleKind::MK_MainFile; - if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) { - CD->setNumCtorInitializers(Record.readInt()); - if (CD->getNumCtorInitializers()) - CD->CtorInitializers = ReadGlobalOffset(); - } - // Store the offset of the body so we can lazily load it later. - Reader.PendingBodies[FD] = GetCurrentCursorOffset(); - HasPendingBody = true; -} - -void ASTDeclReader::Visit(Decl *D) { - DeclVisitor<ASTDeclReader, void>::Visit(D); - - // At this point we have deserialized and merged the decl and it is safe to - // update its canonical decl to signal that the entire entity is used. - D->getCanonicalDecl()->Used |= IsDeclMarkedUsed; - IsDeclMarkedUsed = false; - - if (auto *DD = dyn_cast<DeclaratorDecl>(D)) { - if (auto *TInfo = DD->getTypeSourceInfo()) - Record.readTypeLoc(TInfo->getTypeLoc()); - } - - if (auto *TD = dyn_cast<TypeDecl>(D)) { - // We have a fully initialized TypeDecl. Read its type now. - TD->setTypeForDecl(Reader.GetType(DeferredTypeID).getTypePtrOrNull()); - - // 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)->TypedefNameDeclOrQualifier = - cast<TypedefNameDecl>(Reader.GetDecl(NamedDeclForTagDecl)); - } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) { - // if we have a fully initialized TypeDecl, we can safely read its type now. - ID->TypeForDecl = Reader.GetType(DeferredTypeID).getTypePtrOrNull(); - } else if (auto *FD = dyn_cast<FunctionDecl>(D)) { - // FunctionDecl's body was written last after all other Stmts/Exprs. - // We only read it if FD doesn't already have a body (e.g., from another - // module). - // FIXME: Can we diagnose ODR violations somehow? - if (Record.readInt()) - ReadFunctionDefinition(FD); - } -} - -void ASTDeclReader::VisitDecl(Decl *D) { - if (D->isTemplateParameter() || D->isTemplateParameterPack() || - isa<ParmVarDecl>(D)) { - // We don't want to deserialize the DeclContext of a template - // 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. - GlobalDeclID SemaDCIDForTemplateParmDecl = ReadDeclID(); - GlobalDeclID LexicalDCIDForTemplateParmDecl = ReadDeclID(); - if (!LexicalDCIDForTemplateParmDecl) - LexicalDCIDForTemplateParmDecl = SemaDCIDForTemplateParmDecl; - Reader.addPendingDeclContextInfo(D, - SemaDCIDForTemplateParmDecl, - LexicalDCIDForTemplateParmDecl); - D->setDeclContext(Reader.getContext().getTranslationUnitDecl()); - } else { - auto *SemaDC = ReadDeclAs<DeclContext>(); - auto *LexicalDC = ReadDeclAs<DeclContext>(); - if (!LexicalDC) - LexicalDC = SemaDC; - DeclContext *MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC); - // Avoid calling setLexicalDeclContext() directly because it uses - // Decl::getASTContext() internally which is unsafe during derialization. - D->setDeclContextsImpl(MergedSemaDC ? MergedSemaDC : SemaDC, LexicalDC, - Reader.getContext()); - } - D->setLocation(ThisDeclLoc); - D->setInvalidDecl(Record.readInt()); - if (Record.readInt()) { // hasAttrs - AttrVec Attrs; - Record.readAttributes(Attrs); - // Avoid calling setAttrs() directly because it uses Decl::getASTContext() - // internally which is unsafe during derialization. - D->setAttrsImpl(Attrs, Reader.getContext()); - } - D->setImplicit(Record.readInt()); - D->Used = Record.readInt(); - IsDeclMarkedUsed |= D->Used; - D->setReferenced(Record.readInt()); - D->setTopLevelDeclInObjCContainer(Record.readInt()); - D->setAccess((AccessSpecifier)Record.readInt()); - D->FromASTFile = true; - bool ModulePrivate = Record.readInt(); - - // Determine whether this declaration is part of a (sub)module. If so, it - // may not yet be visible. - if (unsigned SubmoduleID = readSubmoduleID()) { - // Store the owning submodule ID in the declaration. - D->setModuleOwnershipKind( - ModulePrivate ? Decl::ModuleOwnershipKind::ModulePrivate - : Decl::ModuleOwnershipKind::VisibleWhenImported); - D->setOwningModuleID(SubmoduleID); - - if (ModulePrivate) { - // 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. - } else if (Module *Owner = Reader.getSubmodule(SubmoduleID)) { - // Mark the declaration as visible when its owning module becomes visible. - if (Owner->NameVisibility == Module::AllVisible) - D->setVisibleDespiteOwningModule(); - else - Reader.HiddenNamesMap[Owner].push_back(D); - } - } else if (ModulePrivate) { - D->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ModulePrivate); - } -} - -void ASTDeclReader::VisitPragmaCommentDecl(PragmaCommentDecl *D) { - VisitDecl(D); - D->setLocation(ReadSourceLocation()); - D->CommentKind = (PragmaMSCommentKind)Record.readInt(); - std::string Arg = ReadString(); - memcpy(D->getTrailingObjects<char>(), Arg.data(), Arg.size()); - D->getTrailingObjects<char>()[Arg.size()] = '\0'; -} - -void ASTDeclReader::VisitPragmaDetectMismatchDecl(PragmaDetectMismatchDecl *D) { - VisitDecl(D); - D->setLocation(ReadSourceLocation()); - std::string Name = ReadString(); - memcpy(D->getTrailingObjects<char>(), Name.data(), Name.size()); - D->getTrailingObjects<char>()[Name.size()] = '\0'; - - D->ValueStart = Name.size() + 1; - std::string Value = ReadString(); - memcpy(D->getTrailingObjects<char>() + D->ValueStart, Value.data(), - Value.size()); - D->getTrailingObjects<char>()[D->ValueStart + Value.size()] = '\0'; -} - -void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { - llvm_unreachable("Translation units are not serialized"); -} - -void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) { - VisitDecl(ND); - ND->setDeclName(Record.readDeclarationName()); - AnonymousDeclNumber = Record.readInt(); -} - -void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { - VisitNamedDecl(TD); - TD->setLocStart(ReadSourceLocation()); - // Delay type reading until after we have fully initialized the decl. - DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); -} - -ASTDeclReader::RedeclarableResult -ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) { - RedeclarableResult Redecl = VisitRedeclarable(TD); - VisitTypeDecl(TD); - TypeSourceInfo *TInfo = GetTypeSourceInfo(); - if (Record.readInt()) { // isModed - QualType modedT = Record.readType(); - TD->setModedTypeSourceInfo(TInfo, modedT); - } else - TD->setTypeSourceInfo(TInfo); - // Read and discard the declaration for which this is a typedef name for - // linkage, if it exists. We cannot rely on our type to pull in this decl, - // because it might have been merged with a type from another module and - // thus might not refer to our version of the declaration. - ReadDecl(); - return Redecl; -} - -void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) { - RedeclarableResult Redecl = VisitTypedefNameDecl(TD); - mergeRedeclarable(TD, Redecl); -} - -void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) { - RedeclarableResult Redecl = VisitTypedefNameDecl(TD); - if (auto *Template = ReadDeclAs<TypeAliasTemplateDecl>()) - // Merged when we merge the template. - TD->setDescribedAliasTemplate(Template); - else - mergeRedeclarable(TD, Redecl); -} - -ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) { - RedeclarableResult Redecl = VisitRedeclarable(TD); - VisitTypeDecl(TD); - - TD->IdentifierNamespace = Record.readInt(); - TD->setTagKind((TagDecl::TagKind)Record.readInt()); - if (!isa<CXXRecordDecl>(TD)) - TD->setCompleteDefinition(Record.readInt()); - TD->setEmbeddedInDeclarator(Record.readInt()); - TD->setFreeStanding(Record.readInt()); - TD->setCompleteDefinitionRequired(Record.readInt()); - TD->setBraceRange(ReadSourceRange()); - - switch (Record.readInt()) { - case 0: - break; - case 1: { // ExtInfo - auto *Info = new (Reader.getContext()) TagDecl::ExtInfo(); - ReadQualifierInfo(*Info); - TD->TypedefNameDeclOrQualifier = Info; - break; - } - case 2: // TypedefNameForAnonDecl - NamedDeclForTagDecl = ReadDeclID(); - TypedefNameForLinkage = Record.getIdentifierInfo(); - break; - default: - llvm_unreachable("unexpected tag info kind"); - } - - if (!isa<CXXRecordDecl>(TD)) - mergeRedeclarable(TD, Redecl); - return Redecl; -} - -void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { - VisitTagDecl(ED); - if (TypeSourceInfo *TI = GetTypeSourceInfo()) - ED->setIntegerTypeSourceInfo(TI); - else - ED->setIntegerType(Record.readType()); - ED->setPromotionType(Record.readType()); - ED->setNumPositiveBits(Record.readInt()); - ED->setNumNegativeBits(Record.readInt()); - ED->setScoped(Record.readInt()); - ED->setScopedUsingClassTag(Record.readInt()); - ED->setFixed(Record.readInt()); - - ED->setHasODRHash(true); - ED->ODRHash = Record.readInt(); - - // 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) { - 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) { - Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef)); - ED->setCompleteDefinition(false); - Reader.mergeDefinitionVisibility(OldDef, ED); - if (OldDef->getODRHash() != ED->getODRHash()) - Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED); - } else { - OldDef = ED; - } - } - - if (auto *InstED = ReadDeclAs<EnumDecl>()) { - auto TSK = (TemplateSpecializationKind)Record.readInt(); - SourceLocation POI = ReadSourceLocation(); - ED->setInstantiationOfMemberEnum(Reader.getContext(), InstED, TSK); - ED->getMemberSpecializationInfo()->setPointOfInstantiation(POI); - } -} - -ASTDeclReader::RedeclarableResult -ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { - RedeclarableResult Redecl = VisitTagDecl(RD); - RD->setHasFlexibleArrayMember(Record.readInt()); - RD->setAnonymousStructOrUnion(Record.readInt()); - RD->setHasObjectMember(Record.readInt()); - RD->setHasVolatileMember(Record.readInt()); - RD->setNonTrivialToPrimitiveDefaultInitialize(Record.readInt()); - RD->setNonTrivialToPrimitiveCopy(Record.readInt()); - RD->setNonTrivialToPrimitiveDestroy(Record.readInt()); - RD->setParamDestroyedInCallee(Record.readInt()); - RD->setArgPassingRestrictions((RecordDecl::ArgPassingKind)Record.readInt()); - return Redecl; -} - -void ASTDeclReader::VisitValueDecl(ValueDecl *VD) { - VisitNamedDecl(VD); - // For function declarations, defer reading the type in case the function has - // a deduced return type that references an entity declared within the - // function. - if (isa<FunctionDecl>(VD)) - DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); - else - VD->setType(Record.readType()); -} - -void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { - VisitValueDecl(ECD); - if (Record.readInt()) - ECD->setInitExpr(Record.readExpr()); - ECD->setInitVal(Record.readAPSInt()); - mergeMergeable(ECD); -} - -void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { - VisitValueDecl(DD); - DD->setInnerLocStart(ReadSourceLocation()); - if (Record.readInt()) { // hasExtInfo - auto *Info = new (Reader.getContext()) DeclaratorDecl::ExtInfo(); - ReadQualifierInfo(*Info); - DD->DeclInfo = Info; - } - QualType TSIType = Record.readType(); - DD->setTypeSourceInfo( - TSIType.isNull() ? nullptr - : Reader.getContext().CreateTypeSourceInfo(TSIType)); -} - -void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { - RedeclarableResult Redecl = VisitRedeclarable(FD); - VisitDeclaratorDecl(FD); - - // Attach a type to this function. Use the real type if possible, but fall - // back to the type as written if it involves a deduced return type. - if (FD->getTypeSourceInfo() && - FD->getTypeSourceInfo()->getType()->castAs<FunctionType>() - ->getReturnType()->getContainedAutoType()) { - // We'll set up the real type in Visit, once we've finished loading the - // function. - FD->setType(FD->getTypeSourceInfo()->getType()); - Reader.PendingFunctionTypes.push_back({FD, DeferredTypeID}); - } else { - FD->setType(Reader.GetType(DeferredTypeID)); - } - DeferredTypeID = 0; - - ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName()); - FD->IdentifierNamespace = Record.readInt(); - - // FunctionDecl's body is handled last at ASTDeclReader::Visit, - // after everything else is read. - - FD->setStorageClass(static_cast<StorageClass>(Record.readInt())); - FD->setInlineSpecified(Record.readInt()); - FD->setImplicitlyInline(Record.readInt()); - FD->setExplicitSpecified(Record.readInt()); - FD->setVirtualAsWritten(Record.readInt()); - FD->setPure(Record.readInt()); - FD->setHasInheritedPrototype(Record.readInt()); - FD->setHasWrittenPrototype(Record.readInt()); - FD->setDeletedAsWritten(Record.readInt()); - FD->setTrivial(Record.readInt()); - FD->setTrivialForCall(Record.readInt()); - FD->setDefaulted(Record.readInt()); - FD->setExplicitlyDefaulted(Record.readInt()); - FD->setHasImplicitReturnZero(Record.readInt()); - FD->setConstexpr(Record.readInt()); - FD->setUsesSEHTry(Record.readInt()); - FD->setHasSkippedBody(Record.readInt()); - FD->setIsMultiVersion(Record.readInt()); - FD->setLateTemplateParsed(Record.readInt()); - - FD->setCachedLinkage(static_cast<Linkage>(Record.readInt())); - FD->EndRangeLoc = ReadSourceLocation(); - - FD->ODRHash = Record.readInt(); - FD->setHasODRHash(true); - - switch ((FunctionDecl::TemplatedKind)Record.readInt()) { - case FunctionDecl::TK_NonTemplate: - mergeRedeclarable(FD, Redecl); - break; - case FunctionDecl::TK_FunctionTemplate: - // Merged when we merge the template. - FD->setDescribedFunctionTemplate(ReadDeclAs<FunctionTemplateDecl>()); - break; - case FunctionDecl::TK_MemberSpecialization: { - auto *InstFD = ReadDeclAs<FunctionDecl>(); - auto TSK = (TemplateSpecializationKind)Record.readInt(); - SourceLocation POI = ReadSourceLocation(); - FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK); - FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); - mergeRedeclarable(FD, Redecl); - break; - } - case FunctionDecl::TK_FunctionTemplateSpecialization: { - auto *Template = ReadDeclAs<FunctionTemplateDecl>(); - auto TSK = (TemplateSpecializationKind)Record.readInt(); - - // Template arguments. - SmallVector<TemplateArgument, 8> TemplArgs; - Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true); - - // Template args as written. - SmallVector<TemplateArgumentLoc, 8> TemplArgLocs; - SourceLocation LAngleLoc, RAngleLoc; - bool HasTemplateArgumentsAsWritten = Record.readInt(); - if (HasTemplateArgumentsAsWritten) { - unsigned NumTemplateArgLocs = Record.readInt(); - TemplArgLocs.reserve(NumTemplateArgLocs); - for (unsigned i = 0; i != NumTemplateArgLocs; ++i) - TemplArgLocs.push_back(Record.readTemplateArgumentLoc()); - - LAngleLoc = ReadSourceLocation(); - RAngleLoc = ReadSourceLocation(); - } - - SourceLocation POI = ReadSourceLocation(); - - ASTContext &C = Reader.getContext(); - TemplateArgumentList *TemplArgList - = TemplateArgumentList::CreateCopy(C, TemplArgs); - TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc); - for (unsigned i = 0, e = TemplArgLocs.size(); i != e; ++i) - TemplArgsInfo.addArgument(TemplArgLocs[i]); - FunctionTemplateSpecializationInfo *FTInfo - = FunctionTemplateSpecializationInfo::Create(C, FD, Template, TSK, - TemplArgList, - HasTemplateArgumentsAsWritten ? &TemplArgsInfo - : nullptr, - POI); - FD->TemplateOrSpecialization = FTInfo; - - if (FD->isCanonicalDecl()) { // if canonical add to template's set. - // The template that contains the specializations set. It's not safe to - // use getCanonicalDecl on Template since it may still be initializing. - auto *CanonTemplate = ReadDeclAs<FunctionTemplateDecl>(); - // 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. - llvm::FoldingSetNodeID ID; - FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs, C); - void *InsertPos = nullptr; - FunctionTemplateDecl::Common *CommonPtr = CanonTemplate->getCommonPtr(); - FunctionTemplateSpecializationInfo *ExistingInfo = - CommonPtr->Specializations.FindNodeOrInsertPos(ID, InsertPos); - if (InsertPos) - CommonPtr->Specializations.InsertNode(FTInfo, InsertPos); - else { - assert(Reader.getContext().getLangOpts().Modules && - "already deserialized this template specialization"); - mergeRedeclarable(FD, ExistingInfo->Function, Redecl); - } - } - break; - } - case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { - // Templates. - UnresolvedSet<8> TemplDecls; - unsigned NumTemplates = Record.readInt(); - while (NumTemplates--) - TemplDecls.addDecl(ReadDeclAs<NamedDecl>()); - - // Templates args. - TemplateArgumentListInfo TemplArgs; - unsigned NumArgs = Record.readInt(); - while (NumArgs--) - TemplArgs.addArgument(Record.readTemplateArgumentLoc()); - TemplArgs.setLAngleLoc(ReadSourceLocation()); - TemplArgs.setRAngleLoc(ReadSourceLocation()); - - FD->setDependentTemplateSpecialization(Reader.getContext(), - TemplDecls, TemplArgs); - // These are not merged; we don't need to merge redeclarations of dependent - // template friends. - break; - } - } - - // Read in the parameters. - unsigned NumParams = Record.readInt(); - SmallVector<ParmVarDecl *, 16> Params; - Params.reserve(NumParams); - for (unsigned I = 0; I != NumParams; ++I) - Params.push_back(ReadDeclAs<ParmVarDecl>()); - FD->setParams(Reader.getContext(), Params); -} - -void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { - VisitNamedDecl(MD); - if (Record.readInt()) { - // Load the body on-demand. Most clients won't care, because method - // definitions rarely show up in headers. - Reader.PendingBodies[MD] = GetCurrentCursorOffset(); - HasPendingBody = true; - MD->setSelfDecl(ReadDeclAs<ImplicitParamDecl>()); - MD->setCmdDecl(ReadDeclAs<ImplicitParamDecl>()); - } - MD->setInstanceMethod(Record.readInt()); - MD->setVariadic(Record.readInt()); - MD->setPropertyAccessor(Record.readInt()); - MD->setDefined(Record.readInt()); - MD->setOverriding(Record.readInt()); - MD->setHasSkippedBody(Record.readInt()); - - MD->setIsRedeclaration(Record.readInt()); - MD->setHasRedeclaration(Record.readInt()); - if (MD->hasRedeclaration()) - Reader.getContext().setObjCMethodRedeclaration(MD, - ReadDeclAs<ObjCMethodDecl>()); - - MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record.readInt()); - MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record.readInt()); - MD->setRelatedResultType(Record.readInt()); - MD->setReturnType(Record.readType()); - MD->setReturnTypeSourceInfo(GetTypeSourceInfo()); - MD->DeclEndLoc = ReadSourceLocation(); - unsigned NumParams = Record.readInt(); - SmallVector<ParmVarDecl *, 16> Params; - Params.reserve(NumParams); - for (unsigned I = 0; I != NumParams; ++I) - Params.push_back(ReadDeclAs<ParmVarDecl>()); - - MD->setSelLocsKind((SelectorLocationsKind)Record.readInt()); - unsigned NumStoredSelLocs = Record.readInt(); - SmallVector<SourceLocation, 16> SelLocs; - SelLocs.reserve(NumStoredSelLocs); - for (unsigned i = 0; i != NumStoredSelLocs; ++i) - SelLocs.push_back(ReadSourceLocation()); - - MD->setParamsAndSelLocs(Reader.getContext(), Params, SelLocs); -} - -void ASTDeclReader::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) { - VisitTypedefNameDecl(D); - - D->Variance = Record.readInt(); - D->Index = Record.readInt(); - D->VarianceLoc = ReadSourceLocation(); - D->ColonLoc = ReadSourceLocation(); -} - -void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) { - VisitNamedDecl(CD); - CD->setAtStartLoc(ReadSourceLocation()); - CD->setAtEndRange(ReadSourceRange()); -} - -ObjCTypeParamList *ASTDeclReader::ReadObjCTypeParamList() { - unsigned numParams = Record.readInt(); - if (numParams == 0) - return nullptr; - - SmallVector<ObjCTypeParamDecl *, 4> typeParams; - typeParams.reserve(numParams); - for (unsigned i = 0; i != numParams; ++i) { - auto *typeParam = ReadDeclAs<ObjCTypeParamDecl>(); - if (!typeParam) - return nullptr; - - typeParams.push_back(typeParam); - } - - SourceLocation lAngleLoc = ReadSourceLocation(); - SourceLocation rAngleLoc = ReadSourceLocation(); - - return ObjCTypeParamList::create(Reader.getContext(), lAngleLoc, - typeParams, rAngleLoc); -} - -void ASTDeclReader::ReadObjCDefinitionData( - struct ObjCInterfaceDecl::DefinitionData &Data) { - // Read the superclass. - Data.SuperClassTInfo = GetTypeSourceInfo(); - - Data.EndLoc = ReadSourceLocation(); - Data.HasDesignatedInitializers = Record.readInt(); - - // Read the directly referenced protocols and their SourceLocations. - unsigned NumProtocols = Record.readInt(); - SmallVector<ObjCProtocolDecl *, 16> Protocols; - Protocols.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>()); - SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - ProtoLocs.push_back(ReadSourceLocation()); - Data.ReferencedProtocols.set(Protocols.data(), NumProtocols, ProtoLocs.data(), - Reader.getContext()); - - // Read the transitive closure of protocols referenced by this class. - NumProtocols = Record.readInt(); - Protocols.clear(); - Protocols.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>()); - Data.AllReferencedProtocols.set(Protocols.data(), NumProtocols, - Reader.getContext()); -} - -void ASTDeclReader::MergeDefinitionData(ObjCInterfaceDecl *D, - struct ObjCInterfaceDecl::DefinitionData &&NewDD) { - // FIXME: odr checking? -} - -void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { - RedeclarableResult Redecl = VisitRedeclarable(ID); - VisitObjCContainerDecl(ID); - DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); - mergeRedeclarable(ID, Redecl); - - ID->TypeParamList = ReadObjCTypeParamList(); - if (Record.readInt()) { - // Read the definition. - ID->allocateDefinitionData(); - - ReadObjCDefinitionData(ID->data()); - ObjCInterfaceDecl *Canon = ID->getCanonicalDecl(); - if (Canon->Data.getPointer()) { - // If we already have a definition, keep the definition invariant and - // merge the data. - MergeDefinitionData(Canon, std::move(ID->data())); - ID->Data = Canon->Data; - } else { - // Set the definition data of the canonical declaration, so other - // redeclarations will see it. - ID->getCanonicalDecl()->Data = ID->Data; - - // We will rebuild this list lazily. - ID->setIvarList(nullptr); - } - - // Note that we have deserialized a definition. - Reader.PendingDefinitions.insert(ID); - - // Note that we've loaded this Objective-C class. - Reader.ObjCClassesLoaded.push_back(ID); - } else { - ID->Data = ID->getCanonicalDecl()->Data; - } -} - -void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { - VisitFieldDecl(IVD); - IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record.readInt()); - // This field will be built lazily. - IVD->setNextIvar(nullptr); - bool synth = Record.readInt(); - IVD->setSynthesize(synth); -} - -void ASTDeclReader::ReadObjCDefinitionData( - struct ObjCProtocolDecl::DefinitionData &Data) { - unsigned NumProtoRefs = Record.readInt(); - SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; - ProtoRefs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>()); - SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoLocs.push_back(ReadSourceLocation()); - Data.ReferencedProtocols.set(ProtoRefs.data(), NumProtoRefs, - ProtoLocs.data(), Reader.getContext()); -} - -void ASTDeclReader::MergeDefinitionData(ObjCProtocolDecl *D, - struct ObjCProtocolDecl::DefinitionData &&NewDD) { - // FIXME: odr checking? -} - -void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { - RedeclarableResult Redecl = VisitRedeclarable(PD); - VisitObjCContainerDecl(PD); - mergeRedeclarable(PD, Redecl); - - if (Record.readInt()) { - // Read the definition. - PD->allocateDefinitionData(); - - ReadObjCDefinitionData(PD->data()); - - ObjCProtocolDecl *Canon = PD->getCanonicalDecl(); - if (Canon->Data.getPointer()) { - // If we already have a definition, keep the definition invariant and - // merge the data. - MergeDefinitionData(Canon, std::move(PD->data())); - PD->Data = Canon->Data; - } else { - // Set the definition data of the canonical declaration, so other - // redeclarations will see it. - PD->getCanonicalDecl()->Data = PD->Data; - } - // Note that we have deserialized a definition. - Reader.PendingDefinitions.insert(PD); - } else { - PD->Data = PD->getCanonicalDecl()->Data; - } -} - -void ASTDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) { - VisitFieldDecl(FD); -} - -void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) { - VisitObjCContainerDecl(CD); - CD->setCategoryNameLoc(ReadSourceLocation()); - CD->setIvarLBraceLoc(ReadSourceLocation()); - CD->setIvarRBraceLoc(ReadSourceLocation()); - - // 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); - - CD->ClassInterface = ReadDeclAs<ObjCInterfaceDecl>(); - CD->TypeParamList = ReadObjCTypeParamList(); - unsigned NumProtoRefs = Record.readInt(); - SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; - ProtoRefs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>()); - SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoLocs.push_back(ReadSourceLocation()); - CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), - Reader.getContext()); - - // Protocols in the class extension belong to the class. - if (NumProtoRefs > 0 && CD->ClassInterface && CD->IsClassExtension()) - CD->ClassInterface->mergeClassExtensionProtocolList( - (ObjCProtocolDecl *const *)ProtoRefs.data(), NumProtoRefs, - Reader.getContext()); -} - -void ASTDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) { - VisitNamedDecl(CAD); - CAD->setClassInterface(ReadDeclAs<ObjCInterfaceDecl>()); -} - -void ASTDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { - VisitNamedDecl(D); - D->setAtLoc(ReadSourceLocation()); - D->setLParenLoc(ReadSourceLocation()); - QualType T = Record.readType(); - TypeSourceInfo *TSI = GetTypeSourceInfo(); - D->setType(T, TSI); - D->setPropertyAttributes( - (ObjCPropertyDecl::PropertyAttributeKind)Record.readInt()); - D->setPropertyAttributesAsWritten( - (ObjCPropertyDecl::PropertyAttributeKind)Record.readInt()); - D->setPropertyImplementation( - (ObjCPropertyDecl::PropertyControl)Record.readInt()); - DeclarationName GetterName = Record.readDeclarationName(); - SourceLocation GetterLoc = ReadSourceLocation(); - D->setGetterName(GetterName.getObjCSelector(), GetterLoc); - DeclarationName SetterName = Record.readDeclarationName(); - SourceLocation SetterLoc = ReadSourceLocation(); - D->setSetterName(SetterName.getObjCSelector(), SetterLoc); - D->setGetterMethodDecl(ReadDeclAs<ObjCMethodDecl>()); - D->setSetterMethodDecl(ReadDeclAs<ObjCMethodDecl>()); - D->setPropertyIvarDecl(ReadDeclAs<ObjCIvarDecl>()); -} - -void ASTDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) { - VisitObjCContainerDecl(D); - D->setClassInterface(ReadDeclAs<ObjCInterfaceDecl>()); -} - -void ASTDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { - VisitObjCImplDecl(D); - D->CategoryNameLoc = ReadSourceLocation(); -} - -void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { - VisitObjCImplDecl(D); - D->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>()); - D->SuperLoc = ReadSourceLocation(); - D->setIvarLBraceLoc(ReadSourceLocation()); - D->setIvarRBraceLoc(ReadSourceLocation()); - D->setHasNonZeroConstructors(Record.readInt()); - D->setHasDestructors(Record.readInt()); - D->NumIvarInitializers = Record.readInt(); - if (D->NumIvarInitializers) - D->IvarInitializers = ReadGlobalOffset(); -} - -void ASTDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { - VisitDecl(D); - D->setAtLoc(ReadSourceLocation()); - D->setPropertyDecl(ReadDeclAs<ObjCPropertyDecl>()); - D->PropertyIvarDecl = ReadDeclAs<ObjCIvarDecl>(); - D->IvarLoc = ReadSourceLocation(); - D->setGetterCXXConstructor(Record.readExpr()); - D->setSetterCXXAssignment(Record.readExpr()); -} - -void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) { - VisitDeclaratorDecl(FD); - FD->Mutable = Record.readInt(); - - if (auto ISK = static_cast<FieldDecl::InitStorageKind>(Record.readInt())) { - FD->InitStorage.setInt(ISK); - FD->InitStorage.setPointer(ISK == FieldDecl::ISK_CapturedVLAType - ? Record.readType().getAsOpaquePtr() - : Record.readExpr()); - } - - if (auto *BW = Record.readExpr()) - FD->setBitWidth(BW); - - if (!FD->getDeclName()) { - if (auto *Tmpl = ReadDeclAs<FieldDecl>()) - Reader.getContext().setInstantiatedFromUnnamedFieldDecl(FD, Tmpl); - } - mergeMergeable(FD); -} - -void ASTDeclReader::VisitMSPropertyDecl(MSPropertyDecl *PD) { - VisitDeclaratorDecl(PD); - PD->GetterId = Record.getIdentifierInfo(); - PD->SetterId = Record.getIdentifierInfo(); -} - -void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) { - VisitValueDecl(FD); - - FD->ChainingSize = Record.readInt(); - assert(FD->ChainingSize >= 2 && "Anonymous chaining must be >= 2"); - FD->Chaining = new (Reader.getContext())NamedDecl*[FD->ChainingSize]; - - for (unsigned I = 0; I != FD->ChainingSize; ++I) - FD->Chaining[I] = ReadDeclAs<NamedDecl>(); - - mergeMergeable(FD); -} - -ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { - RedeclarableResult Redecl = VisitRedeclarable(VD); - VisitDeclaratorDecl(VD); - - VD->VarDeclBits.SClass = (StorageClass)Record.readInt(); - VD->VarDeclBits.TSCSpec = Record.readInt(); - VD->VarDeclBits.InitStyle = Record.readInt(); - VD->VarDeclBits.ARCPseudoStrong = Record.readInt(); - if (!isa<ParmVarDecl>(VD)) { - VD->NonParmVarDeclBits.IsThisDeclarationADemotedDefinition = - Record.readInt(); - VD->NonParmVarDeclBits.ExceptionVar = Record.readInt(); - VD->NonParmVarDeclBits.NRVOVariable = Record.readInt(); - VD->NonParmVarDeclBits.CXXForRangeDecl = Record.readInt(); - VD->NonParmVarDeclBits.ObjCForDecl = Record.readInt(); - VD->NonParmVarDeclBits.IsInline = Record.readInt(); - VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt(); - VD->NonParmVarDeclBits.IsConstexpr = Record.readInt(); - VD->NonParmVarDeclBits.IsInitCapture = Record.readInt(); - VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record.readInt(); - VD->NonParmVarDeclBits.ImplicitParamKind = Record.readInt(); - VD->NonParmVarDeclBits.EscapingByref = Record.readInt(); - } - auto VarLinkage = Linkage(Record.readInt()); - VD->setCachedLinkage(VarLinkage); - - // Reconstruct the one piece of the IdentifierNamespace that we need. - if (VD->getStorageClass() == SC_Extern && VarLinkage != NoLinkage && - VD->getLexicalDeclContext()->isFunctionOrMethod()) - VD->setLocalExternDecl(); - - if (uint64_t Val = Record.readInt()) { - VD->setInit(Record.readExpr()); - if (Val > 1) { // IsInitKnownICE = 1, IsInitNotICE = 2, IsInitICE = 3 - EvaluatedStmt *Eval = VD->ensureEvaluatedStmt(); - Eval->CheckedICE = true; - Eval->IsICE = Val == 3; - } - } - - if (VD->hasAttr<BlocksAttr>() && VD->getType()->getAsCXXRecordDecl()) { - Expr *CopyExpr = Record.readExpr(); - if (CopyExpr) - Reader.getContext().setBlockVarCopyInit(VD, CopyExpr, Record.readInt()); - } - - if (VD->getStorageDuration() == SD_Static && Record.readInt()) - Reader.DefinitionSource[VD] = Loc.F->Kind == ModuleKind::MK_MainFile; - - enum VarKind { - VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization - }; - switch ((VarKind)Record.readInt()) { - case VarNotTemplate: - // Only true variables (not parameters or implicit parameters) can be - // merged; the other kinds are not really redeclarable at all. - if (!isa<ParmVarDecl>(VD) && !isa<ImplicitParamDecl>(VD) && - !isa<VarTemplateSpecializationDecl>(VD)) - mergeRedeclarable(VD, Redecl); - break; - case VarTemplate: - // Merged when we merge the template. - VD->setDescribedVarTemplate(ReadDeclAs<VarTemplateDecl>()); - break; - case StaticDataMemberSpecialization: { // HasMemberSpecializationInfo. - auto *Tmpl = ReadDeclAs<VarDecl>(); - auto TSK = (TemplateSpecializationKind)Record.readInt(); - SourceLocation POI = ReadSourceLocation(); - Reader.getContext().setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI); - mergeRedeclarable(VD, Redecl); - break; - } - } - - return Redecl; -} - -void ASTDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) { - VisitVarDecl(PD); -} - -void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { - VisitVarDecl(PD); - unsigned isObjCMethodParam = Record.readInt(); - unsigned scopeDepth = Record.readInt(); - unsigned scopeIndex = Record.readInt(); - unsigned declQualifier = Record.readInt(); - if (isObjCMethodParam) { - assert(scopeDepth == 0); - PD->setObjCMethodScopeInfo(scopeIndex); - PD->ParmVarDeclBits.ScopeDepthOrObjCQuals = declQualifier; - } else { - PD->setScopeInfo(scopeDepth, scopeIndex); - } - PD->ParmVarDeclBits.IsKNRPromoted = Record.readInt(); - PD->ParmVarDeclBits.HasInheritedDefaultArg = Record.readInt(); - if (Record.readInt()) // hasUninstantiatedDefaultArg. - PD->setUninstantiatedDefaultArg(Record.readExpr()); - - // FIXME: If this is a redeclaration of a function from another module, handle - // inheritance of default arguments. -} - -void ASTDeclReader::VisitDecompositionDecl(DecompositionDecl *DD) { - VisitVarDecl(DD); - auto **BDs = DD->getTrailingObjects<BindingDecl *>(); - for (unsigned I = 0; I != DD->NumBindings; ++I) - BDs[I] = ReadDeclAs<BindingDecl>(); -} - -void ASTDeclReader::VisitBindingDecl(BindingDecl *BD) { - VisitValueDecl(BD); - BD->Binding = Record.readExpr(); -} - -void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) { - VisitDecl(AD); - AD->setAsmString(cast<StringLiteral>(Record.readExpr())); - AD->setRParenLoc(ReadSourceLocation()); -} - -void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) { - VisitDecl(BD); - BD->setBody(cast_or_null<CompoundStmt>(Record.readStmt())); - BD->setSignatureAsWritten(GetTypeSourceInfo()); - unsigned NumParams = Record.readInt(); - SmallVector<ParmVarDecl *, 16> Params; - Params.reserve(NumParams); - for (unsigned I = 0; I != NumParams; ++I) - Params.push_back(ReadDeclAs<ParmVarDecl>()); - BD->setParams(Params); - - BD->setIsVariadic(Record.readInt()); - BD->setBlockMissingReturnType(Record.readInt()); - BD->setIsConversionFromLambda(Record.readInt()); - BD->setDoesNotEscape(Record.readInt()); - - bool capturesCXXThis = Record.readInt(); - unsigned numCaptures = Record.readInt(); - SmallVector<BlockDecl::Capture, 16> captures; - captures.reserve(numCaptures); - for (unsigned i = 0; i != numCaptures; ++i) { - auto *decl = ReadDeclAs<VarDecl>(); - unsigned flags = Record.readInt(); - bool byRef = (flags & 1); - bool nested = (flags & 2); - Expr *copyExpr = ((flags & 4) ? Record.readExpr() : nullptr); - - captures.push_back(BlockDecl::Capture(decl, byRef, nested, copyExpr)); - } - BD->setCaptures(Reader.getContext(), captures, capturesCXXThis); -} - -void ASTDeclReader::VisitCapturedDecl(CapturedDecl *CD) { - VisitDecl(CD); - unsigned ContextParamPos = Record.readInt(); - CD->setNothrow(Record.readInt() != 0); - // Body is set by VisitCapturedStmt. - for (unsigned I = 0; I < CD->NumParams; ++I) { - if (I != ContextParamPos) - CD->setParam(I, ReadDeclAs<ImplicitParamDecl>()); - else - CD->setContextParam(I, ReadDeclAs<ImplicitParamDecl>()); - } -} - -void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) { - VisitDecl(D); - D->setLanguage((LinkageSpecDecl::LanguageIDs)Record.readInt()); - D->setExternLoc(ReadSourceLocation()); - D->setRBraceLoc(ReadSourceLocation()); -} - -void ASTDeclReader::VisitExportDecl(ExportDecl *D) { - VisitDecl(D); - D->RBraceLoc = ReadSourceLocation(); -} - -void ASTDeclReader::VisitLabelDecl(LabelDecl *D) { - VisitNamedDecl(D); - D->setLocStart(ReadSourceLocation()); -} - -void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { - RedeclarableResult Redecl = VisitRedeclarable(D); - VisitNamedDecl(D); - D->setInline(Record.readInt()); - D->LocStart = ReadSourceLocation(); - D->RBraceLoc = ReadSourceLocation(); - - // 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; - if (Redecl.getFirstID() == ThisDeclID) { - AnonNamespace = ReadDeclID(); - } else { - // Link this namespace back to the first declaration, which has already - // been deserialized. - D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDecl()); - } - - mergeRedeclarable(D, Redecl); - - 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. - auto *Anon = cast<NamespaceDecl>(Reader.GetDecl(AnonNamespace)); - if (!Record.isModule()) - D->setAnonymousNamespace(Anon); - } -} - -void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { - RedeclarableResult Redecl = VisitRedeclarable(D); - VisitNamedDecl(D); - D->NamespaceLoc = ReadSourceLocation(); - D->IdentLoc = ReadSourceLocation(); - D->QualifierLoc = Record.readNestedNameSpecifierLoc(); - D->Namespace = ReadDeclAs<NamedDecl>(); - mergeRedeclarable(D, Redecl); -} - -void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { - VisitNamedDecl(D); - D->setUsingLoc(ReadSourceLocation()); - D->QualifierLoc = Record.readNestedNameSpecifierLoc(); - ReadDeclarationNameLoc(D->DNLoc, D->getDeclName()); - D->FirstUsingShadow.setPointer(ReadDeclAs<UsingShadowDecl>()); - D->setTypename(Record.readInt()); - if (auto *Pattern = ReadDeclAs<NamedDecl>()) - Reader.getContext().setInstantiatedFromUsingDecl(D, Pattern); - mergeMergeable(D); -} - -void ASTDeclReader::VisitUsingPackDecl(UsingPackDecl *D) { - VisitNamedDecl(D); - D->InstantiatedFrom = ReadDeclAs<NamedDecl>(); - auto **Expansions = D->getTrailingObjects<NamedDecl *>(); - for (unsigned I = 0; I != D->NumExpansions; ++I) - Expansions[I] = ReadDeclAs<NamedDecl>(); - mergeMergeable(D); -} - -void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) { - RedeclarableResult Redecl = VisitRedeclarable(D); - VisitNamedDecl(D); - D->Underlying = ReadDeclAs<NamedDecl>(); - D->IdentifierNamespace = Record.readInt(); - D->UsingOrNextShadow = ReadDeclAs<NamedDecl>(); - auto *Pattern = ReadDeclAs<UsingShadowDecl>(); - if (Pattern) - Reader.getContext().setInstantiatedFromUsingShadowDecl(D, Pattern); - mergeRedeclarable(D, Redecl); -} - -void ASTDeclReader::VisitConstructorUsingShadowDecl( - ConstructorUsingShadowDecl *D) { - VisitUsingShadowDecl(D); - D->NominatedBaseClassShadowDecl = ReadDeclAs<ConstructorUsingShadowDecl>(); - D->ConstructedBaseClassShadowDecl = ReadDeclAs<ConstructorUsingShadowDecl>(); - D->IsVirtual = Record.readInt(); -} - -void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { - VisitNamedDecl(D); - D->UsingLoc = ReadSourceLocation(); - D->NamespaceLoc = ReadSourceLocation(); - D->QualifierLoc = Record.readNestedNameSpecifierLoc(); - D->NominatedNamespace = ReadDeclAs<NamedDecl>(); - D->CommonAncestor = ReadDeclAs<DeclContext>(); -} - -void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { - VisitValueDecl(D); - D->setUsingLoc(ReadSourceLocation()); - D->QualifierLoc = Record.readNestedNameSpecifierLoc(); - ReadDeclarationNameLoc(D->DNLoc, D->getDeclName()); - D->EllipsisLoc = ReadSourceLocation(); - mergeMergeable(D); -} - -void ASTDeclReader::VisitUnresolvedUsingTypenameDecl( - UnresolvedUsingTypenameDecl *D) { - VisitTypeDecl(D); - D->TypenameLocation = ReadSourceLocation(); - D->QualifierLoc = Record.readNestedNameSpecifierLoc(); - D->EllipsisLoc = ReadSourceLocation(); - mergeMergeable(D); -} - -void ASTDeclReader::ReadCXXDefinitionData( - struct CXXRecordDecl::DefinitionData &Data, const CXXRecordDecl *D) { - // Note: the caller has deserialized the IsLambda bit already. - Data.UserDeclaredConstructor = Record.readInt(); - Data.UserDeclaredSpecialMembers = Record.readInt(); - Data.Aggregate = Record.readInt(); - Data.PlainOldData = Record.readInt(); - Data.Empty = Record.readInt(); - Data.Polymorphic = Record.readInt(); - Data.Abstract = Record.readInt(); - Data.IsStandardLayout = Record.readInt(); - Data.IsCXX11StandardLayout = Record.readInt(); - Data.HasBasesWithFields = Record.readInt(); - Data.HasBasesWithNonStaticDataMembers = Record.readInt(); - Data.HasPrivateFields = Record.readInt(); - Data.HasProtectedFields = Record.readInt(); - Data.HasPublicFields = Record.readInt(); - Data.HasMutableFields = Record.readInt(); - Data.HasVariantMembers = Record.readInt(); - Data.HasOnlyCMembers = Record.readInt(); - Data.HasInClassInitializer = Record.readInt(); - Data.HasUninitializedReferenceMember = Record.readInt(); - Data.HasUninitializedFields = Record.readInt(); - Data.HasInheritedConstructor = Record.readInt(); - Data.HasInheritedAssignment = Record.readInt(); - Data.NeedOverloadResolutionForCopyConstructor = Record.readInt(); - Data.NeedOverloadResolutionForMoveConstructor = Record.readInt(); - Data.NeedOverloadResolutionForMoveAssignment = Record.readInt(); - Data.NeedOverloadResolutionForDestructor = Record.readInt(); - Data.DefaultedCopyConstructorIsDeleted = Record.readInt(); - Data.DefaultedMoveConstructorIsDeleted = Record.readInt(); - Data.DefaultedMoveAssignmentIsDeleted = Record.readInt(); - Data.DefaultedDestructorIsDeleted = Record.readInt(); - Data.HasTrivialSpecialMembers = Record.readInt(); - Data.HasTrivialSpecialMembersForCall = Record.readInt(); - Data.DeclaredNonTrivialSpecialMembers = Record.readInt(); - Data.DeclaredNonTrivialSpecialMembersForCall = Record.readInt(); - Data.HasIrrelevantDestructor = Record.readInt(); - Data.HasConstexprNonCopyMoveConstructor = Record.readInt(); - Data.HasDefaultedDefaultConstructor = Record.readInt(); - Data.DefaultedDefaultConstructorIsConstexpr = Record.readInt(); - Data.HasConstexprDefaultConstructor = Record.readInt(); - Data.HasNonLiteralTypeFieldsOrBases = Record.readInt(); - Data.ComputedVisibleConversions = Record.readInt(); - Data.UserProvidedDefaultConstructor = Record.readInt(); - Data.DeclaredSpecialMembers = Record.readInt(); - Data.ImplicitCopyConstructorCanHaveConstParamForVBase = Record.readInt(); - Data.ImplicitCopyConstructorCanHaveConstParamForNonVBase = Record.readInt(); - Data.ImplicitCopyAssignmentHasConstParam = Record.readInt(); - Data.HasDeclaredCopyConstructorWithConstParam = Record.readInt(); - Data.HasDeclaredCopyAssignmentWithConstParam = Record.readInt(); - Data.ODRHash = Record.readInt(); - Data.HasODRHash = true; - - if (Record.readInt()) - Reader.DefinitionSource[D] = Loc.F->Kind == ModuleKind::MK_MainFile; - - Data.NumBases = Record.readInt(); - if (Data.NumBases) - Data.Bases = ReadGlobalOffset(); - Data.NumVBases = Record.readInt(); - if (Data.NumVBases) - Data.VBases = ReadGlobalOffset(); - - Record.readUnresolvedSet(Data.Conversions); - Record.readUnresolvedSet(Data.VisibleConversions); - assert(Data.Definition && "Data.Definition should be already set!"); - Data.FirstFriend = ReadDeclID(); - - if (Data.IsLambda) { - using Capture = LambdaCapture; - - auto &Lambda = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data); - Lambda.Dependent = Record.readInt(); - Lambda.IsGenericLambda = Record.readInt(); - Lambda.CaptureDefault = Record.readInt(); - Lambda.NumCaptures = Record.readInt(); - Lambda.NumExplicitCaptures = Record.readInt(); - Lambda.ManglingNumber = Record.readInt(); - Lambda.ContextDecl = ReadDeclID(); - Lambda.Captures = (Capture *)Reader.getContext().Allocate( - sizeof(Capture) * Lambda.NumCaptures); - Capture *ToCapture = Lambda.Captures; - Lambda.MethodTyInfo = GetTypeSourceInfo(); - for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { - SourceLocation Loc = ReadSourceLocation(); - bool IsImplicit = Record.readInt(); - auto Kind = static_cast<LambdaCaptureKind>(Record.readInt()); - switch (Kind) { - case LCK_StarThis: - case LCK_This: - case LCK_VLAType: - *ToCapture++ = Capture(Loc, IsImplicit, Kind, nullptr,SourceLocation()); - break; - case LCK_ByCopy: - case LCK_ByRef: - auto *Var = ReadDeclAs<VarDecl>(); - SourceLocation EllipsisLoc = ReadSourceLocation(); - *ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc); - break; - } - } - } -} - -void ASTDeclReader::MergeDefinitionData( - CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &&MergeDD) { - assert(D->DefinitionData && - "merging class definition into non-definition"); - auto &DD = *D->DefinitionData; - - if (DD.Definition != MergeDD.Definition) { - // Track that we merged the definitions. - Reader.MergedDeclContexts.insert(std::make_pair(MergeDD.Definition, - DD.Definition)); - Reader.PendingDefinitions.erase(MergeDD.Definition); - MergeDD.Definition->setCompleteDefinition(false); - Reader.mergeDefinitionVisibility(DD.Definition, MergeDD.Definition); - assert(Reader.Lookups.find(MergeDD.Definition) == Reader.Lookups.end() && - "already loaded pending lookups for merged definition"); - } - - auto PFDI = Reader.PendingFakeDefinitionData.find(&DD); - if (PFDI != Reader.PendingFakeDefinitionData.end() && - PFDI->second == ASTReader::PendingFakeDefinitionKind::Fake) { - // 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?"); - PFDI->second = ASTReader::PendingFakeDefinitionKind::FakeLoaded; - - // 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; - } - - // 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(IsCXX11StandardLayout) - MATCH_FIELD(HasBasesWithFields) - MATCH_FIELD(HasBasesWithNonStaticDataMembers) - 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(HasUninitializedFields) - MATCH_FIELD(HasInheritedConstructor) - MATCH_FIELD(HasInheritedAssignment) - MATCH_FIELD(NeedOverloadResolutionForCopyConstructor) - MATCH_FIELD(NeedOverloadResolutionForMoveConstructor) - MATCH_FIELD(NeedOverloadResolutionForMoveAssignment) - MATCH_FIELD(NeedOverloadResolutionForDestructor) - MATCH_FIELD(DefaultedCopyConstructorIsDeleted) - MATCH_FIELD(DefaultedMoveConstructorIsDeleted) - MATCH_FIELD(DefaultedMoveAssignmentIsDeleted) - MATCH_FIELD(DefaultedDestructorIsDeleted) - OR_FIELD(HasTrivialSpecialMembers) - OR_FIELD(HasTrivialSpecialMembersForCall) - OR_FIELD(DeclaredNonTrivialSpecialMembers) - OR_FIELD(DeclaredNonTrivialSpecialMembersForCall) - MATCH_FIELD(HasIrrelevantDestructor) - OR_FIELD(HasConstexprNonCopyMoveConstructor) - OR_FIELD(HasDefaultedDefaultConstructor) - MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr) - OR_FIELD(HasConstexprDefaultConstructor) - MATCH_FIELD(HasNonLiteralTypeFieldsOrBases) - // ComputedVisibleConversions is handled below. - MATCH_FIELD(UserProvidedDefaultConstructor) - OR_FIELD(DeclaredSpecialMembers) - MATCH_FIELD(ImplicitCopyConstructorCanHaveConstParamForVBase) - MATCH_FIELD(ImplicitCopyConstructorCanHaveConstParamForNonVBase) - 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 (D->getODRHash() != MergeDD.ODRHash) { - DetectedOdrViolation = true; - } - - if (DetectedOdrViolation) - Reader.PendingOdrMergeFailures[DD.Definition].push_back( - {MergeDD.Definition, &MergeDD}); -} - -void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) { - 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.readInt(); - if (IsLambda) - DD = new (C) CXXRecordDecl::LambdaDefinitionData(D, nullptr, false, false, - LCD_None); - else - DD = new (C) struct CXXRecordDecl::DefinitionData(D); - - CXXRecordDecl *Canon = D->getCanonicalDecl(); - // Set decl definition data before reading it, so that during deserialization - // when we read CXXRecordDecl, it already has definition data and we don't - // set fake one. - if (!Canon->DefinitionData) - Canon->DefinitionData = DD; - D->DefinitionData = Canon->DefinitionData; - ReadCXXDefinitionData(*DD, D); - - // We might already have a different 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. - if (Canon->DefinitionData != DD) { - MergeDefinitionData(Canon, std::move(*DD)); - return; - } - - // Mark this declaration as being a definition. - D->setCompleteDefinition(true); - - // 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) - Reader.PendingDefinitions.insert(D); -} - -ASTDeclReader::RedeclarableResult -ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { - RedeclarableResult Redecl = VisitRecordDeclImpl(D); - - ASTContext &C = Reader.getContext(); - - enum CXXRecKind { - CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization - }; - switch ((CXXRecKind)Record.readInt()) { - case CXXRecNotTemplate: - // Merged when we merge the folding set entry in the primary template. - if (!isa<ClassTemplateSpecializationDecl>(D)) - mergeRedeclarable(D, Redecl); - break; - case CXXRecTemplate: { - // Merged when we merge the template. - auto *Template = ReadDeclAs<ClassTemplateDecl>(); - 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. - DeferredTypeID = 0; - } - break; - } - case CXXRecMemberSpecialization: { - auto *RD = ReadDeclAs<CXXRecordDecl>(); - auto TSK = (TemplateSpecializationKind)Record.readInt(); - SourceLocation POI = ReadSourceLocation(); - MemberSpecializationInfo *MSI = new (C) MemberSpecializationInfo(RD, TSK); - MSI->setPointOfInstantiation(POI); - D->TemplateOrInstantiation = MSI; - mergeRedeclarable(D, Redecl); - break; - } - } - - bool WasDefinition = Record.readInt(); - if (WasDefinition) - ReadCXXRecordDefinition(D, /*Update*/false); - else - // Propagate DefinitionData pointer from the canonical declaration. - D->DefinitionData = D->getCanonicalDecl()->DefinitionData; - - // Lazily load the key function to avoid deserializing every method so we can - // compute it. - if (WasDefinition) { - DeclID KeyFn = ReadDeclID(); - if (KeyFn && D->isCompleteDefinition()) - // 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. - C.KeyFunctions[D] = KeyFn; - } - - return Redecl; -} - -void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { - VisitFunctionDecl(D); - D->setIsCopyDeductionCandidate(Record.readInt()); -} - -void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { - VisitFunctionDecl(D); - - unsigned NumOverridenMethods = Record.readInt(); - if (D->isCanonicalDecl()) { - while (NumOverridenMethods--) { - // Avoid invariant checking of CXXMethodDecl::addOverriddenMethod, - // MD may be initializing. - if (auto *MD = ReadDeclAs<CXXMethodDecl>()) - 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. - Record.skipInts(NumOverridenMethods); - } -} - -void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) { - // We need the inherited constructor information to merge the declaration, - // so we have to read it before we call VisitCXXMethodDecl. - if (D->isInheritingConstructor()) { - auto *Shadow = ReadDeclAs<ConstructorUsingShadowDecl>(); - auto *Ctor = ReadDeclAs<CXXConstructorDecl>(); - *D->getTrailingObjects<InheritedConstructor>() = - InheritedConstructor(Shadow, Ctor); - } - - VisitCXXMethodDecl(D); -} - -void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { - VisitCXXMethodDecl(D); - - if (auto *OperatorDelete = ReadDeclAs<FunctionDecl>()) { - CXXDestructorDecl *Canon = D->getCanonicalDecl(); - auto *ThisArg = Record.readExpr(); - // FIXME: Check consistency if we have an old and new operator delete. - if (!Canon->OperatorDelete) { - Canon->OperatorDelete = OperatorDelete; - Canon->OperatorDeleteThisArg = ThisArg; - } - } -} - -void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) { - VisitCXXMethodDecl(D); -} - -void ASTDeclReader::VisitImportDecl(ImportDecl *D) { - VisitDecl(D); - D->ImportedAndComplete.setPointer(readModule()); - D->ImportedAndComplete.setInt(Record.readInt()); - auto *StoredLocs = D->getTrailingObjects<SourceLocation>(); - for (unsigned I = 0, N = Record.back(); I != N; ++I) - StoredLocs[I] = ReadSourceLocation(); - Record.skipInts(1); // The number of stored source locations. -} - -void ASTDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) { - VisitDecl(D); - D->setColonLoc(ReadSourceLocation()); -} - -void ASTDeclReader::VisitFriendDecl(FriendDecl *D) { - VisitDecl(D); - if (Record.readInt()) // hasFriendDecl - D->Friend = ReadDeclAs<NamedDecl>(); - else - D->Friend = GetTypeSourceInfo(); - for (unsigned i = 0; i != D->NumTPLists; ++i) - D->getTrailingObjects<TemplateParameterList *>()[i] = - Record.readTemplateParameterList(); - D->NextFriend = ReadDeclID(); - D->UnsupportedFriend = (Record.readInt() != 0); - D->FriendLoc = ReadSourceLocation(); -} - -void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) { - VisitDecl(D); - unsigned NumParams = Record.readInt(); - D->NumParams = NumParams; - D->Params = new TemplateParameterList*[NumParams]; - for (unsigned i = 0; i != NumParams; ++i) - D->Params[i] = Record.readTemplateParameterList(); - if (Record.readInt()) // HasFriendDecl - D->Friend = ReadDeclAs<NamedDecl>(); - else - D->Friend = GetTypeSourceInfo(); - D->FriendLoc = ReadSourceLocation(); -} - -DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { - VisitNamedDecl(D); - - DeclID PatternID = ReadDeclID(); - auto *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID)); - TemplateParameterList *TemplateParams = Record.readTemplateParameterList(); - // FIXME handle associated constraints - D->init(TemplatedDecl, TemplateParams); - - return PatternID; -} - -ASTDeclReader::RedeclarableResult -ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { - RedeclarableResult Redecl = VisitRedeclarable(D); - - // 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; - - // If this is the first declaration of the template, fill in the information - // for the 'common' pointer. - if (ThisDeclID == Redecl.getFirstID()) { - if (auto *RTD = ReadDeclAs<RedeclarableTemplateDecl>()) { - assert(RTD->getKind() == D->getKind() && - "InstantiatedFromMemberTemplate kind mismatch"); - D->setInstantiatedFromMemberTemplate(RTD); - if (Record.readInt()) - D->setMemberSpecialization(); - } - } - - DeclID PatternID = VisitTemplateDecl(D); - D->IdentifierNamespace = Record.readInt(); - - mergeRedeclarable(D, Redecl, PatternID); - - // 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; - - return Redecl; -} - -void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { - RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); - - if (ThisDeclID == Redecl.getFirstID()) { - // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of - // the specializations. - SmallVector<serialization::DeclID, 32> SpecIDs; - ReadDeclIDList(SpecIDs); - ASTDeclReader::AddLazySpecializations(D, SpecIDs); - } - - 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.getContext().getInjectedClassNameType( - D->getTemplatedDecl(), D->getInjectedClassNameSpecialization()); - } -} - -void ASTDeclReader::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) { - llvm_unreachable("BuiltinTemplates are not serialized"); -} - -/// TODO: Unify with ClassTemplateDecl version? -/// May require unifying ClassTemplateDecl and -/// VarTemplateDecl beyond TemplateDecl... -void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { - RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); - - if (ThisDeclID == Redecl.getFirstID()) { - // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of - // the specializations. - SmallVector<serialization::DeclID, 32> SpecIDs; - ReadDeclIDList(SpecIDs); - ASTDeclReader::AddLazySpecializations(D, SpecIDs); - } -} - -ASTDeclReader::RedeclarableResult -ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( - ClassTemplateSpecializationDecl *D) { - RedeclarableResult Redecl = VisitCXXRecordDeclImpl(D); - - ASTContext &C = Reader.getContext(); - if (Decl *InstD = ReadDecl()) { - if (auto *CTD = dyn_cast<ClassTemplateDecl>(InstD)) { - D->SpecializedTemplate = CTD; - } else { - SmallVector<TemplateArgument, 8> TemplArgs; - Record.readTemplateArgumentList(TemplArgs); - TemplateArgumentList *ArgList - = TemplateArgumentList::CreateCopy(C, TemplArgs); - auto *PS = - new (C) ClassTemplateSpecializationDecl:: - SpecializedPartialSpecialization(); - PS->PartialSpecialization - = cast<ClassTemplatePartialSpecializationDecl>(InstD); - PS->TemplateArgs = ArgList; - D->SpecializedTemplate = PS; - } - } - - SmallVector<TemplateArgument, 8> TemplArgs; - Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true); - D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs); - D->PointOfInstantiation = ReadSourceLocation(); - D->SpecializationKind = (TemplateSpecializationKind)Record.readInt(); - - bool writtenAsCanonicalDecl = Record.readInt(); - if (writtenAsCanonicalDecl) { - auto *CanonPattern = ReadDeclAs<ClassTemplateDecl>(); - if (D->isCanonicalDecl()) { // It's kept in the folding set. - // Set this as, or find, the canonical declaration for this specialization - ClassTemplateSpecializationDecl *CanonSpec; - if (auto *Partial = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) { - CanonSpec = CanonPattern->getCommonPtr()->PartialSpecializations - .GetOrInsertNode(Partial); - } else { - 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 (auto *DDD = D->DefinitionData) { - if (CanonSpec->DefinitionData) - MergeDefinitionData(CanonSpec, std::move(*DDD)); - else - CanonSpec->DefinitionData = D->DefinitionData; - } - D->DefinitionData = CanonSpec->DefinitionData; - } - } - } - - // Explicit info. - if (TypeSourceInfo *TyInfo = GetTypeSourceInfo()) { - auto *ExplicitInfo = - new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = TyInfo; - ExplicitInfo->ExternLoc = ReadSourceLocation(); - ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(); - D->ExplicitInfo = ExplicitInfo; - } - - return Redecl; -} - -void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( - ClassTemplatePartialSpecializationDecl *D) { - RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D); - - D->TemplateParams = Record.readTemplateParameterList(); - D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); - - // These are read/set from/to the first declaration. - if (ThisDeclID == Redecl.getFirstID()) { - D->InstantiatedFromMember.setPointer( - ReadDeclAs<ClassTemplatePartialSpecializationDecl>()); - D->InstantiatedFromMember.setInt(Record.readInt()); - } -} - -void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl( - ClassScopeFunctionSpecializationDecl *D) { - VisitDecl(D); - D->Specialization = ReadDeclAs<CXXMethodDecl>(); -} - -void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { - RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); - - if (ThisDeclID == Redecl.getFirstID()) { - // This FunctionTemplateDecl owns a CommonPtr; read it. - SmallVector<serialization::DeclID, 32> SpecIDs; - ReadDeclIDList(SpecIDs); - ASTDeclReader::AddLazySpecializations(D, SpecIDs); - } -} - -/// 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. -ASTDeclReader::RedeclarableResult -ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( - VarTemplateSpecializationDecl *D) { - RedeclarableResult Redecl = VisitVarDeclImpl(D); - - ASTContext &C = Reader.getContext(); - if (Decl *InstD = ReadDecl()) { - if (auto *VTD = dyn_cast<VarTemplateDecl>(InstD)) { - D->SpecializedTemplate = VTD; - } else { - SmallVector<TemplateArgument, 8> TemplArgs; - Record.readTemplateArgumentList(TemplArgs); - TemplateArgumentList *ArgList = TemplateArgumentList::CreateCopy( - C, TemplArgs); - auto *PS = - new (C) - VarTemplateSpecializationDecl::SpecializedPartialSpecialization(); - PS->PartialSpecialization = - cast<VarTemplatePartialSpecializationDecl>(InstD); - PS->TemplateArgs = ArgList; - D->SpecializedTemplate = PS; - } - } - - // Explicit info. - if (TypeSourceInfo *TyInfo = GetTypeSourceInfo()) { - auto *ExplicitInfo = - new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = TyInfo; - ExplicitInfo->ExternLoc = ReadSourceLocation(); - ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(); - D->ExplicitInfo = ExplicitInfo; - } - - SmallVector<TemplateArgument, 8> TemplArgs; - Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true); - D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs); - D->PointOfInstantiation = ReadSourceLocation(); - D->SpecializationKind = (TemplateSpecializationKind)Record.readInt(); - D->IsCompleteDefinition = Record.readInt(); - - bool writtenAsCanonicalDecl = Record.readInt(); - if (writtenAsCanonicalDecl) { - auto *CanonPattern = ReadDeclAs<VarTemplateDecl>(); - if (D->isCanonicalDecl()) { // It's kept in the folding set. - // FIXME: If it's already present, merge it. - if (auto *Partial = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) { - CanonPattern->getCommonPtr()->PartialSpecializations - .GetOrInsertNode(Partial); - } else { - CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D); - } - } - } - - return Redecl; -} - -/// 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. -void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl( - VarTemplatePartialSpecializationDecl *D) { - RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D); - - D->TemplateParams = Record.readTemplateParameterList(); - D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); - - // These are read/set from/to the first declaration. - if (ThisDeclID == Redecl.getFirstID()) { - D->InstantiatedFromMember.setPointer( - ReadDeclAs<VarTemplatePartialSpecializationDecl>()); - D->InstantiatedFromMember.setInt(Record.readInt()); - } -} - -void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { - VisitTypeDecl(D); - - D->setDeclaredWithTypename(Record.readInt()); - - if (Record.readInt()) - D->setDefaultArgument(GetTypeSourceInfo()); -} - -void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { - VisitDeclaratorDecl(D); - // TemplateParmPosition. - D->setDepth(Record.readInt()); - D->setPosition(Record.readInt()); - if (D->isExpandedParameterPack()) { - auto TypesAndInfos = - D->getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>(); - for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) { - new (&TypesAndInfos[I].first) QualType(Record.readType()); - TypesAndInfos[I].second = GetTypeSourceInfo(); - } - } else { - // Rest of NonTypeTemplateParmDecl. - D->ParameterPack = Record.readInt(); - if (Record.readInt()) - D->setDefaultArgument(Record.readExpr()); - } -} - -void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { - VisitTemplateDecl(D); - // TemplateParmPosition. - D->setDepth(Record.readInt()); - D->setPosition(Record.readInt()); - if (D->isExpandedParameterPack()) { - auto **Data = D->getTrailingObjects<TemplateParameterList *>(); - for (unsigned I = 0, N = D->getNumExpansionTemplateParameters(); - I != N; ++I) - Data[I] = Record.readTemplateParameterList(); - } else { - // Rest of TemplateTemplateParmDecl. - D->ParameterPack = Record.readInt(); - if (Record.readInt()) - D->setDefaultArgument(Reader.getContext(), - Record.readTemplateArgumentLoc()); - } -} - -void ASTDeclReader::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { - VisitRedeclarableTemplateDecl(D); -} - -void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) { - VisitDecl(D); - D->AssertExprAndFailed.setPointer(Record.readExpr()); - D->AssertExprAndFailed.setInt(Record.readInt()); - D->Message = cast_or_null<StringLiteral>(Record.readExpr()); - D->RParenLoc = ReadSourceLocation(); -} - -void ASTDeclReader::VisitEmptyDecl(EmptyDecl *D) { - VisitDecl(D); -} - -std::pair<uint64_t, uint64_t> -ASTDeclReader::VisitDeclContext(DeclContext *DC) { - uint64_t LexicalOffset = ReadLocalOffset(); - uint64_t VisibleOffset = ReadLocalOffset(); - return std::make_pair(LexicalOffset, VisibleOffset); -} - -template <typename T> -ASTDeclReader::RedeclarableResult -ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { - DeclID FirstDeclID = ReadDeclID(); - Decl *MergeWith = nullptr; - - bool IsKeyDecl = ThisDeclID == FirstDeclID; - bool IsFirstLocalDecl = false; - - uint64_t RedeclOffset = 0; - - // 0 indicates that this declaration was the only declaration of its entity, - // and is used for space optimization. - if (FirstDeclID == 0) { - FirstDeclID = ThisDeclID; - IsKeyDecl = true; - IsFirstLocalDecl = true; - } else if (unsigned N = Record.readInt()) { - // This declaration was the first local declaration, but may have imported - // other declarations. - IsKeyDecl = N == 1; - IsFirstLocalDecl = true; - - // 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 - 1; ++I) - MergeWith = ReadDecl(); - - RedeclOffset = ReadLocalOffset(); - } else { - // This declaration was not the first local declaration. Read the first - // local declaration now, to trigger the import of other redeclarations. - (void)ReadDecl(); - } - - auto *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID)); - if (FirstDecl != D) { - // 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. - D->RedeclLink = Redeclarable<T>::PreviousDeclLink(FirstDecl); - D->First = FirstDecl->getCanonicalDecl(); - } - - auto *DAsT = static_cast<T *>(D); - - // Note that we need to load local redeclarations of this decl and build a - // decl chain for them. This must happen *after* we perform the preloading - // above; this ensures that the redeclaration chain is built in the correct - // order. - if (IsFirstLocalDecl) - Reader.PendingDeclChains.push_back(std::make_pair(DAsT, RedeclOffset)); - - return RedeclarableResult(MergeWith, FirstDeclID, IsKeyDecl); -} - -/// Attempts to merge the given declaration (D) with another declaration -/// of the same entity. -template<typename T> -void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, - RedeclarableResult &Redecl, - DeclID TemplatePatternID) { - // If modules are not available, there is no reason to perform this merge. - if (!Reader.getContext().getLangOpts().Modules) - return; - - // If we're not the canonical declaration, we don't need to merge. - if (!DBase->isFirstDecl()) - return; - - auto *D = static_cast<T *>(DBase); - - 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)) - if (T *Existing = ExistingRes) - mergeRedeclarable(D, Existing, Redecl, TemplatePatternID); -} - -/// "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"); -} - -/// Merge together the pattern declarations from two template -/// declarations. -void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, - RedeclarableTemplateDecl *Existing, - DeclID DsID, bool IsKeyDecl) { - auto *DPattern = D->getTemplatedDecl(); - auto *ExistingPattern = Existing->getTemplatedDecl(); - RedeclarableResult Result(/*MergeWith*/ ExistingPattern, - DPattern->getCanonicalDecl()->getGlobalID(), - IsKeyDecl); - - 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) { - if (ExistingClass->DefinitionData) { - MergeDefinitionData(ExistingClass, std::move(*DDD)); - } else { - ExistingClass->DefinitionData = DClass->DefinitionData; - // We may have skipped this before because we thought that DClass - // was the canonical declaration. - Reader.PendingDefinitions.insert(DClass); - } - } - DClass->DefinitionData = ExistingClass->DefinitionData; - - return mergeRedeclarable(DClass, cast<TagDecl>(ExistingPattern), - Result); - } - 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); - if (auto *DAlias = dyn_cast<TypeAliasDecl>(DPattern)) - return mergeRedeclarable(DAlias, cast<TypedefNameDecl>(ExistingPattern), - Result); - llvm_unreachable("merged an unknown kind of redeclarable template"); -} - -/// Attempts to merge the given declaration (D) with another declaration -/// of the same entity. -template<typename T> -void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing, - RedeclarableResult &Redecl, - DeclID TemplatePatternID) { - auto *D = static_cast<T *>(DBase); - T *ExistingCanon = Existing->getCanonicalDecl(); - T *DCanon = D->getCanonicalDecl(); - if (ExistingCanon != DCanon) { - assert(DCanon->getGlobalID() == Redecl.getFirstID() && - "already merged this declaration"); - - // Have our redeclaration link point back at the canonical declaration - // of the existing declaration, so that this declaration has the - // appropriate canonical declaration. - D->RedeclLink = Redeclarable<T>::PreviousDeclLink(ExistingCanon); - D->First = ExistingCanon; - ExistingCanon->Used |= D->Used; - D->Used = false; - - // When we merge a namespace, update its pointer to the first namespace. - // We cannot have loaded any redeclarations of this declaration yet, so - // there's nothing else that needs to be updated. - if (auto *Namespace = dyn_cast<NamespaceDecl>(D)) - Namespace->AnonOrFirstNamespaceAndInline.setPointer( - 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, Redecl.isKeyDecl()); - - // If this declaration is a key declaration, make a note of that. - if (Redecl.isKeyDecl()) - Reader.KeyDecls[ExistingCanon].push_back(Redecl.getFirstID()); - } -} - -/// ODR-like semantics for C/ObjC allow us to merge tag types and a structural -/// check in Sema guarantees the types can be merged (see C11 6.2.7/1 or C89 -/// 6.1.2.6/1). Although most merging is done in Sema, we need to guarantee -/// that some types are mergeable during deserialization, otherwise name -/// lookup fails. This is the case for EnumConstantDecl. -static bool allowODRLikeMergeInC(NamedDecl *ND) { - if (!ND) - return false; - // TODO: implement merge for other necessary decls. - if (isa<EnumConstantDecl>(ND)) - return true; - return false; -} - -/// 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; - - // ODR-based merging is performed in C++ and in some cases (tag types) in C. - // Note that C identically-named things in different translation units are - // not redeclarations, but may still have compatible types, where ODR-like - // semantics may apply. - if (!Reader.getContext().getLangOpts().CPlusPlus && - !allowODRLikeMergeInC(dyn_cast<NamedDecl>(static_cast<T*>(D)))) - return; - - if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) - if (T *Existing = ExistingRes) - Reader.getContext().setPrimaryMergedDecl(static_cast<T *>(D), - Existing->getCanonicalDecl()); -} - -void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { - VisitDecl(D); - unsigned NumVars = D->varlist_size(); - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); - for (unsigned i = 0; i != NumVars; ++i) { - Vars.push_back(Record.readExpr()); - } - D->setVars(Vars); -} - -void ASTDeclReader::VisitOMPRequiresDecl(OMPRequiresDecl * D) { - VisitDecl(D); - unsigned NumClauses = D->clauselist_size(); - SmallVector<OMPClause *, 8> Clauses; - Clauses.reserve(NumClauses); - OMPClauseReader ClauseReader(Record); - for (unsigned I = 0; I != NumClauses; ++I) - Clauses.push_back(ClauseReader.readClause()); - D->setClauses(Clauses); -} - -void ASTDeclReader::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { - VisitValueDecl(D); - D->setLocation(ReadSourceLocation()); - Expr *In = Record.readExpr(); - Expr *Out = Record.readExpr(); - D->setCombinerData(In, Out); - Expr *Combiner = Record.readExpr(); - D->setCombiner(Combiner); - Expr *Orig = Record.readExpr(); - Expr *Priv = Record.readExpr(); - D->setInitializerData(Orig, Priv); - Expr *Init = Record.readExpr(); - auto IK = static_cast<OMPDeclareReductionDecl::InitKind>(Record.readInt()); - D->setInitializer(Init, IK); - D->PrevDeclInScope = ReadDeclID(); -} - -void ASTDeclReader::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) { - VisitVarDecl(D); -} - -//===----------------------------------------------------------------------===// -// Attribute Reading -//===----------------------------------------------------------------------===// - -namespace { -class AttrReader { - ModuleFile *F; - ASTReader *Reader; - const ASTReader::RecordData &Record; - unsigned &Idx; - -public: - AttrReader(ModuleFile &F, ASTReader &Reader, - const ASTReader::RecordData &Record, unsigned &Idx) - : F(&F), Reader(&Reader), Record(Record), Idx(Idx) {} - - const uint64_t &readInt() { return Record[Idx++]; } - - SourceRange readSourceRange() { - return Reader->ReadSourceRange(*F, Record, Idx); - } - - Expr *readExpr() { return Reader->ReadExpr(*F); } - - std::string readString() { - return Reader->ReadString(Record, Idx); - } - - TypeSourceInfo *getTypeSourceInfo() { - return Reader->GetTypeSourceInfo(*F, Record, Idx); - } - - IdentifierInfo *getIdentifierInfo() { - return Reader->GetIdentifierInfo(*F, Record, Idx); - } - - VersionTuple readVersionTuple() { - return ASTReader::ReadVersionTuple(Record, Idx); - } - - template <typename T> T *GetLocalDeclAs(uint32_t LocalID) { - return cast_or_null<T>(Reader->GetLocalDecl(*F, LocalID)); - } -}; -} - -Attr *ASTReader::ReadAttr(ModuleFile &M, const RecordData &Rec, - unsigned &Idx) { - AttrReader Record(M, *this, Rec, Idx); - auto V = Record.readInt(); - if (!V) - return nullptr; - - Attr *New = nullptr; - // Kind is stored as a 1-based integer because 0 is used to indicate a null - // Attr pointer. - auto Kind = static_cast<attr::Kind>(V - 1); - SourceRange Range = Record.readSourceRange(); - ASTContext &Context = getContext(); - -#include "clang/Serialization/AttrPCHRead.inc" - - assert(New && "Unable to decode attribute?"); - return New; -} - -/// Reads attributes from the current stream position. -void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) { - for (unsigned I = 0, E = Record.readInt(); I != E; ++I) - Attrs.push_back(Record.readAttr()); -} - -//===----------------------------------------------------------------------===// -// ASTReader Implementation -//===----------------------------------------------------------------------===// - -/// Note that we have loaded the declaration with the given -/// Index. -/// -/// 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. -inline void ASTReader::LoadedDecl(unsigned Index, Decl *D) { - assert(!DeclsLoaded[Index] && "Decl loaded twice?"); - DeclsLoaded[Index] = D; -} - -/// 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. -static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) { - // An ObjCMethodDecl is never considered as "interesting" because its - // implementation container always is. - - // An ImportDecl or VarDecl imported from a module map module will get - // emitted when we import the relevant module. - if (isa<ImportDecl>(D) || isa<VarDecl>(D)) { - auto *M = D->getImportedOwningModule(); - if (M && M->Kind == Module::ModuleMapModule && - Ctx.DeclMustBeEmitted(D)) - return false; - } - - if (isa<FileScopeAsmDecl>(D) || - isa<ObjCProtocolDecl>(D) || - isa<ObjCImplDecl>(D) || - isa<ImportDecl>(D) || - isa<PragmaCommentDecl>(D) || - isa<PragmaDetectMismatchDecl>(D)) - return true; - if (isa<OMPThreadPrivateDecl>(D) || isa<OMPDeclareReductionDecl>(D)) - return !D->getDeclContext()->isFunctionOrMethod(); - if (const auto *Var = dyn_cast<VarDecl>(D)) - return Var->isFileVarDecl() && - (Var->isThisDeclarationADefinition() == VarDecl::Definition || - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Var)); - if (const auto *Func = dyn_cast<FunctionDecl>(D)) - return Func->doesThisDeclarationHaveABody() || HasBody; - - if (auto *ES = D->getASTContext().getExternalSource()) - if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never) - return true; - - return false; -} - -/// Get the correct cursor and offset for loading a declaration. -ASTReader::RecordLocation -ASTReader::DeclCursorForID(DeclID ID, SourceLocation &Loc) { - GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID); - assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); - ModuleFile *M = I->second; - const DeclOffset &DOffs = - M->DeclOffsets[ID - M->BaseDeclID - NUM_PREDEF_DECL_IDS]; - Loc = TranslateSourceLocation(*M, DOffs.getLocation()); - return RecordLocation(M, DOffs.BitOffset); -} - -ASTReader::RecordLocation ASTReader::getLocalBitOffset(uint64_t GlobalOffset) { - auto I = GlobalBitOffsetsMap.find(GlobalOffset); - - assert(I != GlobalBitOffsetsMap.end() && "Corrupted global bit offsets map"); - return RecordLocation(I->second, GlobalOffset - I->second->GlobalBitOffset); -} - -uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset) { - return LocalOffset + M.GlobalBitOffset; -} - -static bool isSameTemplateParameterList(const TemplateParameterList *X, - const TemplateParameterList *Y); - -/// 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 auto *TX = dyn_cast<TemplateTypeParmDecl>(X)) { - const auto *TY = cast<TemplateTypeParmDecl>(Y); - return TX->isParameterPack() == TY->isParameterPack(); - } - - if (const auto *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) { - const auto *TY = cast<NonTypeTemplateParmDecl>(Y); - return TX->isParameterPack() == TY->isParameterPack() && - TX->getASTContext().hasSameType(TX->getType(), TY->getType()); - } - - const auto *TX = cast<TemplateTemplateParmDecl>(X); - const auto *TY = cast<TemplateTemplateParmDecl>(Y); - return TX->isParameterPack() == TY->isParameterPack() && - isSameTemplateParameterList(TX->getTemplateParameters(), - TY->getTemplateParameters()); -} - -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; -} - -/// 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; -} - -/// Determine whether the attributes we can overload on are identical for A and -/// B. Will ignore any overloadable attrs represented in the type of A and B. -static bool hasSameOverloadableAttrs(const FunctionDecl *A, - const FunctionDecl *B) { - // Note that pass_object_size attributes are represented in the function's - // ExtParameterInfo, so we don't need to check them here. - - llvm::FoldingSetNodeID Cand1ID, Cand2ID; - auto AEnableIfAttrs = A->specific_attrs<EnableIfAttr>(); - auto BEnableIfAttrs = B->specific_attrs<EnableIfAttr>(); - - for (auto Pair : zip_longest(AEnableIfAttrs, BEnableIfAttrs)) { - Optional<EnableIfAttr *> Cand1A = std::get<0>(Pair); - Optional<EnableIfAttr *> Cand2A = std::get<1>(Pair); - - // Return false if the number of enable_if attributes is different. - if (!Cand1A || !Cand2A) - return false; - - Cand1ID.clear(); - Cand2ID.clear(); - - (*Cand1A)->getCond()->Profile(Cand1ID, A->getASTContext(), true); - (*Cand2A)->getCond()->Profile(Cand2ID, B->getASTContext(), true); - - // Return false if any of the enable_if expressions of A and B are - // different. - if (Cand1ID != Cand2ID) - return false; - } - return true; -} - -/// Determine whether the two declarations refer to the same entity. -static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { - assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!"); - - if (X == Y) - return true; - - // Must be in the same context. - // - // Note that we can't use DeclContext::Equals here, because the DeclContexts - // could be two different declarations of the same function. (We will fix the - // semantic DC to refer to the primary definition after merging.) - if (!declaresSameEntity(cast<Decl>(X->getDeclContext()->getRedeclContext()), - cast<Decl>(Y->getDeclContext()->getRedeclContext()))) - return false; - - // Two typedefs refer to the same entity if they have the same underlying - // type. - if (const auto *TypedefX = dyn_cast<TypedefNameDecl>(X)) - if (const auto *TypedefY = dyn_cast<TypedefNameDecl>(Y)) - return X->getASTContext().hasSameType(TypedefX->getUnderlyingType(), - TypedefY->getUnderlyingType()); - - // Must have the same kind. - if (X->getKind() != Y->getKind()) - return false; - - // Objective-C classes and protocols with the same name always match. - if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X)) - return true; - - if (isa<ClassTemplateSpecializationDecl>(X)) { - // No need to handle these here: we merge them when adding them to the - // template. - return false; - } - - // Compatible tags match. - if (const auto *TagX = dyn_cast<TagDecl>(X)) { - const auto *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)); - } - - // Functions with the same type and linkage match. - // FIXME: This needs to cope with merging of prototyped/non-prototyped - // functions, etc. - if (const auto *FuncX = dyn_cast<FunctionDecl>(X)) { - const auto *FuncY = cast<FunctionDecl>(Y); - if (const auto *CtorX = dyn_cast<CXXConstructorDecl>(X)) { - const auto *CtorY = cast<CXXConstructorDecl>(Y); - if (CtorX->getInheritedConstructor() && - !isSameEntity(CtorX->getInheritedConstructor().getConstructor(), - CtorY->getInheritedConstructor().getConstructor())) - return false; - } - - if (FuncX->isMultiVersion() != FuncY->isMultiVersion()) - return false; - - // Multiversioned functions with different feature strings are represented - // as separate declarations. - if (FuncX->isMultiVersion()) { - const auto *TAX = FuncX->getAttr<TargetAttr>(); - const auto *TAY = FuncY->getAttr<TargetAttr>(); - assert(TAX && TAY && "Multiversion Function without target attribute"); - - if (TAX->getFeaturesStr() != TAY->getFeaturesStr()) - return false; - } - - ASTContext &C = FuncX->getASTContext(); - auto GetTypeAsWritten = [](const FunctionDecl *FD) { - // Map to the first declaration that we've already merged into this one. - // The TSI of redeclarations might not match (due to calling conventions - // being inherited onto the type but not the TSI), but the TSI type of - // the first declaration of the function should match across modules. - FD = FD->getCanonicalDecl(); - return FD->getTypeSourceInfo() ? FD->getTypeSourceInfo()->getType() - : FD->getType(); - }; - QualType XT = GetTypeAsWritten(FuncX), YT = GetTypeAsWritten(FuncY); - if (!C.hasSameType(XT, YT)) { - // We can get functions with different types on the redecl chain in C++17 - // if they have differing exception specifications and at least one of - // the excpetion specs is unresolved. - auto *XFPT = XT->getAs<FunctionProtoType>(); - auto *YFPT = YT->getAs<FunctionProtoType>(); - if (C.getLangOpts().CPlusPlus17 && XFPT && YFPT && - (isUnresolvedExceptionSpec(XFPT->getExceptionSpecType()) || - isUnresolvedExceptionSpec(YFPT->getExceptionSpecType())) && - C.hasSameFunctionTypeIgnoringExceptionSpec(XT, YT)) - return true; - return false; - } - return FuncX->getLinkageInternal() == FuncY->getLinkageInternal() && - hasSameOverloadableAttrs(FuncX, FuncY); - } - - // Variables with the same type and linkage match. - if (const auto *VarX = dyn_cast<VarDecl>(X)) { - const auto *VarY = cast<VarDecl>(Y); - if (VarX->getLinkageInternal() == VarY->getLinkageInternal()) { - ASTContext &C = VarX->getASTContext(); - if (C.hasSameType(VarX->getType(), VarY->getType())) - return true; - - // We can get decls with different types on the redecl chain. Eg. - // template <typename T> struct S { static T Var[]; }; // #1 - // template <typename T> T S<T>::Var[sizeof(T)]; // #2 - // Only? happens when completing an incomplete array type. In this case - // when comparing #1 and #2 we should go through their element type. - const ArrayType *VarXTy = C.getAsArrayType(VarX->getType()); - const ArrayType *VarYTy = C.getAsArrayType(VarY->getType()); - if (!VarXTy || !VarYTy) - return false; - if (VarXTy->isIncompleteArrayType() || VarYTy->isIncompleteArrayType()) - return C.hasSameType(VarXTy->getElementType(), VarYTy->getElementType()); - } - return false; - } - - // Namespaces with the same name and inlinedness match. - if (const auto *NamespaceX = dyn_cast<NamespaceDecl>(X)) { - const auto *NamespaceY = cast<NamespaceDecl>(Y); - return NamespaceX->isInline() == NamespaceY->isInline(); - } - - // Identical template names and kinds match if their template parameter lists - // and patterns match. - if (const auto *TemplateX = dyn_cast<TemplateDecl>(X)) { - const auto *TemplateY = cast<TemplateDecl>(Y); - return isSameEntity(TemplateX->getTemplatedDecl(), - TemplateY->getTemplatedDecl()) && - isSameTemplateParameterList(TemplateX->getTemplateParameters(), - TemplateY->getTemplateParameters()); - } - - // Fields with the same name and the same type match. - if (const auto *FDX = dyn_cast<FieldDecl>(X)) { - const auto *FDY = cast<FieldDecl>(Y); - // FIXME: Also check the bitwidth is odr-equivalent, if any. - return X->getASTContext().hasSameType(FDX->getType(), FDY->getType()); - } - - // Indirect fields with the same target field match. - if (const auto *IFDX = dyn_cast<IndirectFieldDecl>(X)) { - const auto *IFDY = cast<IndirectFieldDecl>(Y); - return IFDX->getAnonField()->getCanonicalDecl() == - IFDY->getAnonField()->getCanonicalDecl(); - } - - // Enumerators with the same name match. - if (isa<EnumConstantDecl>(X)) - // FIXME: Also check the value is odr-equivalent. - return true; - - // Using shadow declarations with the same target match. - if (const auto *USX = dyn_cast<UsingShadowDecl>(X)) { - const auto *USY = cast<UsingShadowDecl>(Y); - return USX->getTargetDecl() == USY->getTargetDecl(); - } - - // Using declarations with the same qualifier match. (We already know that - // the name matches.) - if (const auto *UX = dyn_cast<UsingDecl>(X)) { - const auto *UY = cast<UsingDecl>(Y); - return isSameQualifier(UX->getQualifier(), UY->getQualifier()) && - UX->hasTypename() == UY->hasTypename() && - UX->isAccessDeclaration() == UY->isAccessDeclaration(); - } - if (const auto *UX = dyn_cast<UnresolvedUsingValueDecl>(X)) { - const auto *UY = cast<UnresolvedUsingValueDecl>(Y); - return isSameQualifier(UX->getQualifier(), UY->getQualifier()) && - UX->isAccessDeclaration() == UY->isAccessDeclaration(); - } - if (const auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X)) - return isSameQualifier( - UX->getQualifier(), - cast<UnresolvedUsingTypenameDecl>(Y)->getQualifier()); - - // Namespace alias definitions with the same target match. - if (const auto *NAX = dyn_cast<NamespaceAliasDecl>(X)) { - const auto *NAY = cast<NamespaceAliasDecl>(Y); - return NAX->getNamespace()->Equals(NAY->getNamespace()); - } - - return false; -} - -/// Find the context in which we should search for previous declarations when -/// looking for declarations to merge. -DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader, - DeclContext *DC) { - if (auto *ND = dyn_cast<NamespaceDecl>(DC)) - return ND->getOriginalNamespace(); - - if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) { - // Try to dig out the definition. - auto *DD = RD->DefinitionData; - if (!DD) - DD = RD->getCanonicalDecl()->DefinitionData; - - // 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.getContext()) struct CXXRecordDecl::DefinitionData(RD); - RD->setCompleteDefinition(true); - RD->DefinitionData = DD; - RD->getCanonicalDecl()->DefinitionData = DD; - - // Track that we did this horrible thing so that we can fix it later. - Reader.PendingFakeDefinitionData.insert( - std::make_pair(DD, ASTReader::PendingFakeDefinitionKind::Fake)); - } - - return DD->Definition; - } - - if (auto *ED = dyn_cast<EnumDecl>(DC)) - return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition() - : nullptr; - - // 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; - - return nullptr; -} - -ASTDeclReader::FindExistingResult::~FindExistingResult() { - // 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; - } - - if (!AddResult || Existing) - return; - - DeclarationName Name = New->getDeclName(); - DeclContext *DC = New->getDeclContext()->getRedeclContext(); - if (needsAnonymousDeclarationNumber(New)) { - setAnonymousDeclForMerging(Reader, New->getLexicalDeclContext(), - AnonymousDeclNumber, New); - } else if (DC->isTranslationUnit() && - !Reader.getContext().getLangOpts().CPlusPlus) { - if (Reader.getIdResolver().tryAddTopLevelDecl(New, Name)) - Reader.PendingFakeLookupResults[Name.getAsIdentifierInfo()] - .push_back(New); - } else if (DeclContext *MergeDC = getPrimaryContextForMerging(Reader, DC)) { - // Add the declaration to its redeclaration context so later merging - // lookups will find it. - MergeDC->makeDeclVisibleInContextImpl(New, /*Internal*/true); - } -} - -/// 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. - if (Found->isFromASTFile()) - return nullptr; - - if (auto *TND = dyn_cast<TypedefNameDecl>(Found)) - return TND->getAnonDeclWithTypedefName(/*AnyRedecl*/true); - - return nullptr; -} - -/// Find the declaration to use to populate the anonymous declaration table -/// for the given lexical DeclContext. We only care about finding local -/// definitions of the context; we'll merge imported ones as we go. -DeclContext * -ASTDeclReader::getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC) { - // For classes, we track the definition as we merge. - if (auto *RD = dyn_cast<CXXRecordDecl>(LexicalDC)) { - auto *DD = RD->getCanonicalDecl()->DefinitionData; - return DD ? DD->Definition : nullptr; - } - - // For anything else, walk its merged redeclarations looking for a definition. - // Note that we can't just call getDefinition here because the redeclaration - // chain isn't wired up. - for (auto *D : merged_redecls(cast<Decl>(LexicalDC))) { - if (auto *FD = dyn_cast<FunctionDecl>(D)) - if (FD->isThisDeclarationADefinition()) - return FD; - if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) - if (MD->isThisDeclarationADefinition()) - return MD; - } - - // No merged definition yet. - return nullptr; -} - -NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader, - DeclContext *DC, - unsigned Index) { - // If the lexical context has been merged, look into the now-canonical - // definition. - auto *CanonDC = cast<Decl>(DC)->getCanonicalDecl(); - - // If we've seen this before, return the canonical declaration. - auto &Previous = Reader.AnonymousDeclarationsForMerging[CanonDC]; - 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. - auto *PrimaryDC = getPrimaryDCForAnonymousDecl(DC); - if (PrimaryDC && !cast<Decl>(PrimaryDC)->isFromASTFile()) { - numberAnonymousDeclsWithin(PrimaryDC, [&](NamedDecl *ND, unsigned Number) { - if (Previous.size() == Number) - Previous.push_back(cast<NamedDecl>(ND->getCanonicalDecl())); - else - Previous[Number] = cast<NamedDecl>(ND->getCanonicalDecl()); - }); - } - - return Index < Previous.size() ? Previous[Index] : nullptr; -} - -void ASTDeclReader::setAnonymousDeclForMerging(ASTReader &Reader, - DeclContext *DC, unsigned Index, - NamedDecl *D) { - auto *CanonDC = cast<Decl>(DC)->getCanonicalDecl(); - - auto &Previous = Reader.AnonymousDeclarationsForMerging[CanonDC]; - if (Index >= Previous.size()) - Previous.resize(Index + 1); - if (!Previous[Index]) - Previous[Index] = D; -} - -ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { - DeclarationName Name = TypedefNameForLinkage ? TypedefNameForLinkage - : D->getDeclName(); - - if (!Name && !needsAnonymousDeclarationNumber(D)) { - // Don't bother trying to find unnamed declarations that are in - // unmergeable contexts. - FindExistingResult Result(Reader, D, /*Existing=*/nullptr, - AnonymousDeclNumber, TypedefNameForLinkage); - Result.suppress(); - return Result; - } - - DeclContext *DC = D->getDeclContext()->getRedeclContext(); - if (TypedefNameForLinkage) { - auto It = Reader.ImportedTypedefNamesForLinkage.find( - std::make_pair(DC, TypedefNameForLinkage)); - if (It != Reader.ImportedTypedefNamesForLinkage.end()) - if (isSameEntity(It->second, D)) - return FindExistingResult(Reader, D, It->second, AnonymousDeclNumber, - TypedefNameForLinkage); - // Go on to check in other places in case an existing typedef name - // was not imported. - } - - if (needsAnonymousDeclarationNumber(D)) { - // 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)) - return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber, - TypedefNameForLinkage); - } else if (DC->isTranslationUnit() && - !Reader.getContext().getLangOpts().CPlusPlus) { - IdentifierResolver &IdResolver = Reader.getIdResolver(); - - // Temporarily consider the identifier to be up-to-date. We don't want to - // cause additional lookups here. - class UpToDateIdentifierRAII { - IdentifierInfo *II; - bool WasOutToDate = false; - - public: - explicit UpToDateIdentifierRAII(IdentifierInfo *II) : II(II) { - if (II) { - WasOutToDate = II->isOutOfDate(); - if (WasOutToDate) - II->setOutOfDate(false); - } - } - - ~UpToDateIdentifierRAII() { - if (WasOutToDate) - II->setOutOfDate(true); - } - } UpToDate(Name.getAsIdentifierInfo()); - - for (IdentifierResolver::iterator I = IdResolver.begin(Name), - IEnd = IdResolver.end(); - I != IEnd; ++I) { - if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage)) - if (isSameEntity(Existing, D)) - return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber, - TypedefNameForLinkage); - } - } else if (DeclContext *MergeDC = getPrimaryContextForMerging(Reader, DC)) { - DeclContext::lookup_result R = MergeDC->noload_lookup(Name); - for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { - if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage)) - if (isSameEntity(Existing, D)) - return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber, - TypedefNameForLinkage); - } - } else { - // Not in a mergeable context. - return FindExistingResult(Reader); - } - - // 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. - // - // FIXME: We should do something similar if we merge two definitions of the - // same template specialization into the same CXXRecordDecl. - auto MergedDCIt = Reader.MergedDeclContexts.find(D->getLexicalDeclContext()); - if (MergedDCIt != Reader.MergedDeclContexts.end() && - MergedDCIt->second == D->getDeclContext()) - Reader.PendingOdrMergeChecks.push_back(D); - - return FindExistingResult(Reader, D, /*Existing=*/nullptr, - AnonymousDeclNumber, TypedefNameForLinkage); -} - -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"); -} - -Decl *ASTReader::getMostRecentExistingDecl(Decl *D) { - return ASTDeclReader::getMostRecentDecl(D->getCanonicalDecl()); -} - -template<typename DeclT> -void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, - Redeclarable<DeclT> *D, - Decl *Previous, Decl *Canon) { - D->RedeclLink.setPrevious(cast<DeclT>(Previous)); - D->First = cast<DeclT>(Previous)->First; -} - -namespace clang { - -template<> -void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, - Redeclarable<VarDecl> *D, - Decl *Previous, Decl *Canon) { - auto *VD = static_cast<VarDecl *>(D); - auto *PrevVD = cast<VarDecl>(Previous); - D->RedeclLink.setPrevious(PrevVD); - D->First = PrevVD->First; - - // We should keep at most one definition on the chain. - // FIXME: Cache the definition once we've found it. Building a chain with - // N definitions currently takes O(N^2) time here. - if (VD->isThisDeclarationADefinition() == VarDecl::Definition) { - for (VarDecl *CurD = PrevVD; CurD; CurD = CurD->getPreviousDecl()) { - if (CurD->isThisDeclarationADefinition() == VarDecl::Definition) { - Reader.mergeDefinitionVisibility(CurD, VD); - VD->demoteThisDefinitionToDeclaration(); - break; - } - } - } -} - -static bool isUndeducedReturnType(QualType T) { - auto *DT = T->getContainedDeducedType(); - return DT && !DT->isDeduced(); -} - -template<> -void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, - Redeclarable<FunctionDecl> *D, - Decl *Previous, Decl *Canon) { - auto *FD = static_cast<FunctionDecl *>(D); - auto *PrevFD = cast<FunctionDecl>(Previous); - - FD->RedeclLink.setPrevious(PrevFD); - FD->First = PrevFD->First; - - // If the previous declaration is an inline function declaration, then this - // declaration is too. - if (PrevFD->isInlined() != FD->isInlined()) { - // 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->setImplicitlyInline(true); - } - - auto *FPT = FD->getType()->getAs<FunctionProtoType>(); - auto *PrevFPT = PrevFD->getType()->getAs<FunctionProtoType>(); - if (FPT && PrevFPT) { - // If we need to propagate an exception specification along the redecl - // chain, make a note of that so that we can do so later. - bool IsUnresolved = isUnresolvedExceptionSpec(FPT->getExceptionSpecType()); - bool WasUnresolved = - isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType()); - if (IsUnresolved != WasUnresolved) - Reader.PendingExceptionSpecUpdates.insert( - {Canon, IsUnresolved ? PrevFD : FD}); - - // If we need to propagate a deduced return type along the redecl chain, - // make a note of that so that we can do it later. - bool IsUndeduced = isUndeducedReturnType(FPT->getReturnType()); - bool WasUndeduced = isUndeducedReturnType(PrevFPT->getReturnType()); - if (IsUndeduced != WasUndeduced) - Reader.PendingDeducedTypeUpdates.insert( - {cast<FunctionDecl>(Canon), - (IsUndeduced ? PrevFPT : FPT)->getReturnType()}); - } -} - -} // namespace clang - -void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, ...) { - llvm_unreachable("attachPreviousDecl on non-redeclarable declaration"); -} - -/// 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; - To->setInheritedDefaultArgument(Context, From); - 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(I); - NamedDecl *ToParam = ToTP->getParam(I); - - if (auto *FTTP = dyn_cast<TemplateTypeParmDecl>(FromParam)) - inheritDefaultTemplateArgument(Context, FTTP, ToParam); - else if (auto *FNTTP = dyn_cast<NonTypeTemplateParmDecl>(FromParam)) - inheritDefaultTemplateArgument(Context, FNTTP, ToParam); - else - inheritDefaultTemplateArgument( - Context, cast<TemplateTemplateParmDecl>(FromParam), ToParam); - } -} - -void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D, - Decl *Previous, Decl *Canon) { - assert(D && Previous); - - switch (D->getKind()) { -#define ABSTRACT_DECL(TYPE) -#define DECL(TYPE, BASE) \ - case Decl::TYPE: \ - attachPreviousDeclImpl(Reader, cast<TYPE##Decl>(D), Previous, Canon); \ - break; -#include "clang/AST/DeclNodes.inc" - } - - // If the declaration was visible in one module, a redeclaration of it in - // another module remains visible even if it wouldn't be visible by itself. - // - // FIXME: In this case, the declaration should only be visible if a module - // that makes it visible has been imported. - D->IdentifierNamespace |= - Previous->IdentifierNamespace & - (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type); - - // If the declaration declares a template, it may inherit default arguments - // from the previous declaration. - if (auto *TD = dyn_cast<TemplateDecl>(D)) - inheritDefaultTemplateArguments(Reader.getContext(), - cast<TemplateDecl>(Previous), TD); -} - -template<typename DeclT> -void ASTDeclReader::attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest) { - D->RedeclLink.setLatest(cast<DeclT>(Latest)); -} - -void ASTDeclReader::attachLatestDeclImpl(...) { - llvm_unreachable("attachLatestDecl on non-redeclarable declaration"); -} - -void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) { - assert(D && Latest); - - switch (D->getKind()) { -#define ABSTRACT_DECL(TYPE) -#define DECL(TYPE, BASE) \ - case Decl::TYPE: \ - attachLatestDeclImpl(cast<TYPE##Decl>(D), Latest); \ - break; -#include "clang/AST/DeclNodes.inc" - } -} - -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" - } -} - -/// Read the declaration at the given offset from the AST file. -Decl *ASTReader::ReadDeclRecord(DeclID ID) { - unsigned Index = ID - NUM_PREDEF_DECL_IDS; - SourceLocation DeclLoc; - RecordLocation Loc = DeclCursorForID(ID, DeclLoc); - llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; - // Keep track of where we are in the stream, then jump back there - // after reading this declaration. - SavedStreamPosition SavedPosition(DeclsCursor); - - ReadingKindTracker ReadingKind(Read_Decl, *this); - - // Note that we are loading a declaration record. - Deserializing ADecl(this); - - DeclsCursor.JumpToBit(Loc.Offset); - ASTRecordReader Record(*this, *Loc.F); - ASTDeclReader Reader(*this, Record, Loc, ID, DeclLoc); - unsigned Code = DeclsCursor.ReadCode(); - - ASTContext &Context = getContext(); - Decl *D = nullptr; - switch ((DeclCode)Record.readRecord(DeclsCursor, Code)) { - case DECL_CONTEXT_LEXICAL: - case DECL_CONTEXT_VISIBLE: - llvm_unreachable("Record cannot be de-serialized with ReadDeclRecord"); - case DECL_TYPEDEF: - D = TypedefDecl::CreateDeserialized(Context, ID); - break; - case DECL_TYPEALIAS: - D = TypeAliasDecl::CreateDeserialized(Context, ID); - break; - case DECL_ENUM: - D = EnumDecl::CreateDeserialized(Context, ID); - break; - case DECL_RECORD: - D = RecordDecl::CreateDeserialized(Context, ID); - break; - case DECL_ENUM_CONSTANT: - D = EnumConstantDecl::CreateDeserialized(Context, ID); - break; - case DECL_FUNCTION: - D = FunctionDecl::CreateDeserialized(Context, ID); - break; - case DECL_LINKAGE_SPEC: - D = LinkageSpecDecl::CreateDeserialized(Context, ID); - break; - case DECL_EXPORT: - D = ExportDecl::CreateDeserialized(Context, ID); - break; - case DECL_LABEL: - D = LabelDecl::CreateDeserialized(Context, ID); - break; - case DECL_NAMESPACE: - D = NamespaceDecl::CreateDeserialized(Context, ID); - break; - case DECL_NAMESPACE_ALIAS: - D = NamespaceAliasDecl::CreateDeserialized(Context, ID); - break; - case DECL_USING: - D = UsingDecl::CreateDeserialized(Context, ID); - break; - case DECL_USING_PACK: - D = UsingPackDecl::CreateDeserialized(Context, ID, Record.readInt()); - break; - case DECL_USING_SHADOW: - D = UsingShadowDecl::CreateDeserialized(Context, ID); - break; - case DECL_CONSTRUCTOR_USING_SHADOW: - D = ConstructorUsingShadowDecl::CreateDeserialized(Context, ID); - break; - case DECL_USING_DIRECTIVE: - D = UsingDirectiveDecl::CreateDeserialized(Context, ID); - break; - case DECL_UNRESOLVED_USING_VALUE: - D = UnresolvedUsingValueDecl::CreateDeserialized(Context, ID); - break; - case DECL_UNRESOLVED_USING_TYPENAME: - D = UnresolvedUsingTypenameDecl::CreateDeserialized(Context, ID); - break; - case DECL_CXX_RECORD: - D = CXXRecordDecl::CreateDeserialized(Context, ID); - break; - case DECL_CXX_DEDUCTION_GUIDE: - D = CXXDeductionGuideDecl::CreateDeserialized(Context, ID); - break; - case DECL_CXX_METHOD: - D = CXXMethodDecl::CreateDeserialized(Context, ID); - break; - case DECL_CXX_CONSTRUCTOR: - D = CXXConstructorDecl::CreateDeserialized(Context, ID, false); - break; - case DECL_CXX_INHERITED_CONSTRUCTOR: - D = CXXConstructorDecl::CreateDeserialized(Context, ID, true); - break; - case DECL_CXX_DESTRUCTOR: - D = CXXDestructorDecl::CreateDeserialized(Context, ID); - break; - case DECL_CXX_CONVERSION: - D = CXXConversionDecl::CreateDeserialized(Context, ID); - break; - case DECL_ACCESS_SPEC: - D = AccessSpecDecl::CreateDeserialized(Context, ID); - break; - case DECL_FRIEND: - D = FriendDecl::CreateDeserialized(Context, ID, Record.readInt()); - break; - case DECL_FRIEND_TEMPLATE: - D = FriendTemplateDecl::CreateDeserialized(Context, ID); - break; - case DECL_CLASS_TEMPLATE: - D = ClassTemplateDecl::CreateDeserialized(Context, ID); - break; - case DECL_CLASS_TEMPLATE_SPECIALIZATION: - D = ClassTemplateSpecializationDecl::CreateDeserialized(Context, ID); - break; - case DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION: - D = ClassTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID); - break; - 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; - case DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION: - D = ClassScopeFunctionSpecializationDecl::CreateDeserialized(Context, ID); - break; - case DECL_FUNCTION_TEMPLATE: - D = FunctionTemplateDecl::CreateDeserialized(Context, ID); - break; - case DECL_TEMPLATE_TYPE_PARM: - D = TemplateTypeParmDecl::CreateDeserialized(Context, ID); - break; - case DECL_NON_TYPE_TEMPLATE_PARM: - D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID); - break; - case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK: - D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID, - Record.readInt()); - break; - case DECL_TEMPLATE_TEMPLATE_PARM: - D = TemplateTemplateParmDecl::CreateDeserialized(Context, ID); - break; - case DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK: - D = TemplateTemplateParmDecl::CreateDeserialized(Context, ID, - Record.readInt()); - break; - case DECL_TYPE_ALIAS_TEMPLATE: - D = TypeAliasTemplateDecl::CreateDeserialized(Context, ID); - break; - case DECL_STATIC_ASSERT: - D = StaticAssertDecl::CreateDeserialized(Context, ID); - break; - case DECL_OBJC_METHOD: - D = ObjCMethodDecl::CreateDeserialized(Context, ID); - break; - case DECL_OBJC_INTERFACE: - D = ObjCInterfaceDecl::CreateDeserialized(Context, ID); - break; - case DECL_OBJC_IVAR: - D = ObjCIvarDecl::CreateDeserialized(Context, ID); - break; - case DECL_OBJC_PROTOCOL: - D = ObjCProtocolDecl::CreateDeserialized(Context, ID); - break; - case DECL_OBJC_AT_DEFS_FIELD: - D = ObjCAtDefsFieldDecl::CreateDeserialized(Context, ID); - break; - case DECL_OBJC_CATEGORY: - D = ObjCCategoryDecl::CreateDeserialized(Context, ID); - break; - case DECL_OBJC_CATEGORY_IMPL: - D = ObjCCategoryImplDecl::CreateDeserialized(Context, ID); - break; - case DECL_OBJC_IMPLEMENTATION: - D = ObjCImplementationDecl::CreateDeserialized(Context, ID); - break; - case DECL_OBJC_COMPATIBLE_ALIAS: - D = ObjCCompatibleAliasDecl::CreateDeserialized(Context, ID); - break; - case DECL_OBJC_PROPERTY: - D = ObjCPropertyDecl::CreateDeserialized(Context, ID); - break; - case DECL_OBJC_PROPERTY_IMPL: - D = ObjCPropertyImplDecl::CreateDeserialized(Context, ID); - break; - case DECL_FIELD: - D = FieldDecl::CreateDeserialized(Context, ID); - break; - case DECL_INDIRECTFIELD: - D = IndirectFieldDecl::CreateDeserialized(Context, ID); - break; - case DECL_VAR: - D = VarDecl::CreateDeserialized(Context, ID); - break; - case DECL_IMPLICIT_PARAM: - D = ImplicitParamDecl::CreateDeserialized(Context, ID); - break; - case DECL_PARM_VAR: - D = ParmVarDecl::CreateDeserialized(Context, ID); - break; - case DECL_DECOMPOSITION: - D = DecompositionDecl::CreateDeserialized(Context, ID, Record.readInt()); - break; - case DECL_BINDING: - D = BindingDecl::CreateDeserialized(Context, ID); - break; - case DECL_FILE_SCOPE_ASM: - D = FileScopeAsmDecl::CreateDeserialized(Context, ID); - break; - case DECL_BLOCK: - D = BlockDecl::CreateDeserialized(Context, ID); - break; - case DECL_MS_PROPERTY: - D = MSPropertyDecl::CreateDeserialized(Context, ID); - break; - case DECL_CAPTURED: - D = CapturedDecl::CreateDeserialized(Context, ID, Record.readInt()); - break; - case DECL_CXX_BASE_SPECIFIERS: - Error("attempt to read a C++ base-specifier record as a declaration"); - return nullptr; - case DECL_CXX_CTOR_INITIALIZERS: - Error("attempt to read a C++ ctor initializer record as a declaration"); - return nullptr; - case DECL_IMPORT: - // Note: last entry of the ImportDecl record is the number of stored source - // locations. - D = ImportDecl::CreateDeserialized(Context, ID, Record.back()); - break; - case DECL_OMP_THREADPRIVATE: - D = OMPThreadPrivateDecl::CreateDeserialized(Context, ID, Record.readInt()); - break; - case DECL_OMP_REQUIRES: - D = OMPRequiresDecl::CreateDeserialized(Context, ID, Record.readInt()); - break; - case DECL_OMP_DECLARE_REDUCTION: - D = OMPDeclareReductionDecl::CreateDeserialized(Context, ID); - break; - case DECL_OMP_CAPTUREDEXPR: - D = OMPCapturedExprDecl::CreateDeserialized(Context, ID); - break; - case DECL_PRAGMA_COMMENT: - D = PragmaCommentDecl::CreateDeserialized(Context, ID, Record.readInt()); - break; - case DECL_PRAGMA_DETECT_MISMATCH: - D = PragmaDetectMismatchDecl::CreateDeserialized(Context, ID, - Record.readInt()); - break; - case DECL_EMPTY: - D = EmptyDecl::CreateDeserialized(Context, ID); - break; - case DECL_OBJC_TYPE_PARAM: - D = ObjCTypeParamDecl::CreateDeserialized(Context, ID); - break; - } - - assert(D && "Unknown declaration reading AST file"); - LoadedDecl(Index, D); - // 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()); - Reader.Visit(D); - - // If this declaration is also a declaration context, get the - // offsets for its tables of lexical and visible declarations. - if (auto *DC = dyn_cast<DeclContext>(D)) { - std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC); - if (Offsets.first && - ReadLexicalDeclContextStorage(*Loc.F, DeclsCursor, Offsets.first, DC)) - return nullptr; - if (Offsets.second && - ReadVisibleDeclContextStorage(*Loc.F, DeclsCursor, Offsets.second, ID)) - return nullptr; - } - assert(Record.getIdx() == Record.size()); - - // Load any relevant update records. - PendingUpdateRecords.push_back( - PendingUpdateRecord(ID, D, /*JustLoaded=*/true)); - - // Load the categories after recursive loading is finished. - if (auto *Class = dyn_cast<ObjCInterfaceDecl>(D)) - // If we already have a definition when deserializing the ObjCInterfaceDecl, - // we put the Decl in PendingDefinitions so we can pull the categories here. - if (Class->isThisDeclarationADefinition() || - PendingDefinitions.count(Class)) - loadObjCCategories(ID, Class); - - // 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. - PotentiallyInterestingDecls.push_back( - InterestingDecl(D, Reader.hasPendingBody())); - - return D; -} - -void ASTReader::PassInterestingDeclsToConsumer() { - assert(Consumer); - - if (PassingDeclsToConsumer) - return; - - // Guard variable to avoid recursively redoing the process of passing - // decls to consumer. - SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer, - true); - - // Ensure that we've loaded all potentially-interesting declarations - // that need to be eagerly loaded. - for (auto ID : EagerlyDeserializedDecls) - GetDecl(ID); - EagerlyDeserializedDecls.clear(); - - while (!PotentiallyInterestingDecls.empty()) { - InterestingDecl D = PotentiallyInterestingDecls.front(); - PotentiallyInterestingDecls.pop_front(); - if (isConsumerInterestedIn(getContext(), D.getDecl(), D.hasPendingBody())) - PassInterestingDeclToConsumer(D.getDecl()); - } -} - -void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { - // 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. - serialization::GlobalDeclID ID = Record.ID; - Decl *D = Record.D; - ProcessingUpdatesRAIIObj ProcessingUpdates(*this); - DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID); - - SmallVector<serialization::DeclID, 8> PendingLazySpecializationIDs; - - if (UpdI != DeclUpdateOffsets.end()) { - auto UpdateOffsets = std::move(UpdI->second); - DeclUpdateOffsets.erase(UpdI); - - // Check if this decl was interesting to the consumer. If we just loaded - // the declaration, then we know it was interesting and we skip the call - // to isConsumerInterestedIn because it is unsafe to call in the - // current ASTReader state. - bool WasInteresting = - Record.JustLoaded || isConsumerInterestedIn(getContext(), D, false); - for (auto &FileAndOffset : UpdateOffsets) { - ModuleFile *F = FileAndOffset.first; - uint64_t Offset = FileAndOffset.second; - llvm::BitstreamCursor &Cursor = F->DeclsCursor; - SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(Offset); - unsigned Code = Cursor.ReadCode(); - ASTRecordReader Record(*this, *F); - unsigned RecCode = Record.readRecord(Cursor, Code); - (void)RecCode; - assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!"); - - ASTDeclReader Reader(*this, Record, RecordLocation(F, Offset), ID, - SourceLocation()); - Reader.UpdateDecl(D, PendingLazySpecializationIDs); - - // We might have made this declaration interesting. If so, remember that - // we need to hand it off to the consumer. - if (!WasInteresting && - isConsumerInterestedIn(getContext(), D, Reader.hasPendingBody())) { - PotentiallyInterestingDecls.push_back( - InterestingDecl(D, Reader.hasPendingBody())); - WasInteresting = true; - } - } - } - // Add the lazy specializations to the template. - assert((PendingLazySpecializationIDs.empty() || isa<ClassTemplateDecl>(D) || - isa<FunctionTemplateDecl>(D) || isa<VarTemplateDecl>(D)) && - "Must not have pending specializations"); - if (auto *CTD = dyn_cast<ClassTemplateDecl>(D)) - ASTDeclReader::AddLazySpecializations(CTD, PendingLazySpecializationIDs); - else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) - ASTDeclReader::AddLazySpecializations(FTD, PendingLazySpecializationIDs); - else if (auto *VTD = dyn_cast<VarTemplateDecl>(D)) - ASTDeclReader::AddLazySpecializations(VTD, PendingLazySpecializationIDs); - PendingLazySpecializationIDs.clear(); - - // Load the pending visible updates for this decl context, if it has any. - auto I = PendingVisibleUpdates.find(ID); - if (I != PendingVisibleUpdates.end()) { - auto VisibleUpdates = std::move(I->second); - PendingVisibleUpdates.erase(I); - - auto *DC = cast<DeclContext>(D)->getPrimaryContext(); - for (const auto &Update : VisibleUpdates) - Lookups[DC].Table.add( - Update.Mod, Update.Data, - reader::ASTDeclContextNameLookupTrait(*this, *Update.Mod)); - DC->setHasExternalVisibleStorage(true); - } -} - -void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) { - // Attach FirstLocal to the end of the decl chain. - Decl *CanonDecl = FirstLocal->getCanonicalDecl(); - if (FirstLocal != CanonDecl) { - Decl *PrevMostRecent = ASTDeclReader::getMostRecentDecl(CanonDecl); - ASTDeclReader::attachPreviousDecl( - *this, FirstLocal, PrevMostRecent ? PrevMostRecent : CanonDecl, - CanonDecl); - } - - if (!LocalOffset) { - ASTDeclReader::attachLatestDecl(CanonDecl, FirstLocal); - return; - } - - // Load the list of other redeclarations from this module file. - ModuleFile *M = getOwningModuleFile(FirstLocal); - assert(M && "imported decl from no module file"); - - llvm::BitstreamCursor &Cursor = M->DeclsCursor; - SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(LocalOffset); - - RecordData Record; - unsigned Code = Cursor.ReadCode(); - unsigned RecCode = Cursor.readRecord(Code, Record); - (void)RecCode; - assert(RecCode == LOCAL_REDECLARATIONS && "expected LOCAL_REDECLARATIONS record!"); - - // FIXME: We have several different dispatches on decl kind here; maybe - // we should instead generate one loop per kind and dispatch up-front? - Decl *MostRecent = FirstLocal; - for (unsigned I = 0, N = Record.size(); I != N; ++I) { - auto *D = GetLocalDecl(*M, Record[N - I - 1]); - ASTDeclReader::attachPreviousDecl(*this, D, MostRecent, CanonDecl); - MostRecent = D; - } - ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent); -} - -namespace { - - /// Given an ObjC interface, goes through the modules and links to the - /// interface all the categories for it. - class ObjCCategoriesVisitor { - ASTReader &Reader; - ObjCInterfaceDecl *Interface; - llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized; - ObjCCategoryDecl *Tail = nullptr; - llvm::DenseMap<DeclarationName, ObjCCategoryDecl *> NameCategoryMap; - serialization::GlobalDeclID InterfaceID; - unsigned PreviousGeneration; - - void add(ObjCCategoryDecl *Cat) { - // Only process each category once. - if (!Deserialized.erase(Cat)) - 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 - Interface->setCategoryListRaw(Cat); - Tail = Cat; - } - - public: - ObjCCategoriesVisitor(ASTReader &Reader, - ObjCInterfaceDecl *Interface, - llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized, - serialization::GlobalDeclID InterfaceID, - unsigned PreviousGeneration) - : Reader(Reader), Interface(Interface), Deserialized(Deserialized), - InterfaceID(InterfaceID), PreviousGeneration(PreviousGeneration) { - // Populate the name -> category map with the set of known categories. - for (auto *Cat : Interface->known_categories()) { - if (Cat->getDeclName()) - NameCategoryMap[Cat->getDeclName()] = Cat; - - // Keep track of the tail of the category list. - Tail = Cat; - } - } - - bool operator()(ModuleFile &M) { - // 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; - - // Perform a binary search to find the local redeclarations for this - // declaration (if any). - const ObjCCategoriesInfo Compare = { LocalID, 0 }; - const ObjCCategoriesInfo *Result - = std::lower_bound(M.ObjCCategoriesMap, - M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap, - Compare); - 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); - } - - // 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; - } - }; - -} // namespace - -void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID, - ObjCInterfaceDecl *D, - unsigned PreviousGeneration) { - ObjCCategoriesVisitor Visitor(*this, D, CategoriesDeserialized, ID, - PreviousGeneration); - ModuleMgr.visit(Visitor); -} - -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); - } -} - -void ASTDeclReader::UpdateDecl(Decl *D, - llvm::SmallVectorImpl<serialization::DeclID> &PendingLazySpecializationIDs) { - while (Record.getIdx() < Record.size()) { - switch ((DeclUpdateKind)Record.readInt()) { - case UPD_CXX_ADDED_IMPLICIT_MEMBER: { - auto *RD = cast<CXXRecordDecl>(D); - // FIXME: If we also have an update record for instantiating the - // definition of D, we need that to happen before we get here. - Decl *MD = Record.readDecl(); - assert(MD && "couldn't read decl from update record"); - // FIXME: We should call addHiddenDecl instead, to add the member - // to its DeclContext. - RD->addedMember(MD); - break; - } - - case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: - // It will be added to the template's lazy specialization set. - PendingLazySpecializationIDs.push_back(ReadDeclID()); - break; - - case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: { - auto *Anon = ReadDeclAs<NamespaceDecl>(); - - // Each module has its own anonymous namespace, which is disjoint from - // any other module's anonymous namespaces, so don't attach the anonymous - // namespace at all. - if (!Record.isModule()) { - if (auto *TU = dyn_cast<TranslationUnitDecl>(D)) - TU->setAnonymousNamespace(Anon); - else - cast<NamespaceDecl>(D)->setAnonymousNamespace(Anon); - } - break; - } - - case UPD_CXX_ADDED_VAR_DEFINITION: { - auto *VD = cast<VarDecl>(D); - VD->NonParmVarDeclBits.IsInline = Record.readInt(); - VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt(); - uint64_t Val = Record.readInt(); - if (Val && !VD->getInit()) { - VD->setInit(Record.readExpr()); - if (Val > 1) { // IsInitKnownICE = 1, IsInitNotICE = 2, IsInitICE = 3 - EvaluatedStmt *Eval = VD->ensureEvaluatedStmt(); - Eval->CheckedICE = true; - Eval->IsICE = Val == 3; - } - } - break; - } - - case UPD_CXX_POINT_OF_INSTANTIATION: { - SourceLocation POI = Record.readSourceLocation(); - if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D)) { - VTSD->setPointOfInstantiation(POI); - } else if (auto *VD = dyn_cast<VarDecl>(D)) { - VD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); - } else { - auto *FD = cast<FunctionDecl>(D); - if (auto *FTSInfo = FD->TemplateOrSpecialization - .dyn_cast<FunctionTemplateSpecializationInfo *>()) - FTSInfo->setPointOfInstantiation(POI); - else - FD->TemplateOrSpecialization.get<MemberSpecializationInfo *>() - ->setPointOfInstantiation(POI); - } - break; - } - - case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: { - auto *Param = cast<ParmVarDecl>(D); - - // We have to read the default argument regardless of whether we use it - // so that hypothetical further update records aren't messed up. - // TODO: Add a function to skip over the next expr record. - auto *DefaultArg = Record.readExpr(); - - // Only apply the update if the parameter still has an uninstantiated - // default argument. - if (Param->hasUninstantiatedDefaultArg()) - Param->setDefaultArg(DefaultArg); - break; - } - - case UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER: { - auto *FD = cast<FieldDecl>(D); - auto *DefaultInit = Record.readExpr(); - - // Only apply the update if the field still has an uninstantiated - // default member initializer. - if (FD->hasInClassInitializer() && !FD->getInClassInitializer()) { - if (DefaultInit) - FD->setInClassInitializer(DefaultInit); - else - // Instantiation failed. We can get here if we serialized an AST for - // an invalid program. - FD->removeInClassInitializer(); - } - break; - } - - case UPD_CXX_ADDED_FUNCTION_DEFINITION: { - auto *FD = cast<FunctionDecl>(D); - if (Reader.PendingBodies[FD]) { - // FIXME: Maybe check for ODR violations. - // It's safe to stop now because this update record is always last. - return; - } - - if (Record.readInt()) { - // Maintain AST consistency: any later redeclarations of this function - // are inline if this one is. (We might have merged another declaration - // into this one.) - forAllLaterRedecls(FD, [](FunctionDecl *FD) { - FD->setImplicitlyInline(); - }); - } - FD->setInnerLocStart(ReadSourceLocation()); - ReadFunctionDefinition(FD); - assert(Record.getIdx() == Record.size() && "lazy body must be last"); - break; - } - - case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: { - auto *RD = cast<CXXRecordDecl>(D); - auto *OldDD = RD->getCanonicalDecl()->DefinitionData; - bool HadRealDefinition = - OldDD && (OldDD->Definition != RD || - !Reader.PendingFakeDefinitionData.count(OldDD)); - RD->setParamDestroyedInCallee(Record.readInt()); - RD->setArgPassingRestrictions( - (RecordDecl::ArgPassingKind)Record.readInt()); - ReadCXXRecordDefinition(RD, /*Update*/true); - - // Visible update is handled separately. - uint64_t LexicalOffset = ReadLocalOffset(); - if (!HadRealDefinition && LexicalOffset) { - Record.readLexicalDeclContextStorage(LexicalOffset, RD); - Reader.PendingFakeDefinitionData.erase(OldDD); - } - - auto TSK = (TemplateSpecializationKind)Record.readInt(); - SourceLocation POI = ReadSourceLocation(); - if (MemberSpecializationInfo *MSInfo = - RD->getMemberSpecializationInfo()) { - MSInfo->setTemplateSpecializationKind(TSK); - MSInfo->setPointOfInstantiation(POI); - } else { - auto *Spec = cast<ClassTemplateSpecializationDecl>(RD); - Spec->setTemplateSpecializationKind(TSK); - Spec->setPointOfInstantiation(POI); - - if (Record.readInt()) { - auto *PartialSpec = - ReadDeclAs<ClassTemplatePartialSpecializationDecl>(); - SmallVector<TemplateArgument, 8> TemplArgs; - Record.readTemplateArgumentList(TemplArgs); - auto *TemplArgList = TemplateArgumentList::CreateCopy( - Reader.getContext(), TemplArgs); - - // FIXME: If we already have a partial specialization set, - // check that it matches. - if (!Spec->getSpecializedTemplateOrPartial() - .is<ClassTemplatePartialSpecializationDecl *>()) - Spec->setInstantiationOf(PartialSpec, TemplArgList); - } - } - - RD->setTagKind((TagTypeKind)Record.readInt()); - RD->setLocation(ReadSourceLocation()); - RD->setLocStart(ReadSourceLocation()); - RD->setBraceRange(ReadSourceRange()); - - if (Record.readInt()) { - AttrVec Attrs; - Record.readAttributes(Attrs); - // If the declaration already has attributes, we assume that some other - // AST file already loaded them. - if (!D->hasAttrs()) - D->setAttrsImpl(Attrs, Reader.getContext()); - } - break; - } - - case UPD_CXX_RESOLVED_DTOR_DELETE: { - // Set the 'operator delete' directly to avoid emitting another update - // record. - auto *Del = ReadDeclAs<FunctionDecl>(); - auto *First = cast<CXXDestructorDecl>(D->getCanonicalDecl()); - auto *ThisArg = Record.readExpr(); - // FIXME: Check consistency if we have an old and new operator delete. - if (!First->OperatorDelete) { - First->OperatorDelete = Del; - First->OperatorDeleteThisArg = ThisArg; - } - break; - } - - case UPD_CXX_RESOLVED_EXCEPTION_SPEC: { - FunctionProtoType::ExceptionSpecInfo ESI; - SmallVector<QualType, 8> ExceptionStorage; - Record.readExceptionSpec(ExceptionStorage, ESI); - - // 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())) { - FD->setType(Reader.getContext().getFunctionType( - FPT->getReturnType(), FPT->getParamTypes(), - FPT->getExtProtoInfo().withExceptionSpec(ESI))); - - // 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)); - } - break; - } - - case UPD_CXX_DEDUCED_RETURN_TYPE: { - auto *FD = cast<FunctionDecl>(D); - QualType DeducedResultType = Record.readType(); - Reader.PendingDeducedTypeUpdates.insert( - {FD->getCanonicalDecl(), DeducedResultType}); - break; - } - - case UPD_DECL_MARKED_USED: - // Maintain AST consistency: any later redeclarations are used too. - D->markUsed(Reader.getContext()); - break; - - case UPD_MANGLING_NUMBER: - Reader.getContext().setManglingNumber(cast<NamedDecl>(D), - Record.readInt()); - break; - - case UPD_STATIC_LOCAL_NUMBER: - Reader.getContext().setStaticLocalNumber(cast<VarDecl>(D), - Record.readInt()); - break; - - case UPD_DECL_MARKED_OPENMP_THREADPRIVATE: - D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(Reader.getContext(), - ReadSourceRange())); - break; - - case UPD_DECL_EXPORTED: { - unsigned SubmoduleID = readSubmoduleID(); - auto *Exported = cast<NamedDecl>(D); - Module *Owner = SubmoduleID ? Reader.getSubmodule(SubmoduleID) : nullptr; - Reader.getContext().mergeDefinitionIntoModule(Exported, Owner); - Reader.PendingMergedDefinitionsToDeduplicate.insert(Exported); - break; - } - - case UPD_DECL_MARKED_OPENMP_DECLARETARGET: - D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit( - Reader.getContext(), - static_cast<OMPDeclareTargetDeclAttr::MapTypeTy>(Record.readInt()), - ReadSourceRange())); - break; - - case UPD_ADDED_ATTR_TO_RECORD: - AttrVec Attrs; - Record.readAttributes(Attrs); - assert(Attrs.size() == 1); - D->addAttr(Attrs[0]); - break; - } - } -} diff --git a/gnu/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h b/gnu/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h deleted file mode 100644 index 37a929907dc..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h +++ /dev/null @@ -1,293 +0,0 @@ -//===- ASTReaderInternals.h - AST Reader Internals --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides internal definitions used in the AST reader. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H -#define LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H - -#include "MultiOnDiskHashTable.h" -#include "clang/AST/DeclarationName.h" -#include "clang/Basic/LLVM.h" -#include "clang/Serialization/ASTBitCodes.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/OnDiskHashTable.h" -#include <ctime> -#include <utility> - -namespace clang { - -class ASTReader; -class FileEntry; -struct HeaderFileInfo; -class HeaderSearch; -class IdentifierTable; -class ObjCMethodDecl; - -namespace serialization { - -class ModuleFile; - -namespace reader { - -/// Class that performs name lookup into a DeclContext stored -/// in an AST file. -class ASTDeclContextNameLookupTrait { - ASTReader &Reader; - ModuleFile &F; - -public: - // Maximum number of lookup tables we allow before condensing the tables. - static const int MaxTables = 4; - - /// The lookup result is a list of global declaration IDs. - using data_type = SmallVector<DeclID, 4>; - - struct data_type_builder { - data_type &Data; - llvm::DenseSet<DeclID> Found; - - data_type_builder(data_type &D) : Data(D) {} - - void insert(DeclID ID) { - // Just use a linear scan unless we have more than a few IDs. - if (Found.empty() && !Data.empty()) { - if (Data.size() <= 4) { - for (auto I : Found) - if (I == ID) - return; - Data.push_back(ID); - return; - } - - // Switch to tracking found IDs in the set. - Found.insert(Data.begin(), Data.end()); - } - - if (Found.insert(ID).second) - Data.push_back(ID); - } - }; - using hash_value_type = unsigned; - using offset_type = unsigned; - using file_type = ModuleFile *; - - using external_key_type = DeclarationName; - using internal_key_type = DeclarationNameKey; - - explicit ASTDeclContextNameLookupTrait(ASTReader &Reader, ModuleFile &F) - : Reader(Reader), F(F) {} - - static bool EqualKey(const internal_key_type &a, const internal_key_type &b) { - return a == b; - } - - static hash_value_type ComputeHash(const internal_key_type &Key) { - return Key.getHash(); - } - - static internal_key_type GetInternalKey(const external_key_type &Name) { - return Name; - } - - static std::pair<unsigned, unsigned> - ReadKeyDataLength(const unsigned char *&d); - - internal_key_type ReadKey(const unsigned char *d, unsigned); - - void ReadDataInto(internal_key_type, const unsigned char *d, - unsigned DataLen, data_type_builder &Val); - - static void MergeDataInto(const data_type &From, data_type_builder &To) { - To.Data.reserve(To.Data.size() + From.size()); - for (DeclID ID : From) - To.insert(ID); - } - - file_type ReadFileRef(const unsigned char *&d); -}; - -struct DeclContextLookupTable { - MultiOnDiskHashTable<ASTDeclContextNameLookupTrait> Table; -}; - -/// Base class for the trait describing the on-disk hash table for the -/// identifiers in an AST file. -/// -/// This class is not useful by itself; rather, it provides common -/// functionality for accessing the on-disk hash table of identifiers -/// in an AST file. Different subclasses customize that functionality -/// based on what information they are interested in. Those subclasses -/// must provide the \c data_type type and the ReadData operation, only. -class ASTIdentifierLookupTraitBase { -public: - using external_key_type = StringRef; - using internal_key_type = StringRef; - using hash_value_type = unsigned; - using offset_type = unsigned; - - static bool EqualKey(const internal_key_type& a, const internal_key_type& b) { - return a == b; - } - - static hash_value_type ComputeHash(const internal_key_type& a); - - static std::pair<unsigned, unsigned> - ReadKeyDataLength(const unsigned char*& d); - - // This hopefully will just get inlined and removed by the optimizer. - static const internal_key_type& - GetInternalKey(const external_key_type& x) { return x; } - - // This hopefully will just get inlined and removed by the optimizer. - static const external_key_type& - GetExternalKey(const internal_key_type& x) { return x; } - - static internal_key_type ReadKey(const unsigned char* d, unsigned n); -}; - -/// Class that performs lookup for an identifier stored in an AST file. -class ASTIdentifierLookupTrait : public ASTIdentifierLookupTraitBase { - ASTReader &Reader; - ModuleFile &F; - - // If we know the IdentifierInfo in advance, it is here and we will - // not build a new one. Used when deserializing information about an - // identifier that was constructed before the AST file was read. - IdentifierInfo *KnownII; - -public: - using data_type = IdentifierInfo *; - - ASTIdentifierLookupTrait(ASTReader &Reader, ModuleFile &F, - IdentifierInfo *II = nullptr) - : Reader(Reader), F(F), KnownII(II) {} - - data_type ReadData(const internal_key_type& k, - const unsigned char* d, - unsigned DataLen); - - IdentID ReadIdentifierID(const unsigned char *d); - - ASTReader &getReader() const { return Reader; } -}; - -/// The on-disk hash table used to contain information about -/// all of the identifiers in the program. -using ASTIdentifierLookupTable = - llvm::OnDiskIterableChainedHashTable<ASTIdentifierLookupTrait>; - -/// Class that performs lookup for a selector's entries in the global -/// method pool stored in an AST file. -class ASTSelectorLookupTrait { - ASTReader &Reader; - ModuleFile &F; - -public: - struct data_type { - SelectorID ID; - unsigned InstanceBits; - unsigned FactoryBits; - bool InstanceHasMoreThanOneDecl; - bool FactoryHasMoreThanOneDecl; - SmallVector<ObjCMethodDecl *, 2> Instance; - SmallVector<ObjCMethodDecl *, 2> Factory; - }; - - using external_key_type = Selector; - using internal_key_type = external_key_type; - using hash_value_type = unsigned; - using offset_type = unsigned; - - ASTSelectorLookupTrait(ASTReader &Reader, ModuleFile &F) - : Reader(Reader), F(F) {} - - static bool EqualKey(const internal_key_type& a, - const internal_key_type& b) { - return a == b; - } - - static hash_value_type ComputeHash(Selector Sel); - - static const internal_key_type& - GetInternalKey(const external_key_type& x) { return x; } - - static std::pair<unsigned, unsigned> - ReadKeyDataLength(const unsigned char*& d); - - internal_key_type ReadKey(const unsigned char* d, unsigned); - data_type ReadData(Selector, const unsigned char* d, unsigned DataLen); -}; - -/// The on-disk hash table used for the global method pool. -using ASTSelectorLookupTable = - llvm::OnDiskChainedHashTable<ASTSelectorLookupTrait>; - -/// Trait class used to search the on-disk hash table containing all of -/// the header search information. -/// -/// The on-disk hash table contains a mapping from each header path to -/// information about that header (how many times it has been included, its -/// controlling macro, etc.). Note that we actually hash based on the size -/// and mtime, and support "deep" comparisons of file names based on current -/// inode numbers, so that the search can cope with non-normalized path names -/// and symlinks. -class HeaderFileInfoTrait { - ASTReader &Reader; - ModuleFile &M; - HeaderSearch *HS; - const char *FrameworkStrings; - -public: - using external_key_type = const FileEntry *; - - struct internal_key_type { - off_t Size; - time_t ModTime; - StringRef Filename; - bool Imported; - }; - - using internal_key_ref = const internal_key_type &; - - using data_type = HeaderFileInfo; - using hash_value_type = unsigned; - using offset_type = unsigned; - - HeaderFileInfoTrait(ASTReader &Reader, ModuleFile &M, HeaderSearch *HS, - const char *FrameworkStrings) - : Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings) {} - - static hash_value_type ComputeHash(internal_key_ref ikey); - internal_key_type GetInternalKey(const FileEntry *FE); - bool EqualKey(internal_key_ref a, internal_key_ref b); - - static std::pair<unsigned, unsigned> - ReadKeyDataLength(const unsigned char*& d); - - static internal_key_type ReadKey(const unsigned char *d, unsigned); - - data_type ReadData(internal_key_ref,const unsigned char *d, unsigned DataLen); -}; - -/// The on-disk hash table used for known header files. -using HeaderFileInfoLookupTable = - llvm::OnDiskChainedHashTable<HeaderFileInfoTrait>; - -} // namespace reader - -} // namespace serialization - -} // namespace clang - -#endif // LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H diff --git a/gnu/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp b/gnu/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp deleted file mode 100644 index 60abea95bfa..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp +++ /dev/null @@ -1,3418 +0,0 @@ -//===- ASTReaderStmt.cpp - Stmt/Expr Deserialization ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Statement/expression deserialization. This implements the -// ASTReader::ReadStmt method. -// -//===----------------------------------------------------------------------===// - -#include "clang/Serialization/ASTReader.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/AttrIterator.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclAccessPair.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclGroup.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/DeclarationName.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/ExprObjC.h" -#include "clang/AST/ExprOpenMP.h" -#include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/OpenMPClause.h" -#include "clang/AST/OperationKinds.h" -#include "clang/AST/Stmt.h" -#include "clang/AST/StmtCXX.h" -#include "clang/AST/StmtObjC.h" -#include "clang/AST/StmtOpenMP.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/AST/TemplateBase.h" -#include "clang/AST/Type.h" -#include "clang/AST/UnresolvedSet.h" -#include "clang/Basic/CapturedStmt.h" -#include "clang/Basic/ExpressionTraits.h" -#include "clang/Basic/LLVM.h" -#include "clang/Basic/Lambda.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/OpenMPKinds.h" -#include "clang/Basic/OperatorKinds.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Basic/Specifiers.h" -#include "clang/Basic/TypeTraits.h" -#include "clang/Lex/Token.h" -#include "clang/Serialization/ASTBitCodes.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Bitcode/BitstreamReader.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include <algorithm> -#include <cassert> -#include <cstdint> -#include <string> - -using namespace clang; -using namespace serialization; - -namespace clang { - - class ASTStmtReader : public StmtVisitor<ASTStmtReader> { - friend class OMPClauseReader; - - ASTRecordReader &Record; - llvm::BitstreamCursor &DeclsCursor; - - SourceLocation ReadSourceLocation() { - return Record.readSourceLocation(); - } - - SourceRange ReadSourceRange() { - return Record.readSourceRange(); - } - - std::string ReadString() { - return Record.readString(); - } - - TypeSourceInfo *GetTypeSourceInfo() { - return Record.getTypeSourceInfo(); - } - - Decl *ReadDecl() { - return Record.readDecl(); - } - - template<typename T> - T *ReadDeclAs() { - return Record.readDeclAs<T>(); - } - - void ReadDeclarationNameLoc(DeclarationNameLoc &DNLoc, - DeclarationName Name) { - Record.readDeclarationNameLoc(DNLoc, Name); - } - - void ReadDeclarationNameInfo(DeclarationNameInfo &NameInfo) { - Record.readDeclarationNameInfo(NameInfo); - } - - public: - ASTStmtReader(ASTRecordReader &Record, llvm::BitstreamCursor &Cursor) - : Record(Record), DeclsCursor(Cursor) {} - - /// The number of record fields required for the Stmt class - /// itself. - static const unsigned NumStmtFields = 0; - - /// The number of record fields required for the Expr class - /// itself. - static const unsigned NumExprFields = NumStmtFields + 7; - - /// Read and initialize a ExplicitTemplateArgumentList structure. - void ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args, - TemplateArgumentLoc *ArgsLocArray, - unsigned NumTemplateArgs); - - /// Read and initialize a ExplicitTemplateArgumentList structure. - void ReadExplicitTemplateArgumentList(ASTTemplateArgumentListInfo &ArgList, - unsigned NumTemplateArgs); - - void VisitStmt(Stmt *S); -#define STMT(Type, Base) \ - void Visit##Type(Type *); -#include "clang/AST/StmtNodes.inc" - }; - -} // namespace clang - -void ASTStmtReader::ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args, - TemplateArgumentLoc *ArgsLocArray, - unsigned NumTemplateArgs) { - SourceLocation TemplateKWLoc = ReadSourceLocation(); - TemplateArgumentListInfo ArgInfo; - ArgInfo.setLAngleLoc(ReadSourceLocation()); - ArgInfo.setRAngleLoc(ReadSourceLocation()); - for (unsigned i = 0; i != NumTemplateArgs; ++i) - ArgInfo.addArgument(Record.readTemplateArgumentLoc()); - Args.initializeFrom(TemplateKWLoc, ArgInfo, ArgsLocArray); -} - -void ASTStmtReader::VisitStmt(Stmt *S) { - assert(Record.getIdx() == NumStmtFields && "Incorrect statement field count"); -} - -void ASTStmtReader::VisitNullStmt(NullStmt *S) { - VisitStmt(S); - S->setSemiLoc(ReadSourceLocation()); - S->NullStmtBits.HasLeadingEmptyMacro = Record.readInt(); -} - -void ASTStmtReader::VisitCompoundStmt(CompoundStmt *S) { - VisitStmt(S); - SmallVector<Stmt *, 16> Stmts; - unsigned NumStmts = Record.readInt(); - while (NumStmts--) - Stmts.push_back(Record.readSubStmt()); - S->setStmts(Stmts); - S->CompoundStmtBits.LBraceLoc = ReadSourceLocation(); - S->RBraceLoc = ReadSourceLocation(); -} - -void ASTStmtReader::VisitSwitchCase(SwitchCase *S) { - VisitStmt(S); - Record.recordSwitchCaseID(S, Record.readInt()); - S->setKeywordLoc(ReadSourceLocation()); - S->setColonLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitCaseStmt(CaseStmt *S) { - VisitSwitchCase(S); - bool CaseStmtIsGNURange = Record.readInt(); - S->setLHS(Record.readSubExpr()); - S->setSubStmt(Record.readSubStmt()); - if (CaseStmtIsGNURange) { - S->setRHS(Record.readSubExpr()); - S->setEllipsisLoc(ReadSourceLocation()); - } -} - -void ASTStmtReader::VisitDefaultStmt(DefaultStmt *S) { - VisitSwitchCase(S); - S->setSubStmt(Record.readSubStmt()); -} - -void ASTStmtReader::VisitLabelStmt(LabelStmt *S) { - VisitStmt(S); - auto *LD = ReadDeclAs<LabelDecl>(); - LD->setStmt(S); - S->setDecl(LD); - S->setSubStmt(Record.readSubStmt()); - S->setIdentLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) { - VisitStmt(S); - // NumAttrs in AttributedStmt is set when creating an empty - // AttributedStmt in AttributedStmt::CreateEmpty, since it is needed - // to allocate the right amount of space for the trailing Attr *. - uint64_t NumAttrs = Record.readInt(); - AttrVec Attrs; - Record.readAttributes(Attrs); - (void)NumAttrs; - assert(NumAttrs == S->AttributedStmtBits.NumAttrs); - assert(NumAttrs == Attrs.size()); - std::copy(Attrs.begin(), Attrs.end(), S->getAttrArrayPtr()); - S->SubStmt = Record.readSubStmt(); - S->AttributedStmtBits.AttrLoc = ReadSourceLocation(); -} - -void ASTStmtReader::VisitIfStmt(IfStmt *S) { - VisitStmt(S); - - S->setConstexpr(Record.readInt()); - bool HasElse = Record.readInt(); - bool HasVar = Record.readInt(); - bool HasInit = Record.readInt(); - - S->setCond(Record.readSubExpr()); - S->setThen(Record.readSubStmt()); - if (HasElse) - S->setElse(Record.readSubStmt()); - if (HasVar) - S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>()); - if (HasInit) - S->setInit(Record.readSubStmt()); - - S->setIfLoc(ReadSourceLocation()); - if (HasElse) - S->setElseLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) { - VisitStmt(S); - - bool HasInit = Record.readInt(); - bool HasVar = Record.readInt(); - bool AllEnumCasesCovered = Record.readInt(); - if (AllEnumCasesCovered) - S->setAllEnumCasesCovered(); - - S->setCond(Record.readSubExpr()); - S->setBody(Record.readSubStmt()); - if (HasInit) - S->setInit(Record.readSubStmt()); - if (HasVar) - S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>()); - - S->setSwitchLoc(ReadSourceLocation()); - - SwitchCase *PrevSC = nullptr; - for (auto E = Record.size(); Record.getIdx() != E; ) { - SwitchCase *SC = Record.getSwitchCaseWithID(Record.readInt()); - if (PrevSC) - PrevSC->setNextSwitchCase(SC); - else - S->setSwitchCaseList(SC); - - PrevSC = SC; - } -} - -void ASTStmtReader::VisitWhileStmt(WhileStmt *S) { - VisitStmt(S); - - bool HasVar = Record.readInt(); - - S->setCond(Record.readSubExpr()); - S->setBody(Record.readSubStmt()); - if (HasVar) - S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>()); - - S->setWhileLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitDoStmt(DoStmt *S) { - VisitStmt(S); - S->setCond(Record.readSubExpr()); - S->setBody(Record.readSubStmt()); - S->setDoLoc(ReadSourceLocation()); - S->setWhileLoc(ReadSourceLocation()); - S->setRParenLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitForStmt(ForStmt *S) { - VisitStmt(S); - S->setInit(Record.readSubStmt()); - S->setCond(Record.readSubExpr()); - S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>()); - S->setInc(Record.readSubExpr()); - S->setBody(Record.readSubStmt()); - S->setForLoc(ReadSourceLocation()); - S->setLParenLoc(ReadSourceLocation()); - S->setRParenLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitGotoStmt(GotoStmt *S) { - VisitStmt(S); - S->setLabel(ReadDeclAs<LabelDecl>()); - S->setGotoLoc(ReadSourceLocation()); - S->setLabelLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitIndirectGotoStmt(IndirectGotoStmt *S) { - VisitStmt(S); - S->setGotoLoc(ReadSourceLocation()); - S->setStarLoc(ReadSourceLocation()); - S->setTarget(Record.readSubExpr()); -} - -void ASTStmtReader::VisitContinueStmt(ContinueStmt *S) { - VisitStmt(S); - S->setContinueLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitBreakStmt(BreakStmt *S) { - VisitStmt(S); - S->setBreakLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitReturnStmt(ReturnStmt *S) { - VisitStmt(S); - - bool HasNRVOCandidate = Record.readInt(); - - S->setRetValue(Record.readSubExpr()); - if (HasNRVOCandidate) - S->setNRVOCandidate(ReadDeclAs<VarDecl>()); - - S->setReturnLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitDeclStmt(DeclStmt *S) { - VisitStmt(S); - S->setStartLoc(ReadSourceLocation()); - S->setEndLoc(ReadSourceLocation()); - - if (Record.size() - Record.getIdx() == 1) { - // Single declaration - S->setDeclGroup(DeclGroupRef(ReadDecl())); - } else { - SmallVector<Decl *, 16> Decls; - int N = Record.size() - Record.getIdx(); - Decls.reserve(N); - for (int I = 0; I < N; ++I) - Decls.push_back(ReadDecl()); - S->setDeclGroup(DeclGroupRef(DeclGroup::Create(Record.getContext(), - Decls.data(), - Decls.size()))); - } -} - -void ASTStmtReader::VisitAsmStmt(AsmStmt *S) { - VisitStmt(S); - S->NumOutputs = Record.readInt(); - S->NumInputs = Record.readInt(); - S->NumClobbers = Record.readInt(); - S->setAsmLoc(ReadSourceLocation()); - S->setVolatile(Record.readInt()); - S->setSimple(Record.readInt()); -} - -void ASTStmtReader::VisitGCCAsmStmt(GCCAsmStmt *S) { - VisitAsmStmt(S); - S->setRParenLoc(ReadSourceLocation()); - S->setAsmString(cast_or_null<StringLiteral>(Record.readSubStmt())); - - unsigned NumOutputs = S->getNumOutputs(); - unsigned NumInputs = S->getNumInputs(); - unsigned NumClobbers = S->getNumClobbers(); - - // Outputs and inputs - SmallVector<IdentifierInfo *, 16> Names; - SmallVector<StringLiteral*, 16> Constraints; - SmallVector<Stmt*, 16> Exprs; - for (unsigned I = 0, N = NumOutputs + NumInputs; I != N; ++I) { - Names.push_back(Record.getIdentifierInfo()); - Constraints.push_back(cast_or_null<StringLiteral>(Record.readSubStmt())); - Exprs.push_back(Record.readSubStmt()); - } - - // Constraints - SmallVector<StringLiteral*, 16> Clobbers; - for (unsigned I = 0; I != NumClobbers; ++I) - Clobbers.push_back(cast_or_null<StringLiteral>(Record.readSubStmt())); - - S->setOutputsAndInputsAndClobbers(Record.getContext(), - Names.data(), Constraints.data(), - Exprs.data(), NumOutputs, NumInputs, - Clobbers.data(), NumClobbers); -} - -void ASTStmtReader::VisitMSAsmStmt(MSAsmStmt *S) { - VisitAsmStmt(S); - S->LBraceLoc = ReadSourceLocation(); - S->EndLoc = ReadSourceLocation(); - S->NumAsmToks = Record.readInt(); - std::string AsmStr = ReadString(); - - // Read the tokens. - SmallVector<Token, 16> AsmToks; - AsmToks.reserve(S->NumAsmToks); - for (unsigned i = 0, e = S->NumAsmToks; i != e; ++i) { - AsmToks.push_back(Record.readToken()); - } - - // The calls to reserve() for the FooData vectors are mandatory to - // prevent dead StringRefs in the Foo vectors. - - // Read the clobbers. - SmallVector<std::string, 16> ClobbersData; - SmallVector<StringRef, 16> Clobbers; - ClobbersData.reserve(S->NumClobbers); - Clobbers.reserve(S->NumClobbers); - for (unsigned i = 0, e = S->NumClobbers; i != e; ++i) { - ClobbersData.push_back(ReadString()); - Clobbers.push_back(ClobbersData.back()); - } - - // Read the operands. - unsigned NumOperands = S->NumOutputs + S->NumInputs; - SmallVector<Expr*, 16> Exprs; - SmallVector<std::string, 16> ConstraintsData; - SmallVector<StringRef, 16> Constraints; - Exprs.reserve(NumOperands); - ConstraintsData.reserve(NumOperands); - Constraints.reserve(NumOperands); - for (unsigned i = 0; i != NumOperands; ++i) { - Exprs.push_back(cast<Expr>(Record.readSubStmt())); - ConstraintsData.push_back(ReadString()); - Constraints.push_back(ConstraintsData.back()); - } - - S->initialize(Record.getContext(), AsmStr, AsmToks, - Constraints, Exprs, Clobbers); -} - -void ASTStmtReader::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) { - VisitStmt(S); - assert(Record.peekInt() == S->NumParams); - Record.skipInts(1); - auto *StoredStmts = S->getStoredStmts(); - for (unsigned i = 0; - i < CoroutineBodyStmt::SubStmt::FirstParamMove + S->NumParams; ++i) - StoredStmts[i] = Record.readSubStmt(); -} - -void ASTStmtReader::VisitCoreturnStmt(CoreturnStmt *S) { - VisitStmt(S); - S->CoreturnLoc = Record.readSourceLocation(); - for (auto &SubStmt: S->SubStmts) - SubStmt = Record.readSubStmt(); - S->IsImplicit = Record.readInt() != 0; -} - -void ASTStmtReader::VisitCoawaitExpr(CoawaitExpr *E) { - VisitExpr(E); - E->KeywordLoc = ReadSourceLocation(); - for (auto &SubExpr: E->SubExprs) - SubExpr = Record.readSubStmt(); - E->OpaqueValue = cast_or_null<OpaqueValueExpr>(Record.readSubStmt()); - E->setIsImplicit(Record.readInt() != 0); -} - -void ASTStmtReader::VisitCoyieldExpr(CoyieldExpr *E) { - VisitExpr(E); - E->KeywordLoc = ReadSourceLocation(); - for (auto &SubExpr: E->SubExprs) - SubExpr = Record.readSubStmt(); - E->OpaqueValue = cast_or_null<OpaqueValueExpr>(Record.readSubStmt()); -} - -void ASTStmtReader::VisitDependentCoawaitExpr(DependentCoawaitExpr *E) { - VisitExpr(E); - E->KeywordLoc = ReadSourceLocation(); - for (auto &SubExpr: E->SubExprs) - SubExpr = Record.readSubStmt(); -} - -void ASTStmtReader::VisitCapturedStmt(CapturedStmt *S) { - VisitStmt(S); - Record.skipInts(1); - S->setCapturedDecl(ReadDeclAs<CapturedDecl>()); - S->setCapturedRegionKind(static_cast<CapturedRegionKind>(Record.readInt())); - S->setCapturedRecordDecl(ReadDeclAs<RecordDecl>()); - - // Capture inits - for (CapturedStmt::capture_init_iterator I = S->capture_init_begin(), - E = S->capture_init_end(); - I != E; ++I) - *I = Record.readSubExpr(); - - // Body - S->setCapturedStmt(Record.readSubStmt()); - S->getCapturedDecl()->setBody(S->getCapturedStmt()); - - // Captures - for (auto &I : S->captures()) { - I.VarAndKind.setPointer(ReadDeclAs<VarDecl>()); - I.VarAndKind.setInt( - static_cast<CapturedStmt::VariableCaptureKind>(Record.readInt())); - I.Loc = ReadSourceLocation(); - } -} - -void ASTStmtReader::VisitExpr(Expr *E) { - VisitStmt(E); - E->setType(Record.readType()); - E->setTypeDependent(Record.readInt()); - E->setValueDependent(Record.readInt()); - E->setInstantiationDependent(Record.readInt()); - E->ExprBits.ContainsUnexpandedParameterPack = Record.readInt(); - E->setValueKind(static_cast<ExprValueKind>(Record.readInt())); - E->setObjectKind(static_cast<ExprObjectKind>(Record.readInt())); - assert(Record.getIdx() == NumExprFields && - "Incorrect expression field count"); -} - -void ASTStmtReader::VisitConstantExpr(ConstantExpr *E) { - VisitExpr(E); - E->setSubExpr(Record.readSubExpr()); -} - -void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) { - VisitExpr(E); - bool HasFunctionName = Record.readInt(); - E->PredefinedExprBits.HasFunctionName = HasFunctionName; - E->PredefinedExprBits.Kind = Record.readInt(); - E->setLocation(ReadSourceLocation()); - if (HasFunctionName) - E->setFunctionName(cast<StringLiteral>(Record.readSubExpr())); -} - -void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { - VisitExpr(E); - - E->DeclRefExprBits.HasQualifier = Record.readInt(); - E->DeclRefExprBits.HasFoundDecl = Record.readInt(); - E->DeclRefExprBits.HasTemplateKWAndArgsInfo = Record.readInt(); - E->DeclRefExprBits.HadMultipleCandidates = Record.readInt(); - E->DeclRefExprBits.RefersToEnclosingVariableOrCapture = Record.readInt(); - unsigned NumTemplateArgs = 0; - if (E->hasTemplateKWAndArgsInfo()) - NumTemplateArgs = Record.readInt(); - - if (E->hasQualifier()) - new (E->getTrailingObjects<NestedNameSpecifierLoc>()) - NestedNameSpecifierLoc(Record.readNestedNameSpecifierLoc()); - - if (E->hasFoundDecl()) - *E->getTrailingObjects<NamedDecl *>() = ReadDeclAs<NamedDecl>(); - - if (E->hasTemplateKWAndArgsInfo()) - ReadTemplateKWAndArgsInfo( - *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(), - E->getTrailingObjects<TemplateArgumentLoc>(), NumTemplateArgs); - - E->setDecl(ReadDeclAs<ValueDecl>()); - E->setLocation(ReadSourceLocation()); - ReadDeclarationNameLoc(E->DNLoc, E->getDecl()->getDeclName()); -} - -void ASTStmtReader::VisitIntegerLiteral(IntegerLiteral *E) { - VisitExpr(E); - E->setLocation(ReadSourceLocation()); - E->setValue(Record.getContext(), Record.readAPInt()); -} - -void ASTStmtReader::VisitFixedPointLiteral(FixedPointLiteral *E) { - VisitExpr(E); - E->setLocation(ReadSourceLocation()); - E->setValue(Record.getContext(), Record.readAPInt()); -} - -void ASTStmtReader::VisitFloatingLiteral(FloatingLiteral *E) { - VisitExpr(E); - E->setRawSemantics(static_cast<Stmt::APFloatSemantics>(Record.readInt())); - E->setExact(Record.readInt()); - E->setValue(Record.getContext(), Record.readAPFloat(E->getSemantics())); - E->setLocation(ReadSourceLocation()); -} - -void ASTStmtReader::VisitImaginaryLiteral(ImaginaryLiteral *E) { - VisitExpr(E); - E->setSubExpr(Record.readSubExpr()); -} - -void ASTStmtReader::VisitStringLiteral(StringLiteral *E) { - VisitExpr(E); - - // NumConcatenated, Length and CharByteWidth are set by the empty - // ctor since they are needed to allocate storage for the trailing objects. - unsigned NumConcatenated = Record.readInt(); - unsigned Length = Record.readInt(); - unsigned CharByteWidth = Record.readInt(); - assert((NumConcatenated == E->getNumConcatenated()) && - "Wrong number of concatenated tokens!"); - assert((Length == E->getLength()) && "Wrong Length!"); - assert((CharByteWidth == E->getCharByteWidth()) && "Wrong character width!"); - E->StringLiteralBits.Kind = Record.readInt(); - E->StringLiteralBits.IsPascal = Record.readInt(); - - // The character width is originally computed via mapCharByteWidth. - // Check that the deserialized character width is consistant with the result - // of calling mapCharByteWidth. - assert((CharByteWidth == - StringLiteral::mapCharByteWidth(Record.getContext().getTargetInfo(), - E->getKind())) && - "Wrong character width!"); - - // Deserialize the trailing array of SourceLocation. - for (unsigned I = 0; I < NumConcatenated; ++I) - E->setStrTokenLoc(I, ReadSourceLocation()); - - // Deserialize the trailing array of char holding the string data. - char *StrData = E->getStrDataAsChar(); - for (unsigned I = 0; I < Length * CharByteWidth; ++I) - StrData[I] = Record.readInt(); -} - -void ASTStmtReader::VisitCharacterLiteral(CharacterLiteral *E) { - VisitExpr(E); - E->setValue(Record.readInt()); - E->setLocation(ReadSourceLocation()); - E->setKind(static_cast<CharacterLiteral::CharacterKind>(Record.readInt())); -} - -void ASTStmtReader::VisitParenExpr(ParenExpr *E) { - VisitExpr(E); - E->setLParen(ReadSourceLocation()); - E->setRParen(ReadSourceLocation()); - E->setSubExpr(Record.readSubExpr()); -} - -void ASTStmtReader::VisitParenListExpr(ParenListExpr *E) { - VisitExpr(E); - unsigned NumExprs = Record.readInt(); - assert((NumExprs == E->getNumExprs()) && "Wrong NumExprs!"); - for (unsigned I = 0; I != NumExprs; ++I) - E->getTrailingObjects<Stmt *>()[I] = Record.readSubStmt(); - E->LParenLoc = ReadSourceLocation(); - E->RParenLoc = ReadSourceLocation(); -} - -void ASTStmtReader::VisitUnaryOperator(UnaryOperator *E) { - VisitExpr(E); - E->setSubExpr(Record.readSubExpr()); - E->setOpcode((UnaryOperator::Opcode)Record.readInt()); - E->setOperatorLoc(ReadSourceLocation()); - E->setCanOverflow(Record.readInt()); -} - -void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) { - VisitExpr(E); - assert(E->getNumComponents() == Record.peekInt()); - Record.skipInts(1); - assert(E->getNumExpressions() == Record.peekInt()); - Record.skipInts(1); - E->setOperatorLoc(ReadSourceLocation()); - E->setRParenLoc(ReadSourceLocation()); - E->setTypeSourceInfo(GetTypeSourceInfo()); - for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) { - auto Kind = static_cast<OffsetOfNode::Kind>(Record.readInt()); - SourceLocation Start = ReadSourceLocation(); - SourceLocation End = ReadSourceLocation(); - switch (Kind) { - case OffsetOfNode::Array: - E->setComponent(I, OffsetOfNode(Start, Record.readInt(), End)); - break; - - case OffsetOfNode::Field: - E->setComponent( - I, OffsetOfNode(Start, ReadDeclAs<FieldDecl>(), End)); - break; - - case OffsetOfNode::Identifier: - E->setComponent( - I, - OffsetOfNode(Start, Record.getIdentifierInfo(), End)); - break; - - case OffsetOfNode::Base: { - auto *Base = new (Record.getContext()) CXXBaseSpecifier(); - *Base = Record.readCXXBaseSpecifier(); - E->setComponent(I, OffsetOfNode(Base)); - break; - } - } - } - - for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I) - E->setIndexExpr(I, Record.readSubExpr()); -} - -void ASTStmtReader::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { - VisitExpr(E); - E->setKind(static_cast<UnaryExprOrTypeTrait>(Record.readInt())); - if (Record.peekInt() == 0) { - E->setArgument(Record.readSubExpr()); - Record.skipInts(1); - } else { - E->setArgument(GetTypeSourceInfo()); - } - E->setOperatorLoc(ReadSourceLocation()); - E->setRParenLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { - VisitExpr(E); - E->setLHS(Record.readSubExpr()); - E->setRHS(Record.readSubExpr()); - E->setRBracketLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitOMPArraySectionExpr(OMPArraySectionExpr *E) { - VisitExpr(E); - E->setBase(Record.readSubExpr()); - E->setLowerBound(Record.readSubExpr()); - E->setLength(Record.readSubExpr()); - E->setColonLoc(ReadSourceLocation()); - E->setRBracketLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitCallExpr(CallExpr *E) { - VisitExpr(E); - unsigned NumArgs = Record.readInt(); - assert((NumArgs == E->getNumArgs()) && "Wrong NumArgs!"); - E->setRParenLoc(ReadSourceLocation()); - E->setCallee(Record.readSubExpr()); - for (unsigned I = 0; I != NumArgs; ++I) - E->setArg(I, Record.readSubExpr()); - E->setADLCallKind(static_cast<CallExpr::ADLCallKind>(Record.readInt())); -} - -void ASTStmtReader::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { - VisitCallExpr(E); -} - -void ASTStmtReader::VisitMemberExpr(MemberExpr *E) { - // Don't call VisitExpr, this is fully initialized at creation. - assert(E->getStmtClass() == Stmt::MemberExprClass && - "It's a subclass, we must advance Idx!"); -} - -void ASTStmtReader::VisitObjCIsaExpr(ObjCIsaExpr *E) { - VisitExpr(E); - E->setBase(Record.readSubExpr()); - E->setIsaMemberLoc(ReadSourceLocation()); - E->setOpLoc(ReadSourceLocation()); - E->setArrow(Record.readInt()); -} - -void ASTStmtReader:: -VisitObjCIndirectCopyRestoreExpr(ObjCIndirectCopyRestoreExpr *E) { - VisitExpr(E); - E->Operand = Record.readSubExpr(); - E->setShouldCopy(Record.readInt()); -} - -void ASTStmtReader::VisitObjCBridgedCastExpr(ObjCBridgedCastExpr *E) { - VisitExplicitCastExpr(E); - E->LParenLoc = ReadSourceLocation(); - E->BridgeKeywordLoc = ReadSourceLocation(); - E->Kind = Record.readInt(); -} - -void ASTStmtReader::VisitCastExpr(CastExpr *E) { - VisitExpr(E); - unsigned NumBaseSpecs = Record.readInt(); - assert(NumBaseSpecs == E->path_size()); - E->setSubExpr(Record.readSubExpr()); - E->setCastKind((CastKind)Record.readInt()); - CastExpr::path_iterator BaseI = E->path_begin(); - while (NumBaseSpecs--) { - auto *BaseSpec = new (Record.getContext()) CXXBaseSpecifier; - *BaseSpec = Record.readCXXBaseSpecifier(); - *BaseI++ = BaseSpec; - } -} - -void ASTStmtReader::VisitBinaryOperator(BinaryOperator *E) { - VisitExpr(E); - E->setLHS(Record.readSubExpr()); - E->setRHS(Record.readSubExpr()); - E->setOpcode((BinaryOperator::Opcode)Record.readInt()); - E->setOperatorLoc(ReadSourceLocation()); - E->setFPFeatures(FPOptions(Record.readInt())); -} - -void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) { - VisitBinaryOperator(E); - E->setComputationLHSType(Record.readType()); - E->setComputationResultType(Record.readType()); -} - -void ASTStmtReader::VisitConditionalOperator(ConditionalOperator *E) { - VisitExpr(E); - E->SubExprs[ConditionalOperator::COND] = Record.readSubExpr(); - E->SubExprs[ConditionalOperator::LHS] = Record.readSubExpr(); - E->SubExprs[ConditionalOperator::RHS] = Record.readSubExpr(); - E->QuestionLoc = ReadSourceLocation(); - E->ColonLoc = ReadSourceLocation(); -} - -void -ASTStmtReader::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { - VisitExpr(E); - E->OpaqueValue = cast<OpaqueValueExpr>(Record.readSubExpr()); - E->SubExprs[BinaryConditionalOperator::COMMON] = Record.readSubExpr(); - E->SubExprs[BinaryConditionalOperator::COND] = Record.readSubExpr(); - E->SubExprs[BinaryConditionalOperator::LHS] = Record.readSubExpr(); - E->SubExprs[BinaryConditionalOperator::RHS] = Record.readSubExpr(); - E->QuestionLoc = ReadSourceLocation(); - E->ColonLoc = ReadSourceLocation(); -} - -void ASTStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) { - VisitCastExpr(E); - E->setIsPartOfExplicitCast(Record.readInt()); -} - -void ASTStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) { - VisitCastExpr(E); - E->setTypeInfoAsWritten(GetTypeSourceInfo()); -} - -void ASTStmtReader::VisitCStyleCastExpr(CStyleCastExpr *E) { - VisitExplicitCastExpr(E); - E->setLParenLoc(ReadSourceLocation()); - E->setRParenLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { - VisitExpr(E); - E->setLParenLoc(ReadSourceLocation()); - E->setTypeSourceInfo(GetTypeSourceInfo()); - E->setInitializer(Record.readSubExpr()); - E->setFileScope(Record.readInt()); -} - -void ASTStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { - VisitExpr(E); - E->setBase(Record.readSubExpr()); - E->setAccessor(Record.getIdentifierInfo()); - E->setAccessorLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitInitListExpr(InitListExpr *E) { - VisitExpr(E); - if (auto *SyntForm = cast_or_null<InitListExpr>(Record.readSubStmt())) - E->setSyntacticForm(SyntForm); - E->setLBraceLoc(ReadSourceLocation()); - E->setRBraceLoc(ReadSourceLocation()); - bool isArrayFiller = Record.readInt(); - Expr *filler = nullptr; - if (isArrayFiller) { - filler = Record.readSubExpr(); - E->ArrayFillerOrUnionFieldInit = filler; - } else - E->ArrayFillerOrUnionFieldInit = ReadDeclAs<FieldDecl>(); - E->sawArrayRangeDesignator(Record.readInt()); - unsigned NumInits = Record.readInt(); - E->reserveInits(Record.getContext(), NumInits); - if (isArrayFiller) { - for (unsigned I = 0; I != NumInits; ++I) { - Expr *init = Record.readSubExpr(); - E->updateInit(Record.getContext(), I, init ? init : filler); - } - } else { - for (unsigned I = 0; I != NumInits; ++I) - E->updateInit(Record.getContext(), I, Record.readSubExpr()); - } -} - -void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { - using Designator = DesignatedInitExpr::Designator; - - VisitExpr(E); - unsigned NumSubExprs = Record.readInt(); - assert(NumSubExprs == E->getNumSubExprs() && "Wrong number of subexprs"); - for (unsigned I = 0; I != NumSubExprs; ++I) - E->setSubExpr(I, Record.readSubExpr()); - E->setEqualOrColonLoc(ReadSourceLocation()); - E->setGNUSyntax(Record.readInt()); - - SmallVector<Designator, 4> Designators; - while (Record.getIdx() < Record.size()) { - switch ((DesignatorTypes)Record.readInt()) { - case DESIG_FIELD_DECL: { - auto *Field = ReadDeclAs<FieldDecl>(); - SourceLocation DotLoc = ReadSourceLocation(); - SourceLocation FieldLoc = ReadSourceLocation(); - Designators.push_back(Designator(Field->getIdentifier(), DotLoc, - FieldLoc)); - Designators.back().setField(Field); - break; - } - - case DESIG_FIELD_NAME: { - const IdentifierInfo *Name = Record.getIdentifierInfo(); - SourceLocation DotLoc = ReadSourceLocation(); - SourceLocation FieldLoc = ReadSourceLocation(); - Designators.push_back(Designator(Name, DotLoc, FieldLoc)); - break; - } - - case DESIG_ARRAY: { - unsigned Index = Record.readInt(); - SourceLocation LBracketLoc = ReadSourceLocation(); - SourceLocation RBracketLoc = ReadSourceLocation(); - Designators.push_back(Designator(Index, LBracketLoc, RBracketLoc)); - break; - } - - case DESIG_ARRAY_RANGE: { - unsigned Index = Record.readInt(); - SourceLocation LBracketLoc = ReadSourceLocation(); - SourceLocation EllipsisLoc = ReadSourceLocation(); - SourceLocation RBracketLoc = ReadSourceLocation(); - Designators.push_back(Designator(Index, LBracketLoc, EllipsisLoc, - RBracketLoc)); - break; - } - } - } - E->setDesignators(Record.getContext(), - Designators.data(), Designators.size()); -} - -void ASTStmtReader::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) { - VisitExpr(E); - E->setBase(Record.readSubExpr()); - E->setUpdater(Record.readSubExpr()); -} - -void ASTStmtReader::VisitNoInitExpr(NoInitExpr *E) { - VisitExpr(E); -} - -void ASTStmtReader::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) { - VisitExpr(E); - E->SubExprs[0] = Record.readSubExpr(); - E->SubExprs[1] = Record.readSubExpr(); -} - -void ASTStmtReader::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) { - VisitExpr(E); -} - -void ASTStmtReader::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { - VisitExpr(E); -} - -void ASTStmtReader::VisitVAArgExpr(VAArgExpr *E) { - VisitExpr(E); - E->setSubExpr(Record.readSubExpr()); - E->setWrittenTypeInfo(GetTypeSourceInfo()); - E->setBuiltinLoc(ReadSourceLocation()); - E->setRParenLoc(ReadSourceLocation()); - E->setIsMicrosoftABI(Record.readInt()); -} - -void ASTStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) { - VisitExpr(E); - E->setAmpAmpLoc(ReadSourceLocation()); - E->setLabelLoc(ReadSourceLocation()); - E->setLabel(ReadDeclAs<LabelDecl>()); -} - -void ASTStmtReader::VisitStmtExpr(StmtExpr *E) { - VisitExpr(E); - E->setLParenLoc(ReadSourceLocation()); - E->setRParenLoc(ReadSourceLocation()); - E->setSubStmt(cast_or_null<CompoundStmt>(Record.readSubStmt())); -} - -void ASTStmtReader::VisitChooseExpr(ChooseExpr *E) { - VisitExpr(E); - E->setCond(Record.readSubExpr()); - E->setLHS(Record.readSubExpr()); - E->setRHS(Record.readSubExpr()); - E->setBuiltinLoc(ReadSourceLocation()); - E->setRParenLoc(ReadSourceLocation()); - E->setIsConditionTrue(Record.readInt()); -} - -void ASTStmtReader::VisitGNUNullExpr(GNUNullExpr *E) { - VisitExpr(E); - E->setTokenLocation(ReadSourceLocation()); -} - -void ASTStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { - VisitExpr(E); - SmallVector<Expr *, 16> Exprs; - unsigned NumExprs = Record.readInt(); - while (NumExprs--) - Exprs.push_back(Record.readSubExpr()); - E->setExprs(Record.getContext(), Exprs); - E->setBuiltinLoc(ReadSourceLocation()); - E->setRParenLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitConvertVectorExpr(ConvertVectorExpr *E) { - VisitExpr(E); - E->BuiltinLoc = ReadSourceLocation(); - E->RParenLoc = ReadSourceLocation(); - E->TInfo = GetTypeSourceInfo(); - E->SrcExpr = Record.readSubExpr(); -} - -void ASTStmtReader::VisitBlockExpr(BlockExpr *E) { - VisitExpr(E); - E->setBlockDecl(ReadDeclAs<BlockDecl>()); -} - -void ASTStmtReader::VisitGenericSelectionExpr(GenericSelectionExpr *E) { - VisitExpr(E); - E->NumAssocs = Record.readInt(); - E->AssocTypes = new (Record.getContext()) TypeSourceInfo*[E->NumAssocs]; - E->SubExprs = - new(Record.getContext()) Stmt*[GenericSelectionExpr::END_EXPR+E->NumAssocs]; - - E->SubExprs[GenericSelectionExpr::CONTROLLING] = Record.readSubExpr(); - for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) { - E->AssocTypes[I] = GetTypeSourceInfo(); - E->SubExprs[GenericSelectionExpr::END_EXPR+I] = Record.readSubExpr(); - } - E->ResultIndex = Record.readInt(); - - E->GenericLoc = ReadSourceLocation(); - E->DefaultLoc = ReadSourceLocation(); - E->RParenLoc = ReadSourceLocation(); -} - -void ASTStmtReader::VisitPseudoObjectExpr(PseudoObjectExpr *E) { - VisitExpr(E); - unsigned numSemanticExprs = Record.readInt(); - assert(numSemanticExprs + 1 == E->PseudoObjectExprBits.NumSubExprs); - E->PseudoObjectExprBits.ResultIndex = Record.readInt(); - - // Read the syntactic expression. - E->getSubExprsBuffer()[0] = Record.readSubExpr(); - - // Read all the semantic expressions. - for (unsigned i = 0; i != numSemanticExprs; ++i) { - Expr *subExpr = Record.readSubExpr(); - E->getSubExprsBuffer()[i+1] = subExpr; - } -} - -void ASTStmtReader::VisitAtomicExpr(AtomicExpr *E) { - VisitExpr(E); - E->Op = AtomicExpr::AtomicOp(Record.readInt()); - E->NumSubExprs = AtomicExpr::getNumSubExprs(E->Op); - for (unsigned I = 0; I != E->NumSubExprs; ++I) - E->SubExprs[I] = Record.readSubExpr(); - E->BuiltinLoc = ReadSourceLocation(); - E->RParenLoc = ReadSourceLocation(); -} - -//===----------------------------------------------------------------------===// -// Objective-C Expressions and Statements - -void ASTStmtReader::VisitObjCStringLiteral(ObjCStringLiteral *E) { - VisitExpr(E); - E->setString(cast<StringLiteral>(Record.readSubStmt())); - E->setAtLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitObjCBoxedExpr(ObjCBoxedExpr *E) { - VisitExpr(E); - // could be one of several IntegerLiteral, FloatLiteral, etc. - E->SubExpr = Record.readSubStmt(); - E->BoxingMethod = ReadDeclAs<ObjCMethodDecl>(); - E->Range = ReadSourceRange(); -} - -void ASTStmtReader::VisitObjCArrayLiteral(ObjCArrayLiteral *E) { - VisitExpr(E); - unsigned NumElements = Record.readInt(); - assert(NumElements == E->getNumElements() && "Wrong number of elements"); - Expr **Elements = E->getElements(); - for (unsigned I = 0, N = NumElements; I != N; ++I) - Elements[I] = Record.readSubExpr(); - E->ArrayWithObjectsMethod = ReadDeclAs<ObjCMethodDecl>(); - E->Range = ReadSourceRange(); -} - -void ASTStmtReader::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { - VisitExpr(E); - unsigned NumElements = Record.readInt(); - assert(NumElements == E->getNumElements() && "Wrong number of elements"); - bool HasPackExpansions = Record.readInt(); - assert(HasPackExpansions == E->HasPackExpansions &&"Pack expansion mismatch"); - auto *KeyValues = - E->getTrailingObjects<ObjCDictionaryLiteral::KeyValuePair>(); - auto *Expansions = - E->getTrailingObjects<ObjCDictionaryLiteral::ExpansionData>(); - for (unsigned I = 0; I != NumElements; ++I) { - KeyValues[I].Key = Record.readSubExpr(); - KeyValues[I].Value = Record.readSubExpr(); - if (HasPackExpansions) { - Expansions[I].EllipsisLoc = ReadSourceLocation(); - Expansions[I].NumExpansionsPlusOne = Record.readInt(); - } - } - E->DictWithObjectsMethod = ReadDeclAs<ObjCMethodDecl>(); - E->Range = ReadSourceRange(); -} - -void ASTStmtReader::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { - VisitExpr(E); - E->setEncodedTypeSourceInfo(GetTypeSourceInfo()); - E->setAtLoc(ReadSourceLocation()); - E->setRParenLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitObjCSelectorExpr(ObjCSelectorExpr *E) { - VisitExpr(E); - E->setSelector(Record.readSelector()); - E->setAtLoc(ReadSourceLocation()); - E->setRParenLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitObjCProtocolExpr(ObjCProtocolExpr *E) { - VisitExpr(E); - E->setProtocol(ReadDeclAs<ObjCProtocolDecl>()); - E->setAtLoc(ReadSourceLocation()); - E->ProtoLoc = ReadSourceLocation(); - E->setRParenLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { - VisitExpr(E); - E->setDecl(ReadDeclAs<ObjCIvarDecl>()); - E->setLocation(ReadSourceLocation()); - E->setOpLoc(ReadSourceLocation()); - E->setBase(Record.readSubExpr()); - E->setIsArrow(Record.readInt()); - E->setIsFreeIvar(Record.readInt()); -} - -void ASTStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { - VisitExpr(E); - unsigned MethodRefFlags = Record.readInt(); - bool Implicit = Record.readInt() != 0; - if (Implicit) { - auto *Getter = ReadDeclAs<ObjCMethodDecl>(); - auto *Setter = ReadDeclAs<ObjCMethodDecl>(); - E->setImplicitProperty(Getter, Setter, MethodRefFlags); - } else { - E->setExplicitProperty(ReadDeclAs<ObjCPropertyDecl>(), MethodRefFlags); - } - E->setLocation(ReadSourceLocation()); - E->setReceiverLocation(ReadSourceLocation()); - switch (Record.readInt()) { - case 0: - E->setBase(Record.readSubExpr()); - break; - case 1: - E->setSuperReceiver(Record.readType()); - break; - case 2: - E->setClassReceiver(ReadDeclAs<ObjCInterfaceDecl>()); - break; - } -} - -void ASTStmtReader::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *E) { - VisitExpr(E); - E->setRBracket(ReadSourceLocation()); - E->setBaseExpr(Record.readSubExpr()); - E->setKeyExpr(Record.readSubExpr()); - E->GetAtIndexMethodDecl = ReadDeclAs<ObjCMethodDecl>(); - E->SetAtIndexMethodDecl = ReadDeclAs<ObjCMethodDecl>(); -} - -void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) { - VisitExpr(E); - assert(Record.peekInt() == E->getNumArgs()); - Record.skipInts(1); - unsigned NumStoredSelLocs = Record.readInt(); - E->SelLocsKind = Record.readInt(); - E->setDelegateInitCall(Record.readInt()); - E->IsImplicit = Record.readInt(); - auto Kind = static_cast<ObjCMessageExpr::ReceiverKind>(Record.readInt()); - switch (Kind) { - case ObjCMessageExpr::Instance: - E->setInstanceReceiver(Record.readSubExpr()); - break; - - case ObjCMessageExpr::Class: - E->setClassReceiver(GetTypeSourceInfo()); - break; - - case ObjCMessageExpr::SuperClass: - case ObjCMessageExpr::SuperInstance: { - QualType T = Record.readType(); - SourceLocation SuperLoc = ReadSourceLocation(); - E->setSuper(SuperLoc, T, Kind == ObjCMessageExpr::SuperInstance); - break; - } - } - - assert(Kind == E->getReceiverKind()); - - if (Record.readInt()) - E->setMethodDecl(ReadDeclAs<ObjCMethodDecl>()); - else - E->setSelector(Record.readSelector()); - - E->LBracLoc = ReadSourceLocation(); - E->RBracLoc = ReadSourceLocation(); - - for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) - E->setArg(I, Record.readSubExpr()); - - SourceLocation *Locs = E->getStoredSelLocs(); - for (unsigned I = 0; I != NumStoredSelLocs; ++I) - Locs[I] = ReadSourceLocation(); -} - -void ASTStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { - VisitStmt(S); - S->setElement(Record.readSubStmt()); - S->setCollection(Record.readSubExpr()); - S->setBody(Record.readSubStmt()); - S->setForLoc(ReadSourceLocation()); - S->setRParenLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { - VisitStmt(S); - S->setCatchBody(Record.readSubStmt()); - S->setCatchParamDecl(ReadDeclAs<VarDecl>()); - S->setAtCatchLoc(ReadSourceLocation()); - S->setRParenLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { - VisitStmt(S); - S->setFinallyBody(Record.readSubStmt()); - S->setAtFinallyLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) { - VisitStmt(S); - S->setSubStmt(Record.readSubStmt()); - S->setAtLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { - VisitStmt(S); - assert(Record.peekInt() == S->getNumCatchStmts()); - Record.skipInts(1); - bool HasFinally = Record.readInt(); - S->setTryBody(Record.readSubStmt()); - for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) - S->setCatchStmt(I, cast_or_null<ObjCAtCatchStmt>(Record.readSubStmt())); - - if (HasFinally) - S->setFinallyStmt(Record.readSubStmt()); - S->setAtTryLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { - VisitStmt(S); - S->setSynchExpr(Record.readSubStmt()); - S->setSynchBody(Record.readSubStmt()); - S->setAtSynchronizedLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { - VisitStmt(S); - S->setThrowExpr(Record.readSubStmt()); - S->setThrowLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *E) { - VisitExpr(E); - E->setValue(Record.readInt()); - E->setLocation(ReadSourceLocation()); -} - -void ASTStmtReader::VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) { - VisitExpr(E); - SourceRange R = Record.readSourceRange(); - E->AtLoc = R.getBegin(); - E->RParen = R.getEnd(); - E->VersionToCheck = Record.readVersionTuple(); -} - -//===----------------------------------------------------------------------===// -// C++ Expressions and Statements -//===----------------------------------------------------------------------===// - -void ASTStmtReader::VisitCXXCatchStmt(CXXCatchStmt *S) { - VisitStmt(S); - S->CatchLoc = ReadSourceLocation(); - S->ExceptionDecl = ReadDeclAs<VarDecl>(); - S->HandlerBlock = Record.readSubStmt(); -} - -void ASTStmtReader::VisitCXXTryStmt(CXXTryStmt *S) { - VisitStmt(S); - assert(Record.peekInt() == S->getNumHandlers() && "NumStmtFields is wrong ?"); - Record.skipInts(1); - S->TryLoc = ReadSourceLocation(); - S->getStmts()[0] = Record.readSubStmt(); - for (unsigned i = 0, e = S->getNumHandlers(); i != e; ++i) - S->getStmts()[i + 1] = Record.readSubStmt(); -} - -void ASTStmtReader::VisitCXXForRangeStmt(CXXForRangeStmt *S) { - VisitStmt(S); - S->ForLoc = ReadSourceLocation(); - S->CoawaitLoc = ReadSourceLocation(); - S->ColonLoc = ReadSourceLocation(); - S->RParenLoc = ReadSourceLocation(); - S->setInit(Record.readSubStmt()); - S->setRangeStmt(Record.readSubStmt()); - S->setBeginStmt(Record.readSubStmt()); - S->setEndStmt(Record.readSubStmt()); - S->setCond(Record.readSubExpr()); - S->setInc(Record.readSubExpr()); - S->setLoopVarStmt(Record.readSubStmt()); - S->setBody(Record.readSubStmt()); -} - -void ASTStmtReader::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) { - VisitStmt(S); - S->KeywordLoc = ReadSourceLocation(); - S->IsIfExists = Record.readInt(); - S->QualifierLoc = Record.readNestedNameSpecifierLoc(); - ReadDeclarationNameInfo(S->NameInfo); - S->SubStmt = Record.readSubStmt(); -} - -void ASTStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { - VisitCallExpr(E); - E->CXXOperatorCallExprBits.OperatorKind = Record.readInt(); - E->CXXOperatorCallExprBits.FPFeatures = Record.readInt(); - E->Range = Record.readSourceRange(); -} - -void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) { - VisitExpr(E); - - unsigned NumArgs = Record.readInt(); - assert((NumArgs == E->getNumArgs()) && "Wrong NumArgs!"); - - E->CXXConstructExprBits.Elidable = Record.readInt(); - E->CXXConstructExprBits.HadMultipleCandidates = Record.readInt(); - E->CXXConstructExprBits.ListInitialization = Record.readInt(); - E->CXXConstructExprBits.StdInitListInitialization = Record.readInt(); - E->CXXConstructExprBits.ZeroInitialization = Record.readInt(); - E->CXXConstructExprBits.ConstructionKind = Record.readInt(); - E->CXXConstructExprBits.Loc = ReadSourceLocation(); - E->Constructor = ReadDeclAs<CXXConstructorDecl>(); - E->ParenOrBraceRange = ReadSourceRange(); - - for (unsigned I = 0; I != NumArgs; ++I) - E->setArg(I, Record.readSubExpr()); -} - -void ASTStmtReader::VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E) { - VisitExpr(E); - E->Constructor = ReadDeclAs<CXXConstructorDecl>(); - E->Loc = ReadSourceLocation(); - E->ConstructsVirtualBase = Record.readInt(); - E->InheritedFromVirtualBase = Record.readInt(); -} - -void ASTStmtReader::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { - VisitCXXConstructExpr(E); - E->TSI = GetTypeSourceInfo(); -} - -void ASTStmtReader::VisitLambdaExpr(LambdaExpr *E) { - VisitExpr(E); - unsigned NumCaptures = Record.readInt(); - assert(NumCaptures == E->NumCaptures);(void)NumCaptures; - E->IntroducerRange = ReadSourceRange(); - E->CaptureDefault = static_cast<LambdaCaptureDefault>(Record.readInt()); - E->CaptureDefaultLoc = ReadSourceLocation(); - E->ExplicitParams = Record.readInt(); - E->ExplicitResultType = Record.readInt(); - E->ClosingBrace = ReadSourceLocation(); - - // Read capture initializers. - for (LambdaExpr::capture_init_iterator C = E->capture_init_begin(), - CEnd = E->capture_init_end(); - C != CEnd; ++C) - *C = Record.readSubExpr(); -} - -void -ASTStmtReader::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { - VisitExpr(E); - E->SubExpr = Record.readSubExpr(); -} - -void ASTStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { - VisitExplicitCastExpr(E); - SourceRange R = ReadSourceRange(); - E->Loc = R.getBegin(); - E->RParenLoc = R.getEnd(); - R = ReadSourceRange(); - E->AngleBrackets = R; -} - -void ASTStmtReader::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -void ASTStmtReader::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -void ASTStmtReader::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -void ASTStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -void ASTStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { - VisitExplicitCastExpr(E); - E->setLParenLoc(ReadSourceLocation()); - E->setRParenLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitUserDefinedLiteral(UserDefinedLiteral *E) { - VisitCallExpr(E); - E->UDSuffixLoc = ReadSourceLocation(); -} - -void ASTStmtReader::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { - VisitExpr(E); - E->setValue(Record.readInt()); - E->setLocation(ReadSourceLocation()); -} - -void ASTStmtReader::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { - VisitExpr(E); - E->setLocation(ReadSourceLocation()); -} - -void ASTStmtReader::VisitCXXTypeidExpr(CXXTypeidExpr *E) { - VisitExpr(E); - E->setSourceRange(ReadSourceRange()); - if (E->isTypeOperand()) { // typeid(int) - E->setTypeOperandSourceInfo( - GetTypeSourceInfo()); - return; - } - - // typeid(42+2) - E->setExprOperand(Record.readSubExpr()); -} - -void ASTStmtReader::VisitCXXThisExpr(CXXThisExpr *E) { - VisitExpr(E); - E->setLocation(ReadSourceLocation()); - E->setImplicit(Record.readInt()); -} - -void ASTStmtReader::VisitCXXThrowExpr(CXXThrowExpr *E) { - VisitExpr(E); - E->CXXThrowExprBits.ThrowLoc = ReadSourceLocation(); - E->Operand = Record.readSubExpr(); - E->CXXThrowExprBits.IsThrownVariableInScope = Record.readInt(); -} - -void ASTStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { - VisitExpr(E); - E->Param = ReadDeclAs<ParmVarDecl>(); - E->CXXDefaultArgExprBits.Loc = ReadSourceLocation(); -} - -void ASTStmtReader::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { - VisitExpr(E); - E->Field = ReadDeclAs<FieldDecl>(); - E->CXXDefaultInitExprBits.Loc = ReadSourceLocation(); -} - -void ASTStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { - VisitExpr(E); - E->setTemporary(Record.readCXXTemporary()); - E->setSubExpr(Record.readSubExpr()); -} - -void ASTStmtReader::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { - VisitExpr(E); - E->TypeInfo = GetTypeSourceInfo(); - E->CXXScalarValueInitExprBits.RParenLoc = ReadSourceLocation(); -} - -void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) { - VisitExpr(E); - - bool IsArray = Record.readInt(); - bool HasInit = Record.readInt(); - unsigned NumPlacementArgs = Record.readInt(); - bool IsParenTypeId = Record.readInt(); - - E->CXXNewExprBits.IsGlobalNew = Record.readInt(); - E->CXXNewExprBits.ShouldPassAlignment = Record.readInt(); - E->CXXNewExprBits.UsualArrayDeleteWantsSize = Record.readInt(); - E->CXXNewExprBits.StoredInitializationStyle = Record.readInt(); - - assert((IsArray == E->isArray()) && "Wrong IsArray!"); - assert((HasInit == E->hasInitializer()) && "Wrong HasInit!"); - assert((NumPlacementArgs == E->getNumPlacementArgs()) && - "Wrong NumPlacementArgs!"); - assert((IsParenTypeId == E->isParenTypeId()) && "Wrong IsParenTypeId!"); - (void)IsArray; - (void)HasInit; - (void)NumPlacementArgs; - - E->setOperatorNew(ReadDeclAs<FunctionDecl>()); - E->setOperatorDelete(ReadDeclAs<FunctionDecl>()); - E->AllocatedTypeInfo = GetTypeSourceInfo(); - if (IsParenTypeId) - E->getTrailingObjects<SourceRange>()[0] = ReadSourceRange(); - E->Range = ReadSourceRange(); - E->DirectInitRange = ReadSourceRange(); - - // Install all the subexpressions. - for (CXXNewExpr::raw_arg_iterator I = E->raw_arg_begin(), - N = E->raw_arg_end(); - I != N; ++I) - *I = Record.readSubStmt(); -} - -void ASTStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) { - VisitExpr(E); - E->CXXDeleteExprBits.GlobalDelete = Record.readInt(); - E->CXXDeleteExprBits.ArrayForm = Record.readInt(); - E->CXXDeleteExprBits.ArrayFormAsWritten = Record.readInt(); - E->CXXDeleteExprBits.UsualArrayDeleteWantsSize = Record.readInt(); - E->OperatorDelete = ReadDeclAs<FunctionDecl>(); - E->Argument = Record.readSubExpr(); - E->CXXDeleteExprBits.Loc = ReadSourceLocation(); -} - -void ASTStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { - VisitExpr(E); - - E->Base = Record.readSubExpr(); - E->IsArrow = Record.readInt(); - E->OperatorLoc = ReadSourceLocation(); - E->QualifierLoc = Record.readNestedNameSpecifierLoc(); - E->ScopeType = GetTypeSourceInfo(); - E->ColonColonLoc = ReadSourceLocation(); - E->TildeLoc = ReadSourceLocation(); - - IdentifierInfo *II = Record.getIdentifierInfo(); - if (II) - E->setDestroyedType(II, ReadSourceLocation()); - else - E->setDestroyedType(GetTypeSourceInfo()); -} - -void ASTStmtReader::VisitExprWithCleanups(ExprWithCleanups *E) { - VisitExpr(E); - - unsigned NumObjects = Record.readInt(); - assert(NumObjects == E->getNumObjects()); - for (unsigned i = 0; i != NumObjects; ++i) - E->getTrailingObjects<BlockDecl *>()[i] = - ReadDeclAs<BlockDecl>(); - - E->ExprWithCleanupsBits.CleanupsHaveSideEffects = Record.readInt(); - E->SubExpr = Record.readSubExpr(); -} - -void ASTStmtReader::VisitCXXDependentScopeMemberExpr( - CXXDependentScopeMemberExpr *E) { - VisitExpr(E); - - bool HasTemplateKWAndArgsInfo = Record.readInt(); - unsigned NumTemplateArgs = Record.readInt(); - bool HasFirstQualifierFoundInScope = Record.readInt(); - - assert((HasTemplateKWAndArgsInfo == E->hasTemplateKWAndArgsInfo()) && - "Wrong HasTemplateKWAndArgsInfo!"); - assert( - (HasFirstQualifierFoundInScope == E->hasFirstQualifierFoundInScope()) && - "Wrong HasFirstQualifierFoundInScope!"); - - if (HasTemplateKWAndArgsInfo) - ReadTemplateKWAndArgsInfo( - *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(), - E->getTrailingObjects<TemplateArgumentLoc>(), NumTemplateArgs); - - assert((NumTemplateArgs == E->getNumTemplateArgs()) && - "Wrong NumTemplateArgs!"); - - E->CXXDependentScopeMemberExprBits.IsArrow = Record.readInt(); - E->CXXDependentScopeMemberExprBits.OperatorLoc = ReadSourceLocation(); - E->BaseType = Record.readType(); - E->QualifierLoc = Record.readNestedNameSpecifierLoc(); - E->Base = Record.readSubExpr(); - - if (HasFirstQualifierFoundInScope) - *E->getTrailingObjects<NamedDecl *>() = ReadDeclAs<NamedDecl>(); - - ReadDeclarationNameInfo(E->MemberNameInfo); -} - -void -ASTStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { - VisitExpr(E); - - if (Record.readInt()) // HasTemplateKWAndArgsInfo - ReadTemplateKWAndArgsInfo( - *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(), - E->getTrailingObjects<TemplateArgumentLoc>(), - /*NumTemplateArgs=*/Record.readInt()); - - E->QualifierLoc = Record.readNestedNameSpecifierLoc(); - ReadDeclarationNameInfo(E->NameInfo); -} - -void -ASTStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { - VisitExpr(E); - assert(Record.peekInt() == E->arg_size() && - "Read wrong record during creation ?"); - Record.skipInts(1); - for (unsigned I = 0, N = E->arg_size(); I != N; ++I) - E->setArg(I, Record.readSubExpr()); - E->TSI = GetTypeSourceInfo(); - E->setLParenLoc(ReadSourceLocation()); - E->setRParenLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) { - VisitExpr(E); - - unsigned NumResults = Record.readInt(); - bool HasTemplateKWAndArgsInfo = Record.readInt(); - assert((E->getNumDecls() == NumResults) && "Wrong NumResults!"); - assert((E->hasTemplateKWAndArgsInfo() == HasTemplateKWAndArgsInfo) && - "Wrong HasTemplateKWAndArgsInfo!"); - - if (HasTemplateKWAndArgsInfo) { - unsigned NumTemplateArgs = Record.readInt(); - ReadTemplateKWAndArgsInfo(*E->getTrailingASTTemplateKWAndArgsInfo(), - E->getTrailingTemplateArgumentLoc(), - NumTemplateArgs); - assert((E->getNumTemplateArgs() == NumTemplateArgs) && - "Wrong NumTemplateArgs!"); - } - - UnresolvedSet<8> Decls; - for (unsigned I = 0; I != NumResults; ++I) { - auto *D = ReadDeclAs<NamedDecl>(); - auto AS = (AccessSpecifier)Record.readInt(); - Decls.addDecl(D, AS); - } - - DeclAccessPair *Results = E->getTrailingResults(); - UnresolvedSetIterator Iter = Decls.begin(); - for (unsigned I = 0; I != NumResults; ++I) { - Results[I] = (Iter + I).getPair(); - } - - ReadDeclarationNameInfo(E->NameInfo); - E->QualifierLoc = Record.readNestedNameSpecifierLoc(); -} - -void ASTStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { - VisitOverloadExpr(E); - E->UnresolvedMemberExprBits.IsArrow = Record.readInt(); - E->UnresolvedMemberExprBits.HasUnresolvedUsing = Record.readInt(); - E->Base = Record.readSubExpr(); - E->BaseType = Record.readType(); - E->OperatorLoc = ReadSourceLocation(); -} - -void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { - VisitOverloadExpr(E); - E->UnresolvedLookupExprBits.RequiresADL = Record.readInt(); - E->UnresolvedLookupExprBits.Overloaded = Record.readInt(); - E->NamingClass = ReadDeclAs<CXXRecordDecl>(); -} - -void ASTStmtReader::VisitTypeTraitExpr(TypeTraitExpr *E) { - VisitExpr(E); - E->TypeTraitExprBits.NumArgs = Record.readInt(); - E->TypeTraitExprBits.Kind = Record.readInt(); - E->TypeTraitExprBits.Value = Record.readInt(); - SourceRange Range = ReadSourceRange(); - E->Loc = Range.getBegin(); - E->RParenLoc = Range.getEnd(); - - auto **Args = E->getTrailingObjects<TypeSourceInfo *>(); - for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) - Args[I] = GetTypeSourceInfo(); -} - -void ASTStmtReader::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { - VisitExpr(E); - E->ATT = (ArrayTypeTrait)Record.readInt(); - E->Value = (unsigned int)Record.readInt(); - SourceRange Range = ReadSourceRange(); - E->Loc = Range.getBegin(); - E->RParen = Range.getEnd(); - E->QueriedType = GetTypeSourceInfo(); - E->Dimension = Record.readSubExpr(); -} - -void ASTStmtReader::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { - VisitExpr(E); - E->ET = (ExpressionTrait)Record.readInt(); - E->Value = (bool)Record.readInt(); - SourceRange Range = ReadSourceRange(); - E->QueriedExpression = Record.readSubExpr(); - E->Loc = Range.getBegin(); - E->RParen = Range.getEnd(); -} - -void ASTStmtReader::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { - VisitExpr(E); - E->CXXNoexceptExprBits.Value = Record.readInt(); - E->Range = ReadSourceRange(); - E->Operand = Record.readSubExpr(); -} - -void ASTStmtReader::VisitPackExpansionExpr(PackExpansionExpr *E) { - VisitExpr(E); - E->EllipsisLoc = ReadSourceLocation(); - E->NumExpansions = Record.readInt(); - E->Pattern = Record.readSubExpr(); -} - -void ASTStmtReader::VisitSizeOfPackExpr(SizeOfPackExpr *E) { - VisitExpr(E); - unsigned NumPartialArgs = Record.readInt(); - E->OperatorLoc = ReadSourceLocation(); - E->PackLoc = ReadSourceLocation(); - E->RParenLoc = ReadSourceLocation(); - E->Pack = Record.readDeclAs<NamedDecl>(); - if (E->isPartiallySubstituted()) { - assert(E->Length == NumPartialArgs); - for (auto *I = E->getTrailingObjects<TemplateArgument>(), - *E = I + NumPartialArgs; - I != E; ++I) - new (I) TemplateArgument(Record.readTemplateArgument()); - } else if (!E->isValueDependent()) { - E->Length = Record.readInt(); - } -} - -void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr( - SubstNonTypeTemplateParmExpr *E) { - VisitExpr(E); - E->Param = ReadDeclAs<NonTypeTemplateParmDecl>(); - E->SubstNonTypeTemplateParmExprBits.NameLoc = ReadSourceLocation(); - E->Replacement = Record.readSubExpr(); -} - -void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr( - SubstNonTypeTemplateParmPackExpr *E) { - VisitExpr(E); - E->Param = ReadDeclAs<NonTypeTemplateParmDecl>(); - TemplateArgument ArgPack = Record.readTemplateArgument(); - if (ArgPack.getKind() != TemplateArgument::Pack) - return; - - E->Arguments = ArgPack.pack_begin(); - E->NumArguments = ArgPack.pack_size(); - E->NameLoc = ReadSourceLocation(); -} - -void ASTStmtReader::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) { - VisitExpr(E); - E->NumParameters = Record.readInt(); - E->ParamPack = ReadDeclAs<ParmVarDecl>(); - E->NameLoc = ReadSourceLocation(); - auto **Parms = E->getTrailingObjects<ParmVarDecl *>(); - for (unsigned i = 0, n = E->NumParameters; i != n; ++i) - Parms[i] = ReadDeclAs<ParmVarDecl>(); -} - -void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { - VisitExpr(E); - E->State = Record.readSubExpr(); - auto *VD = ReadDeclAs<ValueDecl>(); - unsigned ManglingNumber = Record.readInt(); - E->setExtendingDecl(VD, ManglingNumber); -} - -void ASTStmtReader::VisitCXXFoldExpr(CXXFoldExpr *E) { - VisitExpr(E); - E->LParenLoc = ReadSourceLocation(); - E->EllipsisLoc = ReadSourceLocation(); - E->RParenLoc = ReadSourceLocation(); - E->SubExprs[0] = Record.readSubExpr(); - E->SubExprs[1] = Record.readSubExpr(); - E->Opcode = (BinaryOperatorKind)Record.readInt(); -} - -void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) { - VisitExpr(E); - E->SourceExpr = Record.readSubExpr(); - E->OpaqueValueExprBits.Loc = ReadSourceLocation(); - E->setIsUnique(Record.readInt()); -} - -void ASTStmtReader::VisitTypoExpr(TypoExpr *E) { - llvm_unreachable("Cannot read TypoExpr nodes"); -} - -//===----------------------------------------------------------------------===// -// Microsoft Expressions and Statements -//===----------------------------------------------------------------------===// -void ASTStmtReader::VisitMSPropertyRefExpr(MSPropertyRefExpr *E) { - VisitExpr(E); - E->IsArrow = (Record.readInt() != 0); - E->BaseExpr = Record.readSubExpr(); - E->QualifierLoc = Record.readNestedNameSpecifierLoc(); - E->MemberLoc = ReadSourceLocation(); - E->TheDecl = ReadDeclAs<MSPropertyDecl>(); -} - -void ASTStmtReader::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *E) { - VisitExpr(E); - E->setBase(Record.readSubExpr()); - E->setIdx(Record.readSubExpr()); - E->setRBracketLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitCXXUuidofExpr(CXXUuidofExpr *E) { - VisitExpr(E); - E->setSourceRange(ReadSourceRange()); - std::string UuidStr = ReadString(); - E->setUuidStr(StringRef(UuidStr).copy(Record.getContext())); - if (E->isTypeOperand()) { // __uuidof(ComType) - E->setTypeOperandSourceInfo( - GetTypeSourceInfo()); - return; - } - - // __uuidof(expr) - E->setExprOperand(Record.readSubExpr()); -} - -void ASTStmtReader::VisitSEHLeaveStmt(SEHLeaveStmt *S) { - VisitStmt(S); - S->setLeaveLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitSEHExceptStmt(SEHExceptStmt *S) { - VisitStmt(S); - S->Loc = ReadSourceLocation(); - S->Children[SEHExceptStmt::FILTER_EXPR] = Record.readSubStmt(); - S->Children[SEHExceptStmt::BLOCK] = Record.readSubStmt(); -} - -void ASTStmtReader::VisitSEHFinallyStmt(SEHFinallyStmt *S) { - VisitStmt(S); - S->Loc = ReadSourceLocation(); - S->Block = Record.readSubStmt(); -} - -void ASTStmtReader::VisitSEHTryStmt(SEHTryStmt *S) { - VisitStmt(S); - S->IsCXXTry = Record.readInt(); - S->TryLoc = ReadSourceLocation(); - S->Children[SEHTryStmt::TRY] = Record.readSubStmt(); - S->Children[SEHTryStmt::HANDLER] = Record.readSubStmt(); -} - -//===----------------------------------------------------------------------===// -// CUDA Expressions and Statements -//===----------------------------------------------------------------------===// - -void ASTStmtReader::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E) { - VisitCallExpr(E); - E->setConfig(cast<CallExpr>(Record.readSubExpr())); -} - -//===----------------------------------------------------------------------===// -// OpenCL Expressions and Statements. -//===----------------------------------------------------------------------===// -void ASTStmtReader::VisitAsTypeExpr(AsTypeExpr *E) { - VisitExpr(E); - E->BuiltinLoc = ReadSourceLocation(); - E->RParenLoc = ReadSourceLocation(); - E->SrcExpr = Record.readSubExpr(); -} - -//===----------------------------------------------------------------------===// -// OpenMP Directives. -//===----------------------------------------------------------------------===// - -void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) { - E->setLocStart(ReadSourceLocation()); - E->setLocEnd(ReadSourceLocation()); - OMPClauseReader ClauseReader(Record); - SmallVector<OMPClause *, 5> Clauses; - for (unsigned i = 0; i < E->getNumClauses(); ++i) - Clauses.push_back(ClauseReader.readClause()); - E->setClauses(Clauses); - if (E->hasAssociatedStmt()) - E->setAssociatedStmt(Record.readSubStmt()); -} - -void ASTStmtReader::VisitOMPLoopDirective(OMPLoopDirective *D) { - VisitStmt(D); - // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream. - Record.skipInts(2); - VisitOMPExecutableDirective(D); - D->setIterationVariable(Record.readSubExpr()); - D->setLastIteration(Record.readSubExpr()); - D->setCalcLastIteration(Record.readSubExpr()); - D->setPreCond(Record.readSubExpr()); - D->setCond(Record.readSubExpr()); - D->setInit(Record.readSubExpr()); - D->setInc(Record.readSubExpr()); - D->setPreInits(Record.readSubStmt()); - if (isOpenMPWorksharingDirective(D->getDirectiveKind()) || - isOpenMPTaskLoopDirective(D->getDirectiveKind()) || - isOpenMPDistributeDirective(D->getDirectiveKind())) { - D->setIsLastIterVariable(Record.readSubExpr()); - D->setLowerBoundVariable(Record.readSubExpr()); - D->setUpperBoundVariable(Record.readSubExpr()); - D->setStrideVariable(Record.readSubExpr()); - D->setEnsureUpperBound(Record.readSubExpr()); - D->setNextLowerBound(Record.readSubExpr()); - D->setNextUpperBound(Record.readSubExpr()); - D->setNumIterations(Record.readSubExpr()); - } - if (isOpenMPLoopBoundSharingDirective(D->getDirectiveKind())) { - D->setPrevLowerBoundVariable(Record.readSubExpr()); - D->setPrevUpperBoundVariable(Record.readSubExpr()); - D->setDistInc(Record.readSubExpr()); - D->setPrevEnsureUpperBound(Record.readSubExpr()); - D->setCombinedLowerBoundVariable(Record.readSubExpr()); - D->setCombinedUpperBoundVariable(Record.readSubExpr()); - D->setCombinedEnsureUpperBound(Record.readSubExpr()); - D->setCombinedInit(Record.readSubExpr()); - D->setCombinedCond(Record.readSubExpr()); - D->setCombinedNextLowerBound(Record.readSubExpr()); - D->setCombinedNextUpperBound(Record.readSubExpr()); - D->setCombinedDistCond(Record.readSubExpr()); - D->setCombinedParForInDistCond(Record.readSubExpr()); - } - SmallVector<Expr *, 4> Sub; - unsigned CollapsedNum = D->getCollapsedNumber(); - Sub.reserve(CollapsedNum); - for (unsigned i = 0; i < CollapsedNum; ++i) - Sub.push_back(Record.readSubExpr()); - D->setCounters(Sub); - Sub.clear(); - for (unsigned i = 0; i < CollapsedNum; ++i) - Sub.push_back(Record.readSubExpr()); - D->setPrivateCounters(Sub); - Sub.clear(); - for (unsigned i = 0; i < CollapsedNum; ++i) - Sub.push_back(Record.readSubExpr()); - D->setInits(Sub); - Sub.clear(); - for (unsigned i = 0; i < CollapsedNum; ++i) - Sub.push_back(Record.readSubExpr()); - D->setUpdates(Sub); - Sub.clear(); - for (unsigned i = 0; i < CollapsedNum; ++i) - Sub.push_back(Record.readSubExpr()); - D->setFinals(Sub); -} - -void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) { - VisitStmt(D); - // The NumClauses field was read in ReadStmtFromStream. - Record.skipInts(1); - VisitOMPExecutableDirective(D); - D->setHasCancel(Record.readInt()); -} - -void ASTStmtReader::VisitOMPSimdDirective(OMPSimdDirective *D) { - VisitOMPLoopDirective(D); -} - -void ASTStmtReader::VisitOMPForDirective(OMPForDirective *D) { - VisitOMPLoopDirective(D); - D->setHasCancel(Record.readInt()); -} - -void ASTStmtReader::VisitOMPForSimdDirective(OMPForSimdDirective *D) { - VisitOMPLoopDirective(D); -} - -void ASTStmtReader::VisitOMPSectionsDirective(OMPSectionsDirective *D) { - VisitStmt(D); - // The NumClauses field was read in ReadStmtFromStream. - Record.skipInts(1); - VisitOMPExecutableDirective(D); - D->setHasCancel(Record.readInt()); -} - -void ASTStmtReader::VisitOMPSectionDirective(OMPSectionDirective *D) { - VisitStmt(D); - VisitOMPExecutableDirective(D); - D->setHasCancel(Record.readInt()); -} - -void ASTStmtReader::VisitOMPSingleDirective(OMPSingleDirective *D) { - VisitStmt(D); - // The NumClauses field was read in ReadStmtFromStream. - Record.skipInts(1); - VisitOMPExecutableDirective(D); -} - -void ASTStmtReader::VisitOMPMasterDirective(OMPMasterDirective *D) { - VisitStmt(D); - VisitOMPExecutableDirective(D); -} - -void ASTStmtReader::VisitOMPCriticalDirective(OMPCriticalDirective *D) { - VisitStmt(D); - // The NumClauses field was read in ReadStmtFromStream. - Record.skipInts(1); - VisitOMPExecutableDirective(D); - ReadDeclarationNameInfo(D->DirName); -} - -void ASTStmtReader::VisitOMPParallelForDirective(OMPParallelForDirective *D) { - VisitOMPLoopDirective(D); - D->setHasCancel(Record.readInt()); -} - -void ASTStmtReader::VisitOMPParallelForSimdDirective( - OMPParallelForSimdDirective *D) { - VisitOMPLoopDirective(D); -} - -void ASTStmtReader::VisitOMPParallelSectionsDirective( - OMPParallelSectionsDirective *D) { - VisitStmt(D); - // The NumClauses field was read in ReadStmtFromStream. - Record.skipInts(1); - VisitOMPExecutableDirective(D); - D->setHasCancel(Record.readInt()); -} - -void ASTStmtReader::VisitOMPTaskDirective(OMPTaskDirective *D) { - VisitStmt(D); - // The NumClauses field was read in ReadStmtFromStream. - Record.skipInts(1); - VisitOMPExecutableDirective(D); - D->setHasCancel(Record.readInt()); -} - -void ASTStmtReader::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) { - VisitStmt(D); - VisitOMPExecutableDirective(D); -} - -void ASTStmtReader::VisitOMPBarrierDirective(OMPBarrierDirective *D) { - VisitStmt(D); - VisitOMPExecutableDirective(D); -} - -void ASTStmtReader::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) { - VisitStmt(D); - VisitOMPExecutableDirective(D); -} - -void ASTStmtReader::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *D) { - VisitStmt(D); - // The NumClauses field was read in ReadStmtFromStream. - Record.skipInts(1); - VisitOMPExecutableDirective(D); - D->setReductionRef(Record.readSubExpr()); -} - -void ASTStmtReader::VisitOMPFlushDirective(OMPFlushDirective *D) { - VisitStmt(D); - // The NumClauses field was read in ReadStmtFromStream. - Record.skipInts(1); - VisitOMPExecutableDirective(D); -} - -void ASTStmtReader::VisitOMPOrderedDirective(OMPOrderedDirective *D) { - VisitStmt(D); - // The NumClauses field was read in ReadStmtFromStream. - Record.skipInts(1); - VisitOMPExecutableDirective(D); -} - -void ASTStmtReader::VisitOMPAtomicDirective(OMPAtomicDirective *D) { - VisitStmt(D); - // The NumClauses field was read in ReadStmtFromStream. - Record.skipInts(1); - VisitOMPExecutableDirective(D); - D->setX(Record.readSubExpr()); - D->setV(Record.readSubExpr()); - D->setExpr(Record.readSubExpr()); - D->setUpdateExpr(Record.readSubExpr()); - D->IsXLHSInRHSPart = Record.readInt() != 0; - D->IsPostfixUpdate = Record.readInt() != 0; -} - -void ASTStmtReader::VisitOMPTargetDirective(OMPTargetDirective *D) { - VisitStmt(D); - // The NumClauses field was read in ReadStmtFromStream. - Record.skipInts(1); - VisitOMPExecutableDirective(D); -} - -void ASTStmtReader::VisitOMPTargetDataDirective(OMPTargetDataDirective *D) { - VisitStmt(D); - Record.skipInts(1); - VisitOMPExecutableDirective(D); -} - -void ASTStmtReader::VisitOMPTargetEnterDataDirective( - OMPTargetEnterDataDirective *D) { - VisitStmt(D); - Record.skipInts(1); - VisitOMPExecutableDirective(D); -} - -void ASTStmtReader::VisitOMPTargetExitDataDirective( - OMPTargetExitDataDirective *D) { - VisitStmt(D); - Record.skipInts(1); - VisitOMPExecutableDirective(D); -} - -void ASTStmtReader::VisitOMPTargetParallelDirective( - OMPTargetParallelDirective *D) { - VisitStmt(D); - Record.skipInts(1); - VisitOMPExecutableDirective(D); -} - -void ASTStmtReader::VisitOMPTargetParallelForDirective( - OMPTargetParallelForDirective *D) { - VisitOMPLoopDirective(D); - D->setHasCancel(Record.readInt()); -} - -void ASTStmtReader::VisitOMPTeamsDirective(OMPTeamsDirective *D) { - VisitStmt(D); - // The NumClauses field was read in ReadStmtFromStream. - Record.skipInts(1); - VisitOMPExecutableDirective(D); -} - -void ASTStmtReader::VisitOMPCancellationPointDirective( - OMPCancellationPointDirective *D) { - VisitStmt(D); - VisitOMPExecutableDirective(D); - D->setCancelRegion(static_cast<OpenMPDirectiveKind>(Record.readInt())); -} - -void ASTStmtReader::VisitOMPCancelDirective(OMPCancelDirective *D) { - VisitStmt(D); - // The NumClauses field was read in ReadStmtFromStream. - Record.skipInts(1); - VisitOMPExecutableDirective(D); - D->setCancelRegion(static_cast<OpenMPDirectiveKind>(Record.readInt())); -} - -void ASTStmtReader::VisitOMPTaskLoopDirective(OMPTaskLoopDirective *D) { - VisitOMPLoopDirective(D); -} - -void ASTStmtReader::VisitOMPTaskLoopSimdDirective(OMPTaskLoopSimdDirective *D) { - VisitOMPLoopDirective(D); -} - -void ASTStmtReader::VisitOMPDistributeDirective(OMPDistributeDirective *D) { - VisitOMPLoopDirective(D); -} - -void ASTStmtReader::VisitOMPTargetUpdateDirective(OMPTargetUpdateDirective *D) { - VisitStmt(D); - Record.skipInts(1); - VisitOMPExecutableDirective(D); -} - -void ASTStmtReader::VisitOMPDistributeParallelForDirective( - OMPDistributeParallelForDirective *D) { - VisitOMPLoopDirective(D); - D->setHasCancel(Record.readInt()); -} - -void ASTStmtReader::VisitOMPDistributeParallelForSimdDirective( - OMPDistributeParallelForSimdDirective *D) { - VisitOMPLoopDirective(D); -} - -void ASTStmtReader::VisitOMPDistributeSimdDirective( - OMPDistributeSimdDirective *D) { - VisitOMPLoopDirective(D); -} - -void ASTStmtReader::VisitOMPTargetParallelForSimdDirective( - OMPTargetParallelForSimdDirective *D) { - VisitOMPLoopDirective(D); -} - -void ASTStmtReader::VisitOMPTargetSimdDirective(OMPTargetSimdDirective *D) { - VisitOMPLoopDirective(D); -} - -void ASTStmtReader::VisitOMPTeamsDistributeDirective( - OMPTeamsDistributeDirective *D) { - VisitOMPLoopDirective(D); -} - -void ASTStmtReader::VisitOMPTeamsDistributeSimdDirective( - OMPTeamsDistributeSimdDirective *D) { - VisitOMPLoopDirective(D); -} - -void ASTStmtReader::VisitOMPTeamsDistributeParallelForSimdDirective( - OMPTeamsDistributeParallelForSimdDirective *D) { - VisitOMPLoopDirective(D); -} - -void ASTStmtReader::VisitOMPTeamsDistributeParallelForDirective( - OMPTeamsDistributeParallelForDirective *D) { - VisitOMPLoopDirective(D); - D->setHasCancel(Record.readInt()); -} - -void ASTStmtReader::VisitOMPTargetTeamsDirective(OMPTargetTeamsDirective *D) { - VisitStmt(D); - // The NumClauses field was read in ReadStmtFromStream. - Record.skipInts(1); - VisitOMPExecutableDirective(D); -} - -void ASTStmtReader::VisitOMPTargetTeamsDistributeDirective( - OMPTargetTeamsDistributeDirective *D) { - VisitOMPLoopDirective(D); -} - -void ASTStmtReader::VisitOMPTargetTeamsDistributeParallelForDirective( - OMPTargetTeamsDistributeParallelForDirective *D) { - VisitOMPLoopDirective(D); - D->setHasCancel(Record.readInt()); -} - -void ASTStmtReader::VisitOMPTargetTeamsDistributeParallelForSimdDirective( - OMPTargetTeamsDistributeParallelForSimdDirective *D) { - VisitOMPLoopDirective(D); -} - -void ASTStmtReader::VisitOMPTargetTeamsDistributeSimdDirective( - OMPTargetTeamsDistributeSimdDirective *D) { - VisitOMPLoopDirective(D); -} - -//===----------------------------------------------------------------------===// -// ASTReader Implementation -//===----------------------------------------------------------------------===// - -Stmt *ASTReader::ReadStmt(ModuleFile &F) { - switch (ReadingKind) { - case Read_None: - llvm_unreachable("should not call this when not reading anything"); - case Read_Decl: - case Read_Type: - return ReadStmtFromStream(F); - case Read_Stmt: - return ReadSubStmt(); - } - - llvm_unreachable("ReadingKind not set ?"); -} - -Expr *ASTReader::ReadExpr(ModuleFile &F) { - return cast_or_null<Expr>(ReadStmt(F)); -} - -Expr *ASTReader::ReadSubExpr() { - return cast_or_null<Expr>(ReadSubStmt()); -} - -// Within the bitstream, expressions are stored in Reverse Polish -// Notation, with each of the subexpressions preceding the -// expression they are stored in. Subexpressions are stored from last to first. -// To evaluate expressions, we continue reading expressions and placing them on -// the stack, with expressions having operands removing those operands from the -// stack. Evaluation terminates when we see a STMT_STOP record, and -// the single remaining expression on the stack is our result. -Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { - ReadingKindTracker ReadingKind(Read_Stmt, *this); - llvm::BitstreamCursor &Cursor = F.DeclsCursor; - - // Map of offset to previously deserialized stmt. The offset points - // just after the stmt record. - llvm::DenseMap<uint64_t, Stmt *> StmtEntries; - -#ifndef NDEBUG - unsigned PrevNumStmts = StmtStack.size(); -#endif - - ASTRecordReader Record(*this, F); - ASTStmtReader Reader(Record, Cursor); - Stmt::EmptyShell Empty; - - while (true) { - llvm::BitstreamEntry Entry = Cursor.advanceSkippingSubblocks(); - - switch (Entry.Kind) { - case llvm::BitstreamEntry::SubBlock: // Handled for us already. - case llvm::BitstreamEntry::Error: - Error("malformed block record in AST file"); - return nullptr; - case llvm::BitstreamEntry::EndBlock: - goto Done; - case llvm::BitstreamEntry::Record: - // The interesting case. - break; - } - - ASTContext &Context = getContext(); - Stmt *S = nullptr; - bool Finished = false; - bool IsStmtReference = false; - switch ((StmtCode)Record.readRecord(Cursor, Entry.ID)) { - case STMT_STOP: - Finished = true; - break; - - case STMT_REF_PTR: - IsStmtReference = true; - assert(StmtEntries.find(Record[0]) != StmtEntries.end() && - "No stmt was recorded for this offset reference!"); - S = StmtEntries[Record.readInt()]; - break; - - case STMT_NULL_PTR: - S = nullptr; - break; - - case STMT_NULL: - S = new (Context) NullStmt(Empty); - break; - - case STMT_COMPOUND: - S = CompoundStmt::CreateEmpty( - Context, /*NumStmts=*/Record[ASTStmtReader::NumStmtFields]); - break; - - case STMT_CASE: - S = CaseStmt::CreateEmpty( - Context, - /*CaseStmtIsGNURange*/ Record[ASTStmtReader::NumStmtFields + 3]); - break; - - case STMT_DEFAULT: - S = new (Context) DefaultStmt(Empty); - break; - - case STMT_LABEL: - S = new (Context) LabelStmt(Empty); - break; - - case STMT_ATTRIBUTED: - S = AttributedStmt::CreateEmpty( - Context, - /*NumAttrs*/Record[ASTStmtReader::NumStmtFields]); - break; - - case STMT_IF: - S = IfStmt::CreateEmpty( - Context, - /* HasElse=*/Record[ASTStmtReader::NumStmtFields + 1], - /* HasVar=*/Record[ASTStmtReader::NumStmtFields + 2], - /* HasInit=*/Record[ASTStmtReader::NumStmtFields + 3]); - break; - - case STMT_SWITCH: - S = SwitchStmt::CreateEmpty( - Context, - /* HasInit=*/Record[ASTStmtReader::NumStmtFields], - /* HasVar=*/Record[ASTStmtReader::NumStmtFields + 1]); - break; - - case STMT_WHILE: - S = WhileStmt::CreateEmpty( - Context, - /* HasVar=*/Record[ASTStmtReader::NumStmtFields]); - break; - - case STMT_DO: - S = new (Context) DoStmt(Empty); - break; - - case STMT_FOR: - S = new (Context) ForStmt(Empty); - break; - - case STMT_GOTO: - S = new (Context) GotoStmt(Empty); - break; - - case STMT_INDIRECT_GOTO: - S = new (Context) IndirectGotoStmt(Empty); - break; - - case STMT_CONTINUE: - S = new (Context) ContinueStmt(Empty); - break; - - case STMT_BREAK: - S = new (Context) BreakStmt(Empty); - break; - - case STMT_RETURN: - S = ReturnStmt::CreateEmpty( - Context, /* HasNRVOCandidate=*/Record[ASTStmtReader::NumStmtFields]); - break; - - case STMT_DECL: - S = new (Context) DeclStmt(Empty); - break; - - case STMT_GCCASM: - S = new (Context) GCCAsmStmt(Empty); - break; - - case STMT_MSASM: - S = new (Context) MSAsmStmt(Empty); - break; - - case STMT_CAPTURED: - S = CapturedStmt::CreateDeserialized( - Context, Record[ASTStmtReader::NumStmtFields]); - break; - - case EXPR_CONSTANT: - S = new (Context) ConstantExpr(Empty); - break; - - case EXPR_PREDEFINED: - S = PredefinedExpr::CreateEmpty( - Context, - /*HasFunctionName*/ Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_DECL_REF: - S = DeclRefExpr::CreateEmpty( - Context, - /*HasQualifier=*/Record[ASTStmtReader::NumExprFields], - /*HasFoundDecl=*/Record[ASTStmtReader::NumExprFields + 1], - /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields + 2], - /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 2] ? - Record[ASTStmtReader::NumExprFields + 5] : 0); - break; - - case EXPR_INTEGER_LITERAL: - S = IntegerLiteral::Create(Context, Empty); - break; - - case EXPR_FLOATING_LITERAL: - S = FloatingLiteral::Create(Context, Empty); - break; - - case EXPR_IMAGINARY_LITERAL: - S = new (Context) ImaginaryLiteral(Empty); - break; - - case EXPR_STRING_LITERAL: - S = StringLiteral::CreateEmpty( - Context, - /* NumConcatenated=*/Record[ASTStmtReader::NumExprFields], - /* Length=*/Record[ASTStmtReader::NumExprFields + 1], - /* CharByteWidth=*/Record[ASTStmtReader::NumExprFields + 2]); - break; - - case EXPR_CHARACTER_LITERAL: - S = new (Context) CharacterLiteral(Empty); - break; - - case EXPR_PAREN: - S = new (Context) ParenExpr(Empty); - break; - - case EXPR_PAREN_LIST: - S = ParenListExpr::CreateEmpty( - Context, - /* NumExprs=*/Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_UNARY_OPERATOR: - S = new (Context) UnaryOperator(Empty); - break; - - case EXPR_OFFSETOF: - S = OffsetOfExpr::CreateEmpty(Context, - Record[ASTStmtReader::NumExprFields], - Record[ASTStmtReader::NumExprFields + 1]); - break; - - case EXPR_SIZEOF_ALIGN_OF: - S = new (Context) UnaryExprOrTypeTraitExpr(Empty); - break; - - case EXPR_ARRAY_SUBSCRIPT: - S = new (Context) ArraySubscriptExpr(Empty); - break; - - case EXPR_OMP_ARRAY_SECTION: - S = new (Context) OMPArraySectionExpr(Empty); - break; - - case EXPR_CALL: - S = CallExpr::CreateEmpty( - Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty); - break; - - case EXPR_MEMBER: { - // We load everything here and fully initialize it at creation. - // That way we can use MemberExpr::Create and don't have to duplicate its - // logic with a MemberExpr::CreateEmpty. - - assert(Record.getIdx() == 0); - NestedNameSpecifierLoc QualifierLoc; - if (Record.readInt()) { // HasQualifier. - QualifierLoc = Record.readNestedNameSpecifierLoc(); - } - - SourceLocation TemplateKWLoc; - TemplateArgumentListInfo ArgInfo; - bool HasTemplateKWAndArgsInfo = Record.readInt(); - if (HasTemplateKWAndArgsInfo) { - TemplateKWLoc = Record.readSourceLocation(); - unsigned NumTemplateArgs = Record.readInt(); - ArgInfo.setLAngleLoc(Record.readSourceLocation()); - ArgInfo.setRAngleLoc(Record.readSourceLocation()); - for (unsigned i = 0; i != NumTemplateArgs; ++i) - ArgInfo.addArgument(Record.readTemplateArgumentLoc()); - } - - bool HadMultipleCandidates = Record.readInt(); - - auto *FoundD = Record.readDeclAs<NamedDecl>(); - auto AS = (AccessSpecifier)Record.readInt(); - DeclAccessPair FoundDecl = DeclAccessPair::make(FoundD, AS); - - QualType T = Record.readType(); - auto VK = static_cast<ExprValueKind>(Record.readInt()); - auto OK = static_cast<ExprObjectKind>(Record.readInt()); - Expr *Base = ReadSubExpr(); - auto *MemberD = Record.readDeclAs<ValueDecl>(); - SourceLocation MemberLoc = Record.readSourceLocation(); - DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc); - bool IsArrow = Record.readInt(); - SourceLocation OperatorLoc = Record.readSourceLocation(); - - S = MemberExpr::Create(Context, Base, IsArrow, OperatorLoc, QualifierLoc, - TemplateKWLoc, MemberD, FoundDecl, MemberNameInfo, - HasTemplateKWAndArgsInfo ? &ArgInfo : nullptr, T, - VK, OK); - Record.readDeclarationNameLoc(cast<MemberExpr>(S)->MemberDNLoc, - MemberD->getDeclName()); - if (HadMultipleCandidates) - cast<MemberExpr>(S)->setHadMultipleCandidates(true); - break; - } - - case EXPR_BINARY_OPERATOR: - S = new (Context) BinaryOperator(Empty); - break; - - case EXPR_COMPOUND_ASSIGN_OPERATOR: - S = new (Context) CompoundAssignOperator(Empty); - break; - - case EXPR_CONDITIONAL_OPERATOR: - S = new (Context) ConditionalOperator(Empty); - break; - - case EXPR_BINARY_CONDITIONAL_OPERATOR: - S = new (Context) BinaryConditionalOperator(Empty); - break; - - case EXPR_IMPLICIT_CAST: - S = ImplicitCastExpr::CreateEmpty(Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_CSTYLE_CAST: - S = CStyleCastExpr::CreateEmpty(Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_COMPOUND_LITERAL: - S = new (Context) CompoundLiteralExpr(Empty); - break; - - case EXPR_EXT_VECTOR_ELEMENT: - S = new (Context) ExtVectorElementExpr(Empty); - break; - - case EXPR_INIT_LIST: - S = new (Context) InitListExpr(Empty); - break; - - case EXPR_DESIGNATED_INIT: - S = DesignatedInitExpr::CreateEmpty(Context, - Record[ASTStmtReader::NumExprFields] - 1); - - break; - - case EXPR_DESIGNATED_INIT_UPDATE: - S = new (Context) DesignatedInitUpdateExpr(Empty); - break; - - case EXPR_IMPLICIT_VALUE_INIT: - S = new (Context) ImplicitValueInitExpr(Empty); - break; - - case EXPR_NO_INIT: - S = new (Context) NoInitExpr(Empty); - break; - - case EXPR_ARRAY_INIT_LOOP: - S = new (Context) ArrayInitLoopExpr(Empty); - break; - - case EXPR_ARRAY_INIT_INDEX: - S = new (Context) ArrayInitIndexExpr(Empty); - break; - - case EXPR_VA_ARG: - S = new (Context) VAArgExpr(Empty); - break; - - case EXPR_ADDR_LABEL: - S = new (Context) AddrLabelExpr(Empty); - break; - - case EXPR_STMT: - S = new (Context) StmtExpr(Empty); - break; - - case EXPR_CHOOSE: - S = new (Context) ChooseExpr(Empty); - break; - - case EXPR_GNU_NULL: - S = new (Context) GNUNullExpr(Empty); - break; - - case EXPR_SHUFFLE_VECTOR: - S = new (Context) ShuffleVectorExpr(Empty); - break; - - case EXPR_CONVERT_VECTOR: - S = new (Context) ConvertVectorExpr(Empty); - break; - - case EXPR_BLOCK: - S = new (Context) BlockExpr(Empty); - break; - - case EXPR_GENERIC_SELECTION: - S = new (Context) GenericSelectionExpr(Empty); - break; - - case EXPR_OBJC_STRING_LITERAL: - S = new (Context) ObjCStringLiteral(Empty); - break; - - case EXPR_OBJC_BOXED_EXPRESSION: - S = new (Context) ObjCBoxedExpr(Empty); - break; - - case EXPR_OBJC_ARRAY_LITERAL: - S = ObjCArrayLiteral::CreateEmpty(Context, - Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_OBJC_DICTIONARY_LITERAL: - S = ObjCDictionaryLiteral::CreateEmpty(Context, - Record[ASTStmtReader::NumExprFields], - Record[ASTStmtReader::NumExprFields + 1]); - break; - - case EXPR_OBJC_ENCODE: - S = new (Context) ObjCEncodeExpr(Empty); - break; - - case EXPR_OBJC_SELECTOR_EXPR: - S = new (Context) ObjCSelectorExpr(Empty); - break; - - case EXPR_OBJC_PROTOCOL_EXPR: - S = new (Context) ObjCProtocolExpr(Empty); - break; - - case EXPR_OBJC_IVAR_REF_EXPR: - S = new (Context) ObjCIvarRefExpr(Empty); - break; - - case EXPR_OBJC_PROPERTY_REF_EXPR: - S = new (Context) ObjCPropertyRefExpr(Empty); - break; - - case EXPR_OBJC_SUBSCRIPT_REF_EXPR: - S = new (Context) ObjCSubscriptRefExpr(Empty); - break; - - case EXPR_OBJC_KVC_REF_EXPR: - llvm_unreachable("mismatching AST file"); - - case EXPR_OBJC_MESSAGE_EXPR: - S = ObjCMessageExpr::CreateEmpty(Context, - Record[ASTStmtReader::NumExprFields], - Record[ASTStmtReader::NumExprFields + 1]); - break; - - case EXPR_OBJC_ISA: - S = new (Context) ObjCIsaExpr(Empty); - break; - - case EXPR_OBJC_INDIRECT_COPY_RESTORE: - S = new (Context) ObjCIndirectCopyRestoreExpr(Empty); - break; - - case EXPR_OBJC_BRIDGED_CAST: - S = new (Context) ObjCBridgedCastExpr(Empty); - break; - - case STMT_OBJC_FOR_COLLECTION: - S = new (Context) ObjCForCollectionStmt(Empty); - break; - - case STMT_OBJC_CATCH: - S = new (Context) ObjCAtCatchStmt(Empty); - break; - - case STMT_OBJC_FINALLY: - S = new (Context) ObjCAtFinallyStmt(Empty); - break; - - case STMT_OBJC_AT_TRY: - S = ObjCAtTryStmt::CreateEmpty(Context, - Record[ASTStmtReader::NumStmtFields], - Record[ASTStmtReader::NumStmtFields + 1]); - break; - - case STMT_OBJC_AT_SYNCHRONIZED: - S = new (Context) ObjCAtSynchronizedStmt(Empty); - break; - - case STMT_OBJC_AT_THROW: - S = new (Context) ObjCAtThrowStmt(Empty); - break; - - case STMT_OBJC_AUTORELEASE_POOL: - S = new (Context) ObjCAutoreleasePoolStmt(Empty); - break; - - case EXPR_OBJC_BOOL_LITERAL: - S = new (Context) ObjCBoolLiteralExpr(Empty); - break; - - case EXPR_OBJC_AVAILABILITY_CHECK: - S = new (Context) ObjCAvailabilityCheckExpr(Empty); - break; - - case STMT_SEH_LEAVE: - S = new (Context) SEHLeaveStmt(Empty); - break; - - case STMT_SEH_EXCEPT: - S = new (Context) SEHExceptStmt(Empty); - break; - - case STMT_SEH_FINALLY: - S = new (Context) SEHFinallyStmt(Empty); - break; - - case STMT_SEH_TRY: - S = new (Context) SEHTryStmt(Empty); - break; - - case STMT_CXX_CATCH: - S = new (Context) CXXCatchStmt(Empty); - break; - - case STMT_CXX_TRY: - S = CXXTryStmt::Create(Context, Empty, - /*NumHandlers=*/Record[ASTStmtReader::NumStmtFields]); - break; - - case STMT_CXX_FOR_RANGE: - S = new (Context) CXXForRangeStmt(Empty); - break; - - case STMT_MS_DEPENDENT_EXISTS: - S = new (Context) MSDependentExistsStmt(SourceLocation(), true, - NestedNameSpecifierLoc(), - DeclarationNameInfo(), - nullptr); - break; - - case STMT_OMP_PARALLEL_DIRECTIVE: - S = - OMPParallelDirective::CreateEmpty(Context, - Record[ASTStmtReader::NumStmtFields], - Empty); - break; - - case STMT_OMP_SIMD_DIRECTIVE: { - unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; - unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPSimdDirective::CreateEmpty(Context, NumClauses, - CollapsedNum, Empty); - break; - } - - case STMT_OMP_FOR_DIRECTIVE: { - unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; - unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPForDirective::CreateEmpty(Context, NumClauses, CollapsedNum, - Empty); - break; - } - - case STMT_OMP_FOR_SIMD_DIRECTIVE: { - unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; - unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPForSimdDirective::CreateEmpty(Context, NumClauses, CollapsedNum, - Empty); - break; - } - - case STMT_OMP_SECTIONS_DIRECTIVE: - S = OMPSectionsDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_SECTION_DIRECTIVE: - S = OMPSectionDirective::CreateEmpty(Context, Empty); - break; - - case STMT_OMP_SINGLE_DIRECTIVE: - S = OMPSingleDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_MASTER_DIRECTIVE: - S = OMPMasterDirective::CreateEmpty(Context, Empty); - break; - - case STMT_OMP_CRITICAL_DIRECTIVE: - S = OMPCriticalDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_PARALLEL_FOR_DIRECTIVE: { - unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; - unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPParallelForDirective::CreateEmpty(Context, NumClauses, - CollapsedNum, Empty); - break; - } - - case STMT_OMP_PARALLEL_FOR_SIMD_DIRECTIVE: { - unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; - unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPParallelForSimdDirective::CreateEmpty(Context, NumClauses, - CollapsedNum, Empty); - break; - } - - case STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE: - S = OMPParallelSectionsDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_TASK_DIRECTIVE: - S = OMPTaskDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_TASKYIELD_DIRECTIVE: - S = OMPTaskyieldDirective::CreateEmpty(Context, Empty); - break; - - case STMT_OMP_BARRIER_DIRECTIVE: - S = OMPBarrierDirective::CreateEmpty(Context, Empty); - break; - - case STMT_OMP_TASKWAIT_DIRECTIVE: - S = OMPTaskwaitDirective::CreateEmpty(Context, Empty); - break; - - case STMT_OMP_TASKGROUP_DIRECTIVE: - S = OMPTaskgroupDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_FLUSH_DIRECTIVE: - S = OMPFlushDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_ORDERED_DIRECTIVE: - S = OMPOrderedDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_ATOMIC_DIRECTIVE: - S = OMPAtomicDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_TARGET_DIRECTIVE: - S = OMPTargetDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_TARGET_DATA_DIRECTIVE: - S = OMPTargetDataDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_TARGET_ENTER_DATA_DIRECTIVE: - S = OMPTargetEnterDataDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_TARGET_EXIT_DATA_DIRECTIVE: - S = OMPTargetExitDataDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_TARGET_PARALLEL_DIRECTIVE: - S = OMPTargetParallelDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_TARGET_PARALLEL_FOR_DIRECTIVE: { - unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; - unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPTargetParallelForDirective::CreateEmpty(Context, NumClauses, - CollapsedNum, Empty); - break; - } - - case STMT_OMP_TARGET_UPDATE_DIRECTIVE: - S = OMPTargetUpdateDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_TEAMS_DIRECTIVE: - S = OMPTeamsDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_CANCELLATION_POINT_DIRECTIVE: - S = OMPCancellationPointDirective::CreateEmpty(Context, Empty); - break; - - case STMT_OMP_CANCEL_DIRECTIVE: - S = OMPCancelDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_TASKLOOP_DIRECTIVE: { - unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; - unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPTaskLoopDirective::CreateEmpty(Context, NumClauses, CollapsedNum, - Empty); - break; - } - - case STMT_OMP_TASKLOOP_SIMD_DIRECTIVE: { - unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; - unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPTaskLoopSimdDirective::CreateEmpty(Context, NumClauses, - CollapsedNum, Empty); - break; - } - - case STMT_OMP_DISTRIBUTE_DIRECTIVE: { - unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; - unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPDistributeDirective::CreateEmpty(Context, NumClauses, CollapsedNum, - Empty); - break; - } - - case STMT_OMP_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE: { - unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; - unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPDistributeParallelForDirective::CreateEmpty(Context, NumClauses, - CollapsedNum, Empty); - break; - } - - case STMT_OMP_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE: { - unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; - unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPDistributeParallelForSimdDirective::CreateEmpty(Context, NumClauses, - CollapsedNum, - Empty); - break; - } - - case STMT_OMP_DISTRIBUTE_SIMD_DIRECTIVE: { - unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; - unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPDistributeSimdDirective::CreateEmpty(Context, NumClauses, - CollapsedNum, Empty); - break; - } - - case STMT_OMP_TARGET_PARALLEL_FOR_SIMD_DIRECTIVE: { - unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; - unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPTargetParallelForSimdDirective::CreateEmpty(Context, NumClauses, - CollapsedNum, Empty); - break; - } - - case STMT_OMP_TARGET_SIMD_DIRECTIVE: { - auto NumClauses = Record[ASTStmtReader::NumStmtFields]; - auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPTargetSimdDirective::CreateEmpty(Context, NumClauses, CollapsedNum, - Empty); - break; - } - - case STMT_OMP_TEAMS_DISTRIBUTE_DIRECTIVE: { - auto NumClauses = Record[ASTStmtReader::NumStmtFields]; - auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPTeamsDistributeDirective::CreateEmpty(Context, NumClauses, - CollapsedNum, Empty); - break; - } - - case STMT_OMP_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE: { - unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; - unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPTeamsDistributeSimdDirective::CreateEmpty(Context, NumClauses, - CollapsedNum, Empty); - break; - } - - case STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE: { - auto NumClauses = Record[ASTStmtReader::NumStmtFields]; - auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPTeamsDistributeParallelForSimdDirective::CreateEmpty( - Context, NumClauses, CollapsedNum, Empty); - break; - } - - case STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE: { - auto NumClauses = Record[ASTStmtReader::NumStmtFields]; - auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPTeamsDistributeParallelForDirective::CreateEmpty( - Context, NumClauses, CollapsedNum, Empty); - break; - } - - case STMT_OMP_TARGET_TEAMS_DIRECTIVE: - S = OMPTargetTeamsDirective::CreateEmpty( - Context, Record[ASTStmtReader::NumStmtFields], Empty); - break; - - case STMT_OMP_TARGET_TEAMS_DISTRIBUTE_DIRECTIVE: { - auto NumClauses = Record[ASTStmtReader::NumStmtFields]; - auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPTargetTeamsDistributeDirective::CreateEmpty(Context, NumClauses, - CollapsedNum, Empty); - break; - } - - case STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE: { - auto NumClauses = Record[ASTStmtReader::NumStmtFields]; - auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPTargetTeamsDistributeParallelForDirective::CreateEmpty( - Context, NumClauses, CollapsedNum, Empty); - break; - } - - case STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE: { - auto NumClauses = Record[ASTStmtReader::NumStmtFields]; - auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPTargetTeamsDistributeParallelForSimdDirective::CreateEmpty( - Context, NumClauses, CollapsedNum, Empty); - break; - } - - case STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE: { - auto NumClauses = Record[ASTStmtReader::NumStmtFields]; - auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; - S = OMPTargetTeamsDistributeSimdDirective::CreateEmpty( - Context, NumClauses, CollapsedNum, Empty); - break; - } - - case EXPR_CXX_OPERATOR_CALL: - S = CXXOperatorCallExpr::CreateEmpty( - Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty); - break; - - case EXPR_CXX_MEMBER_CALL: - S = CXXMemberCallExpr::CreateEmpty( - Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty); - break; - - case EXPR_CXX_CONSTRUCT: - S = CXXConstructExpr::CreateEmpty( - Context, - /* NumArgs=*/Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_CXX_INHERITED_CTOR_INIT: - S = new (Context) CXXInheritedCtorInitExpr(Empty); - break; - - case EXPR_CXX_TEMPORARY_OBJECT: - S = CXXTemporaryObjectExpr::CreateEmpty( - Context, - /* NumArgs=*/Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_CXX_STATIC_CAST: - S = CXXStaticCastExpr::CreateEmpty(Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_CXX_DYNAMIC_CAST: - S = CXXDynamicCastExpr::CreateEmpty(Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_CXX_REINTERPRET_CAST: - S = CXXReinterpretCastExpr::CreateEmpty(Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_CXX_CONST_CAST: - S = CXXConstCastExpr::CreateEmpty(Context); - break; - - case EXPR_CXX_FUNCTIONAL_CAST: - S = CXXFunctionalCastExpr::CreateEmpty(Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_USER_DEFINED_LITERAL: - S = UserDefinedLiteral::CreateEmpty( - Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty); - break; - - case EXPR_CXX_STD_INITIALIZER_LIST: - S = new (Context) CXXStdInitializerListExpr(Empty); - break; - - case EXPR_CXX_BOOL_LITERAL: - S = new (Context) CXXBoolLiteralExpr(Empty); - break; - - case EXPR_CXX_NULL_PTR_LITERAL: - S = new (Context) CXXNullPtrLiteralExpr(Empty); - break; - - case EXPR_CXX_TYPEID_EXPR: - S = new (Context) CXXTypeidExpr(Empty, true); - break; - - case EXPR_CXX_TYPEID_TYPE: - S = new (Context) CXXTypeidExpr(Empty, false); - break; - - case EXPR_CXX_UUIDOF_EXPR: - S = new (Context) CXXUuidofExpr(Empty, true); - break; - - case EXPR_CXX_PROPERTY_REF_EXPR: - S = new (Context) MSPropertyRefExpr(Empty); - break; - - case EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR: - S = new (Context) MSPropertySubscriptExpr(Empty); - break; - - case EXPR_CXX_UUIDOF_TYPE: - S = new (Context) CXXUuidofExpr(Empty, false); - break; - - case EXPR_CXX_THIS: - S = new (Context) CXXThisExpr(Empty); - break; - - case EXPR_CXX_THROW: - S = new (Context) CXXThrowExpr(Empty); - break; - - case EXPR_CXX_DEFAULT_ARG: - S = new (Context) CXXDefaultArgExpr(Empty); - break; - - case EXPR_CXX_DEFAULT_INIT: - S = new (Context) CXXDefaultInitExpr(Empty); - break; - - case EXPR_CXX_BIND_TEMPORARY: - S = new (Context) CXXBindTemporaryExpr(Empty); - break; - - case EXPR_CXX_SCALAR_VALUE_INIT: - S = new (Context) CXXScalarValueInitExpr(Empty); - break; - - case EXPR_CXX_NEW: - S = CXXNewExpr::CreateEmpty( - Context, - /*IsArray=*/Record[ASTStmtReader::NumExprFields], - /*HasInit=*/Record[ASTStmtReader::NumExprFields + 1], - /*NumPlacementArgs=*/Record[ASTStmtReader::NumExprFields + 2], - /*IsParenTypeId=*/Record[ASTStmtReader::NumExprFields + 3]); - break; - - case EXPR_CXX_DELETE: - S = new (Context) CXXDeleteExpr(Empty); - break; - - case EXPR_CXX_PSEUDO_DESTRUCTOR: - S = new (Context) CXXPseudoDestructorExpr(Empty); - break; - - case EXPR_EXPR_WITH_CLEANUPS: - S = ExprWithCleanups::Create(Context, Empty, - Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_CXX_DEPENDENT_SCOPE_MEMBER: - S = CXXDependentScopeMemberExpr::CreateEmpty( - Context, - /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields], - /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1], - /*HasFirstQualifierFoundInScope=*/ - Record[ASTStmtReader::NumExprFields + 2]); - break; - - case EXPR_CXX_DEPENDENT_SCOPE_DECL_REF: - S = DependentScopeDeclRefExpr::CreateEmpty(Context, - /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields], - /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] - ? Record[ASTStmtReader::NumExprFields + 1] - : 0); - break; - - case EXPR_CXX_UNRESOLVED_CONSTRUCT: - S = CXXUnresolvedConstructExpr::CreateEmpty(Context, - /*NumArgs=*/Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_CXX_UNRESOLVED_MEMBER: - S = UnresolvedMemberExpr::CreateEmpty( - Context, - /*NumResults=*/Record[ASTStmtReader::NumExprFields], - /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields + 1], - /*NumTemplateArgs=*/ - Record[ASTStmtReader::NumExprFields + 1] - ? Record[ASTStmtReader::NumExprFields + 2] - : 0); - break; - - case EXPR_CXX_UNRESOLVED_LOOKUP: - S = UnresolvedLookupExpr::CreateEmpty( - Context, - /*NumResults=*/Record[ASTStmtReader::NumExprFields], - /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields + 1], - /*NumTemplateArgs=*/ - Record[ASTStmtReader::NumExprFields + 1] - ? Record[ASTStmtReader::NumExprFields + 2] - : 0); - break; - - case EXPR_TYPE_TRAIT: - S = TypeTraitExpr::CreateDeserialized(Context, - Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_ARRAY_TYPE_TRAIT: - S = new (Context) ArrayTypeTraitExpr(Empty); - break; - - case EXPR_CXX_EXPRESSION_TRAIT: - S = new (Context) ExpressionTraitExpr(Empty); - break; - - case EXPR_CXX_NOEXCEPT: - S = new (Context) CXXNoexceptExpr(Empty); - break; - - case EXPR_PACK_EXPANSION: - S = new (Context) PackExpansionExpr(Empty); - break; - - case EXPR_SIZEOF_PACK: - S = SizeOfPackExpr::CreateDeserialized( - Context, - /*NumPartialArgs=*/Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_SUBST_NON_TYPE_TEMPLATE_PARM: - S = new (Context) SubstNonTypeTemplateParmExpr(Empty); - break; - - case EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK: - S = new (Context) SubstNonTypeTemplateParmPackExpr(Empty); - break; - - case EXPR_FUNCTION_PARM_PACK: - S = FunctionParmPackExpr::CreateEmpty(Context, - Record[ASTStmtReader::NumExprFields]); - break; - - case EXPR_MATERIALIZE_TEMPORARY: - S = new (Context) MaterializeTemporaryExpr(Empty); - break; - - case EXPR_CXX_FOLD: - S = new (Context) CXXFoldExpr(Empty); - break; - - case EXPR_OPAQUE_VALUE: - S = new (Context) OpaqueValueExpr(Empty); - break; - - case EXPR_CUDA_KERNEL_CALL: - S = CUDAKernelCallExpr::CreateEmpty( - Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty); - break; - - case EXPR_ASTYPE: - S = new (Context) AsTypeExpr(Empty); - break; - - case EXPR_PSEUDO_OBJECT: { - unsigned numSemanticExprs = Record[ASTStmtReader::NumExprFields]; - S = PseudoObjectExpr::Create(Context, Empty, numSemanticExprs); - break; - } - - case EXPR_ATOMIC: - S = new (Context) AtomicExpr(Empty); - break; - - case EXPR_LAMBDA: { - unsigned NumCaptures = Record[ASTStmtReader::NumExprFields]; - S = LambdaExpr::CreateDeserialized(Context, NumCaptures); - break; - } - - case STMT_COROUTINE_BODY: { - unsigned NumParams = Record[ASTStmtReader::NumStmtFields]; - S = CoroutineBodyStmt::Create(Context, Empty, NumParams); - break; - } - - case STMT_CORETURN: - S = new (Context) CoreturnStmt(Empty); - break; - - case EXPR_COAWAIT: - S = new (Context) CoawaitExpr(Empty); - break; - - case EXPR_COYIELD: - S = new (Context) CoyieldExpr(Empty); - break; - - case EXPR_DEPENDENT_COAWAIT: - S = new (Context) DependentCoawaitExpr(Empty); - break; - } - - // We hit a STMT_STOP, so we're done with this expression. - if (Finished) - break; - - ++NumStatementsRead; - - if (S && !IsStmtReference) { - Reader.Visit(S); - StmtEntries[Cursor.GetCurrentBitNo()] = S; - } - - assert(Record.getIdx() == Record.size() && - "Invalid deserialization of statement"); - StmtStack.push_back(S); - } -Done: - assert(StmtStack.size() > PrevNumStmts && "Read too many sub-stmts!"); - assert(StmtStack.size() == PrevNumStmts + 1 && "Extra expressions on stack!"); - return StmtStack.pop_back_val(); -} diff --git a/gnu/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/gnu/llvm/tools/clang/lib/Serialization/ASTWriter.cpp deleted file mode 100644 index 37adcb70640..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/ASTWriter.cpp +++ /dev/null @@ -1,6955 +0,0 @@ -//===- ASTWriter.cpp - AST File Writer ------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the ASTWriter class, which writes AST files. -// -//===----------------------------------------------------------------------===// - -#include "clang/Serialization/ASTWriter.h" -#include "ASTCommon.h" -#include "ASTReaderInternals.h" -#include "MultiOnDiskHashTable.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/ASTUnresolvedSet.h" -#include "clang/AST/Attr.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclBase.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclContextInternals.h" -#include "clang/AST/DeclFriend.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/DeclarationName.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/LambdaCapture.h" -#include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/RawCommentList.h" -#include "clang/AST/TemplateName.h" -#include "clang/AST/Type.h" -#include "clang/AST/TypeLocVisitor.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/DiagnosticOptions.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/FileSystemOptions.h" -#include "clang/Basic/IdentifierTable.h" -#include "clang/Basic/LLVM.h" -#include "clang/Basic/Lambda.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/MemoryBufferCache.h" -#include "clang/Basic/Module.h" -#include "clang/Basic/ObjCRuntime.h" -#include "clang/Basic/OpenCLOptions.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/SourceManagerInternals.h" -#include "clang/Basic/Specifiers.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/TargetOptions.h" -#include "clang/Basic/Version.h" -#include "clang/Lex/HeaderSearch.h" -#include "clang/Lex/HeaderSearchOptions.h" -#include "clang/Lex/MacroInfo.h" -#include "clang/Lex/ModuleMap.h" -#include "clang/Lex/PreprocessingRecord.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Lex/PreprocessorOptions.h" -#include "clang/Lex/Token.h" -#include "clang/Sema/IdentifierResolver.h" -#include "clang/Sema/ObjCMethodList.h" -#include "clang/Sema/Sema.h" -#include "clang/Sema/Weak.h" -#include "clang/Serialization/ASTReader.h" -#include "clang/Serialization/Module.h" -#include "clang/Serialization/ModuleFileExtension.h" -#include "clang/Serialization/SerializationDiagnostic.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/APSInt.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Hashing.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/ScopeExit.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Bitcode/BitCodes.h" -#include "llvm/Bitcode/BitstreamWriter.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compression.h" -#include "llvm/Support/DJB.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/EndianStream.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/OnDiskHashTable.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/SHA1.h" -#include "llvm/Support/VersionTuple.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <cstdint> -#include <cstdlib> -#include <cstring> -#include <ctime> -#include <deque> -#include <limits> -#include <memory> -#include <queue> -#include <tuple> -#include <utility> -#include <vector> - -using namespace clang; -using namespace clang::serialization; - -template <typename T, typename Allocator> -static StringRef bytes(const std::vector<T, Allocator> &v) { - if (v.empty()) return StringRef(); - return StringRef(reinterpret_cast<const char*>(&v[0]), - sizeof(T) * v.size()); -} - -template <typename T> -static StringRef bytes(const SmallVectorImpl<T> &v) { - return StringRef(reinterpret_cast<const char*>(v.data()), - sizeof(T) * v.size()); -} - -//===----------------------------------------------------------------------===// -// Type serialization -//===----------------------------------------------------------------------===// - -namespace clang { - - class ASTTypeWriter { - ASTWriter &Writer; - ASTRecordWriter Record; - - /// Type code that corresponds to the record generated. - TypeCode Code = static_cast<TypeCode>(0); - - /// Abbreviation to use for the record, if any. - unsigned AbbrevToUse = 0; - - public: - ASTTypeWriter(ASTWriter &Writer, ASTWriter::RecordDataImpl &Record) - : Writer(Writer), Record(Writer, Record) {} - - uint64_t Emit() { - return Record.Emit(Code, AbbrevToUse); - } - - void Visit(QualType T) { - if (T.hasLocalNonFastQualifiers()) { - Qualifiers Qs = T.getLocalQualifiers(); - Record.AddTypeRef(T.getLocalUnqualifiedType()); - Record.push_back(Qs.getAsOpaqueValue()); - Code = TYPE_EXT_QUAL; - AbbrevToUse = Writer.TypeExtQualAbbrev; - } else { - switch (T->getTypeClass()) { - // For all of the concrete, non-dependent types, call the - // appropriate visitor function. -#define TYPE(Class, Base) \ - case Type::Class: Visit##Class##Type(cast<Class##Type>(T)); break; -#define ABSTRACT_TYPE(Class, Base) -#include "clang/AST/TypeNodes.def" - } - } - } - - void VisitArrayType(const ArrayType *T); - void VisitFunctionType(const FunctionType *T); - void VisitTagType(const TagType *T); - -#define TYPE(Class, Base) void Visit##Class##Type(const Class##Type *T); -#define ABSTRACT_TYPE(Class, Base) -#include "clang/AST/TypeNodes.def" - }; - -} // namespace clang - -void ASTTypeWriter::VisitBuiltinType(const BuiltinType *T) { - llvm_unreachable("Built-in types are never serialized"); -} - -void ASTTypeWriter::VisitComplexType(const ComplexType *T) { - Record.AddTypeRef(T->getElementType()); - Code = TYPE_COMPLEX; -} - -void ASTTypeWriter::VisitPointerType(const PointerType *T) { - Record.AddTypeRef(T->getPointeeType()); - Code = TYPE_POINTER; -} - -void ASTTypeWriter::VisitDecayedType(const DecayedType *T) { - Record.AddTypeRef(T->getOriginalType()); - Code = TYPE_DECAYED; -} - -void ASTTypeWriter::VisitAdjustedType(const AdjustedType *T) { - Record.AddTypeRef(T->getOriginalType()); - Record.AddTypeRef(T->getAdjustedType()); - Code = TYPE_ADJUSTED; -} - -void ASTTypeWriter::VisitBlockPointerType(const BlockPointerType *T) { - Record.AddTypeRef(T->getPointeeType()); - Code = TYPE_BLOCK_POINTER; -} - -void ASTTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) { - Record.AddTypeRef(T->getPointeeTypeAsWritten()); - Record.push_back(T->isSpelledAsLValue()); - Code = TYPE_LVALUE_REFERENCE; -} - -void ASTTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) { - Record.AddTypeRef(T->getPointeeTypeAsWritten()); - Code = TYPE_RVALUE_REFERENCE; -} - -void ASTTypeWriter::VisitMemberPointerType(const MemberPointerType *T) { - Record.AddTypeRef(T->getPointeeType()); - Record.AddTypeRef(QualType(T->getClass(), 0)); - Code = TYPE_MEMBER_POINTER; -} - -void ASTTypeWriter::VisitArrayType(const ArrayType *T) { - Record.AddTypeRef(T->getElementType()); - Record.push_back(T->getSizeModifier()); // FIXME: stable values - Record.push_back(T->getIndexTypeCVRQualifiers()); // FIXME: stable values -} - -void ASTTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) { - VisitArrayType(T); - Record.AddAPInt(T->getSize()); - Code = TYPE_CONSTANT_ARRAY; -} - -void ASTTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) { - VisitArrayType(T); - Code = TYPE_INCOMPLETE_ARRAY; -} - -void ASTTypeWriter::VisitVariableArrayType(const VariableArrayType *T) { - VisitArrayType(T); - Record.AddSourceLocation(T->getLBracketLoc()); - Record.AddSourceLocation(T->getRBracketLoc()); - Record.AddStmt(T->getSizeExpr()); - Code = TYPE_VARIABLE_ARRAY; -} - -void ASTTypeWriter::VisitVectorType(const VectorType *T) { - Record.AddTypeRef(T->getElementType()); - Record.push_back(T->getNumElements()); - Record.push_back(T->getVectorKind()); - Code = TYPE_VECTOR; -} - -void ASTTypeWriter::VisitExtVectorType(const ExtVectorType *T) { - VisitVectorType(T); - Code = TYPE_EXT_VECTOR; -} - -void ASTTypeWriter::VisitFunctionType(const FunctionType *T) { - Record.AddTypeRef(T->getReturnType()); - FunctionType::ExtInfo C = T->getExtInfo(); - Record.push_back(C.getNoReturn()); - Record.push_back(C.getHasRegParm()); - Record.push_back(C.getRegParm()); - // FIXME: need to stabilize encoding of calling convention... - Record.push_back(C.getCC()); - Record.push_back(C.getProducesResult()); - Record.push_back(C.getNoCallerSavedRegs()); - Record.push_back(C.getNoCfCheck()); - - if (C.getHasRegParm() || C.getRegParm() || C.getProducesResult()) - AbbrevToUse = 0; -} - -void ASTTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { - VisitFunctionType(T); - Code = TYPE_FUNCTION_NO_PROTO; -} - -static void addExceptionSpec(const FunctionProtoType *T, - ASTRecordWriter &Record) { - Record.push_back(T->getExceptionSpecType()); - if (T->getExceptionSpecType() == EST_Dynamic) { - Record.push_back(T->getNumExceptions()); - for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) - Record.AddTypeRef(T->getExceptionType(I)); - } else if (isComputedNoexcept(T->getExceptionSpecType())) { - Record.AddStmt(T->getNoexceptExpr()); - } else if (T->getExceptionSpecType() == EST_Uninstantiated) { - Record.AddDeclRef(T->getExceptionSpecDecl()); - Record.AddDeclRef(T->getExceptionSpecTemplate()); - } else if (T->getExceptionSpecType() == EST_Unevaluated) { - Record.AddDeclRef(T->getExceptionSpecDecl()); - } -} - -void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) { - VisitFunctionType(T); - - Record.push_back(T->isVariadic()); - Record.push_back(T->hasTrailingReturn()); - Record.push_back(T->getTypeQuals().getAsOpaqueValue()); - Record.push_back(static_cast<unsigned>(T->getRefQualifier())); - addExceptionSpec(T, Record); - - Record.push_back(T->getNumParams()); - for (unsigned I = 0, N = T->getNumParams(); I != N; ++I) - Record.AddTypeRef(T->getParamType(I)); - - if (T->hasExtParameterInfos()) { - for (unsigned I = 0, N = T->getNumParams(); I != N; ++I) - Record.push_back(T->getExtParameterInfo(I).getOpaqueValue()); - } - - if (T->isVariadic() || T->hasTrailingReturn() || T->getTypeQuals() || - T->getRefQualifier() || T->getExceptionSpecType() != EST_None || - T->hasExtParameterInfos()) - AbbrevToUse = 0; - - Code = TYPE_FUNCTION_PROTO; -} - -void ASTTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) { - Record.AddDeclRef(T->getDecl()); - Code = TYPE_UNRESOLVED_USING; -} - -void ASTTypeWriter::VisitTypedefType(const TypedefType *T) { - Record.AddDeclRef(T->getDecl()); - assert(!T->isCanonicalUnqualified() && "Invalid typedef ?"); - Record.AddTypeRef(T->getCanonicalTypeInternal()); - Code = TYPE_TYPEDEF; -} - -void ASTTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) { - Record.AddStmt(T->getUnderlyingExpr()); - Code = TYPE_TYPEOF_EXPR; -} - -void ASTTypeWriter::VisitTypeOfType(const TypeOfType *T) { - Record.AddTypeRef(T->getUnderlyingType()); - Code = TYPE_TYPEOF; -} - -void ASTTypeWriter::VisitDecltypeType(const DecltypeType *T) { - Record.AddTypeRef(T->getUnderlyingType()); - Record.AddStmt(T->getUnderlyingExpr()); - Code = TYPE_DECLTYPE; -} - -void ASTTypeWriter::VisitUnaryTransformType(const UnaryTransformType *T) { - Record.AddTypeRef(T->getBaseType()); - Record.AddTypeRef(T->getUnderlyingType()); - Record.push_back(T->getUTTKind()); - Code = TYPE_UNARY_TRANSFORM; -} - -void ASTTypeWriter::VisitAutoType(const AutoType *T) { - Record.AddTypeRef(T->getDeducedType()); - Record.push_back((unsigned)T->getKeyword()); - if (T->getDeducedType().isNull()) - Record.push_back(T->isDependentType()); - Code = TYPE_AUTO; -} - -void ASTTypeWriter::VisitDeducedTemplateSpecializationType( - const DeducedTemplateSpecializationType *T) { - Record.AddTemplateName(T->getTemplateName()); - Record.AddTypeRef(T->getDeducedType()); - if (T->getDeducedType().isNull()) - Record.push_back(T->isDependentType()); - Code = TYPE_DEDUCED_TEMPLATE_SPECIALIZATION; -} - -void ASTTypeWriter::VisitTagType(const TagType *T) { - Record.push_back(T->isDependentType()); - Record.AddDeclRef(T->getDecl()->getCanonicalDecl()); - assert(!T->isBeingDefined() && - "Cannot serialize in the middle of a type definition"); -} - -void ASTTypeWriter::VisitRecordType(const RecordType *T) { - VisitTagType(T); - Code = TYPE_RECORD; -} - -void ASTTypeWriter::VisitEnumType(const EnumType *T) { - VisitTagType(T); - Code = TYPE_ENUM; -} - -void ASTTypeWriter::VisitAttributedType(const AttributedType *T) { - Record.AddTypeRef(T->getModifiedType()); - Record.AddTypeRef(T->getEquivalentType()); - Record.push_back(T->getAttrKind()); - Code = TYPE_ATTRIBUTED; -} - -void -ASTTypeWriter::VisitSubstTemplateTypeParmType( - const SubstTemplateTypeParmType *T) { - Record.AddTypeRef(QualType(T->getReplacedParameter(), 0)); - Record.AddTypeRef(T->getReplacementType()); - Code = TYPE_SUBST_TEMPLATE_TYPE_PARM; -} - -void -ASTTypeWriter::VisitSubstTemplateTypeParmPackType( - const SubstTemplateTypeParmPackType *T) { - Record.AddTypeRef(QualType(T->getReplacedParameter(), 0)); - Record.AddTemplateArgument(T->getArgumentPack()); - Code = TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK; -} - -void -ASTTypeWriter::VisitTemplateSpecializationType( - const TemplateSpecializationType *T) { - Record.push_back(T->isDependentType()); - Record.AddTemplateName(T->getTemplateName()); - Record.push_back(T->getNumArgs()); - for (const auto &ArgI : *T) - Record.AddTemplateArgument(ArgI); - Record.AddTypeRef(T->isTypeAlias() ? T->getAliasedType() - : T->isCanonicalUnqualified() - ? QualType() - : T->getCanonicalTypeInternal()); - Code = TYPE_TEMPLATE_SPECIALIZATION; -} - -void -ASTTypeWriter::VisitDependentSizedArrayType(const DependentSizedArrayType *T) { - VisitArrayType(T); - Record.AddStmt(T->getSizeExpr()); - Record.AddSourceRange(T->getBracketsRange()); - Code = TYPE_DEPENDENT_SIZED_ARRAY; -} - -void -ASTTypeWriter::VisitDependentSizedExtVectorType( - const DependentSizedExtVectorType *T) { - Record.AddTypeRef(T->getElementType()); - Record.AddStmt(T->getSizeExpr()); - Record.AddSourceLocation(T->getAttributeLoc()); - Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR; -} - -void ASTTypeWriter::VisitDependentVectorType(const DependentVectorType *T) { - Record.AddTypeRef(T->getElementType()); - Record.AddStmt(const_cast<Expr*>(T->getSizeExpr())); - Record.AddSourceLocation(T->getAttributeLoc()); - Record.push_back(T->getVectorKind()); - Code = TYPE_DEPENDENT_SIZED_VECTOR; -} - -void -ASTTypeWriter::VisitDependentAddressSpaceType( - const DependentAddressSpaceType *T) { - Record.AddTypeRef(T->getPointeeType()); - Record.AddStmt(T->getAddrSpaceExpr()); - Record.AddSourceLocation(T->getAttributeLoc()); - Code = TYPE_DEPENDENT_ADDRESS_SPACE; -} - -void -ASTTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) { - Record.push_back(T->getDepth()); - Record.push_back(T->getIndex()); - Record.push_back(T->isParameterPack()); - Record.AddDeclRef(T->getDecl()); - Code = TYPE_TEMPLATE_TYPE_PARM; -} - -void -ASTTypeWriter::VisitDependentNameType(const DependentNameType *T) { - Record.push_back(T->getKeyword()); - Record.AddNestedNameSpecifier(T->getQualifier()); - Record.AddIdentifierRef(T->getIdentifier()); - Record.AddTypeRef( - T->isCanonicalUnqualified() ? QualType() : T->getCanonicalTypeInternal()); - Code = TYPE_DEPENDENT_NAME; -} - -void -ASTTypeWriter::VisitDependentTemplateSpecializationType( - const DependentTemplateSpecializationType *T) { - Record.push_back(T->getKeyword()); - Record.AddNestedNameSpecifier(T->getQualifier()); - Record.AddIdentifierRef(T->getIdentifier()); - Record.push_back(T->getNumArgs()); - for (const auto &I : *T) - Record.AddTemplateArgument(I); - Code = TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION; -} - -void ASTTypeWriter::VisitPackExpansionType(const PackExpansionType *T) { - Record.AddTypeRef(T->getPattern()); - if (Optional<unsigned> NumExpansions = T->getNumExpansions()) - Record.push_back(*NumExpansions + 1); - else - Record.push_back(0); - Code = TYPE_PACK_EXPANSION; -} - -void ASTTypeWriter::VisitParenType(const ParenType *T) { - Record.AddTypeRef(T->getInnerType()); - Code = TYPE_PAREN; -} - -void ASTTypeWriter::VisitElaboratedType(const ElaboratedType *T) { - Record.push_back(T->getKeyword()); - Record.AddNestedNameSpecifier(T->getQualifier()); - Record.AddTypeRef(T->getNamedType()); - Record.AddDeclRef(T->getOwnedTagDecl()); - Code = TYPE_ELABORATED; -} - -void ASTTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) { - Record.AddDeclRef(T->getDecl()->getCanonicalDecl()); - Record.AddTypeRef(T->getInjectedSpecializationType()); - Code = TYPE_INJECTED_CLASS_NAME; -} - -void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { - Record.AddDeclRef(T->getDecl()->getCanonicalDecl()); - Code = TYPE_OBJC_INTERFACE; -} - -void ASTTypeWriter::VisitObjCTypeParamType(const ObjCTypeParamType *T) { - Record.AddDeclRef(T->getDecl()); - Record.push_back(T->getNumProtocols()); - for (const auto *I : T->quals()) - Record.AddDeclRef(I); - Code = TYPE_OBJC_TYPE_PARAM; -} - -void ASTTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) { - Record.AddTypeRef(T->getBaseType()); - Record.push_back(T->getTypeArgsAsWritten().size()); - for (auto TypeArg : T->getTypeArgsAsWritten()) - Record.AddTypeRef(TypeArg); - Record.push_back(T->getNumProtocols()); - for (const auto *I : T->quals()) - Record.AddDeclRef(I); - Record.push_back(T->isKindOfTypeAsWritten()); - Code = TYPE_OBJC_OBJECT; -} - -void -ASTTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { - Record.AddTypeRef(T->getPointeeType()); - Code = TYPE_OBJC_OBJECT_POINTER; -} - -void -ASTTypeWriter::VisitAtomicType(const AtomicType *T) { - Record.AddTypeRef(T->getValueType()); - Code = TYPE_ATOMIC; -} - -void -ASTTypeWriter::VisitPipeType(const PipeType *T) { - Record.AddTypeRef(T->getElementType()); - Record.push_back(T->isReadOnly()); - Code = TYPE_PIPE; -} - -namespace { - -class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> { - ASTRecordWriter &Record; - -public: - TypeLocWriter(ASTRecordWriter &Record) : Record(Record) {} - -#define ABSTRACT_TYPELOC(CLASS, PARENT) -#define TYPELOC(CLASS, PARENT) \ - void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc); -#include "clang/AST/TypeLocNodes.def" - - void VisitArrayTypeLoc(ArrayTypeLoc TyLoc); - void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc); -}; - -} // namespace - -void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { - // nothing to do -} - -void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { - Record.AddSourceLocation(TL.getBuiltinLoc()); - if (TL.needsExtraLocalData()) { - Record.push_back(TL.getWrittenTypeSpec()); - Record.push_back(TL.getWrittenSignSpec()); - Record.push_back(TL.getWrittenWidthSpec()); - Record.push_back(TL.hasModeAttr()); - } -} - -void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) { - Record.AddSourceLocation(TL.getStarLoc()); -} - -void TypeLocWriter::VisitDecayedTypeLoc(DecayedTypeLoc TL) { - // nothing to do -} - -void TypeLocWriter::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { - // nothing to do -} - -void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { - Record.AddSourceLocation(TL.getCaretLoc()); -} - -void TypeLocWriter::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { - Record.AddSourceLocation(TL.getAmpLoc()); -} - -void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { - Record.AddSourceLocation(TL.getAmpAmpLoc()); -} - -void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { - Record.AddSourceLocation(TL.getStarLoc()); - Record.AddTypeSourceInfo(TL.getClassTInfo()); -} - -void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) { - Record.AddSourceLocation(TL.getLBracketLoc()); - Record.AddSourceLocation(TL.getRBracketLoc()); - Record.push_back(TL.getSizeExpr() ? 1 : 0); - if (TL.getSizeExpr()) - Record.AddStmt(TL.getSizeExpr()); -} - -void TypeLocWriter::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} - -void TypeLocWriter::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} - -void TypeLocWriter::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} - -void TypeLocWriter::VisitDependentSizedArrayTypeLoc( - DependentSizedArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} - -void TypeLocWriter::VisitDependentAddressSpaceTypeLoc( - DependentAddressSpaceTypeLoc TL) { - Record.AddSourceLocation(TL.getAttrNameLoc()); - SourceRange range = TL.getAttrOperandParensRange(); - Record.AddSourceLocation(range.getBegin()); - Record.AddSourceLocation(range.getEnd()); - Record.AddStmt(TL.getAttrExprOperand()); -} - -void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc( - DependentSizedExtVectorTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitDependentVectorTypeLoc( - DependentVectorTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) { - Record.AddSourceLocation(TL.getLocalRangeBegin()); - Record.AddSourceLocation(TL.getLParenLoc()); - Record.AddSourceLocation(TL.getRParenLoc()); - Record.AddSourceRange(TL.getExceptionSpecRange()); - Record.AddSourceLocation(TL.getLocalRangeEnd()); - for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i) - Record.AddDeclRef(TL.getParam(i)); -} - -void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { - VisitFunctionTypeLoc(TL); -} - -void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) { - VisitFunctionTypeLoc(TL); -} - -void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) { - if (TL.getNumProtocols()) { - Record.AddSourceLocation(TL.getProtocolLAngleLoc()); - Record.AddSourceLocation(TL.getProtocolRAngleLoc()); - } - for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) - Record.AddSourceLocation(TL.getProtocolLoc(i)); -} - -void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { - Record.AddSourceLocation(TL.getTypeofLoc()); - Record.AddSourceLocation(TL.getLParenLoc()); - Record.AddSourceLocation(TL.getRParenLoc()); -} - -void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { - Record.AddSourceLocation(TL.getTypeofLoc()); - Record.AddSourceLocation(TL.getLParenLoc()); - Record.AddSourceLocation(TL.getRParenLoc()); - Record.AddTypeSourceInfo(TL.getUnderlyingTInfo()); -} - -void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) { - Record.AddSourceLocation(TL.getKWLoc()); - Record.AddSourceLocation(TL.getLParenLoc()); - Record.AddSourceLocation(TL.getRParenLoc()); - Record.AddTypeSourceInfo(TL.getUnderlyingTInfo()); -} - -void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitDeducedTemplateSpecializationTypeLoc( - DeducedTemplateSpecializationTypeLoc TL) { - Record.AddSourceLocation(TL.getTemplateNameLoc()); -} - -void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) { - Record.AddAttr(TL.getAttr()); -} - -void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc( - SubstTemplateTypeParmTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitSubstTemplateTypeParmPackTypeLoc( - SubstTemplateTypeParmPackTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitTemplateSpecializationTypeLoc( - TemplateSpecializationTypeLoc TL) { - Record.AddSourceLocation(TL.getTemplateKeywordLoc()); - Record.AddSourceLocation(TL.getTemplateNameLoc()); - Record.AddSourceLocation(TL.getLAngleLoc()); - Record.AddSourceLocation(TL.getRAngleLoc()); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - Record.AddTemplateArgumentLocInfo(TL.getArgLoc(i).getArgument().getKind(), - TL.getArgLoc(i).getLocInfo()); -} - -void TypeLocWriter::VisitParenTypeLoc(ParenTypeLoc TL) { - Record.AddSourceLocation(TL.getLParenLoc()); - Record.AddSourceLocation(TL.getRParenLoc()); -} - -void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { - Record.AddSourceLocation(TL.getElaboratedKeywordLoc()); - Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); -} - -void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { - Record.AddSourceLocation(TL.getElaboratedKeywordLoc()); - Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc( - DependentTemplateSpecializationTypeLoc TL) { - Record.AddSourceLocation(TL.getElaboratedKeywordLoc()); - Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); - Record.AddSourceLocation(TL.getTemplateKeywordLoc()); - Record.AddSourceLocation(TL.getTemplateNameLoc()); - Record.AddSourceLocation(TL.getLAngleLoc()); - Record.AddSourceLocation(TL.getRAngleLoc()); - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) - Record.AddTemplateArgumentLocInfo(TL.getArgLoc(I).getArgument().getKind(), - TL.getArgLoc(I).getLocInfo()); -} - -void TypeLocWriter::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) { - Record.AddSourceLocation(TL.getEllipsisLoc()); -} - -void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - -void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { - Record.push_back(TL.hasBaseTypeAsWritten()); - Record.AddSourceLocation(TL.getTypeArgsLAngleLoc()); - Record.AddSourceLocation(TL.getTypeArgsRAngleLoc()); - for (unsigned i = 0, e = TL.getNumTypeArgs(); i != e; ++i) - Record.AddTypeSourceInfo(TL.getTypeArgTInfo(i)); - Record.AddSourceLocation(TL.getProtocolLAngleLoc()); - Record.AddSourceLocation(TL.getProtocolRAngleLoc()); - for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) - Record.AddSourceLocation(TL.getProtocolLoc(i)); -} - -void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { - Record.AddSourceLocation(TL.getStarLoc()); -} - -void TypeLocWriter::VisitAtomicTypeLoc(AtomicTypeLoc TL) { - Record.AddSourceLocation(TL.getKWLoc()); - Record.AddSourceLocation(TL.getLParenLoc()); - Record.AddSourceLocation(TL.getRParenLoc()); -} - -void TypeLocWriter::VisitPipeTypeLoc(PipeTypeLoc TL) { - Record.AddSourceLocation(TL.getKWLoc()); -} - -void ASTWriter::WriteTypeAbbrevs() { - using namespace llvm; - - std::shared_ptr<BitCodeAbbrev> Abv; - - // Abbreviation for TYPE_EXT_QUAL - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::TYPE_EXT_QUAL)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 3)); // Quals - TypeExtQualAbbrev = Stream.EmitAbbrev(std::move(Abv)); - - // Abbreviation for TYPE_FUNCTION_PROTO - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::TYPE_FUNCTION_PROTO)); - // FunctionType - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ReturnType - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // NoReturn - Abv->Add(BitCodeAbbrevOp(0)); // HasRegParm - Abv->Add(BitCodeAbbrevOp(0)); // RegParm - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // CC - Abv->Add(BitCodeAbbrevOp(0)); // ProducesResult - Abv->Add(BitCodeAbbrevOp(0)); // NoCallerSavedRegs - Abv->Add(BitCodeAbbrevOp(0)); // NoCfCheck - // FunctionProtoType - Abv->Add(BitCodeAbbrevOp(0)); // IsVariadic - Abv->Add(BitCodeAbbrevOp(0)); // HasTrailingReturn - Abv->Add(BitCodeAbbrevOp(0)); // TypeQuals - Abv->Add(BitCodeAbbrevOp(0)); // RefQualifier - Abv->Add(BitCodeAbbrevOp(EST_None)); // ExceptionSpec - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // NumParams - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Params - TypeFunctionProtoAbbrev = Stream.EmitAbbrev(std::move(Abv)); -} - -//===----------------------------------------------------------------------===// -// ASTWriter Implementation -//===----------------------------------------------------------------------===// - -static void EmitBlockID(unsigned ID, const char *Name, - llvm::BitstreamWriter &Stream, - ASTWriter::RecordDataImpl &Record) { - Record.clear(); - Record.push_back(ID); - Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); - - // Emit the block name if present. - if (!Name || Name[0] == 0) - return; - Record.clear(); - while (*Name) - Record.push_back(*Name++); - Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); -} - -static void EmitRecordID(unsigned ID, const char *Name, - llvm::BitstreamWriter &Stream, - ASTWriter::RecordDataImpl &Record) { - Record.clear(); - Record.push_back(ID); - while (*Name) - Record.push_back(*Name++); - Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); -} - -static void AddStmtsExprs(llvm::BitstreamWriter &Stream, - ASTWriter::RecordDataImpl &Record) { -#define RECORD(X) EmitRecordID(X, #X, Stream, Record) - RECORD(STMT_STOP); - RECORD(STMT_NULL_PTR); - RECORD(STMT_REF_PTR); - RECORD(STMT_NULL); - RECORD(STMT_COMPOUND); - RECORD(STMT_CASE); - RECORD(STMT_DEFAULT); - RECORD(STMT_LABEL); - RECORD(STMT_ATTRIBUTED); - RECORD(STMT_IF); - RECORD(STMT_SWITCH); - RECORD(STMT_WHILE); - RECORD(STMT_DO); - RECORD(STMT_FOR); - RECORD(STMT_GOTO); - RECORD(STMT_INDIRECT_GOTO); - RECORD(STMT_CONTINUE); - RECORD(STMT_BREAK); - RECORD(STMT_RETURN); - RECORD(STMT_DECL); - RECORD(STMT_GCCASM); - RECORD(STMT_MSASM); - RECORD(EXPR_PREDEFINED); - RECORD(EXPR_DECL_REF); - RECORD(EXPR_INTEGER_LITERAL); - RECORD(EXPR_FLOATING_LITERAL); - RECORD(EXPR_IMAGINARY_LITERAL); - RECORD(EXPR_STRING_LITERAL); - RECORD(EXPR_CHARACTER_LITERAL); - RECORD(EXPR_PAREN); - RECORD(EXPR_PAREN_LIST); - RECORD(EXPR_UNARY_OPERATOR); - RECORD(EXPR_SIZEOF_ALIGN_OF); - RECORD(EXPR_ARRAY_SUBSCRIPT); - RECORD(EXPR_CALL); - RECORD(EXPR_MEMBER); - RECORD(EXPR_BINARY_OPERATOR); - RECORD(EXPR_COMPOUND_ASSIGN_OPERATOR); - RECORD(EXPR_CONDITIONAL_OPERATOR); - RECORD(EXPR_IMPLICIT_CAST); - RECORD(EXPR_CSTYLE_CAST); - RECORD(EXPR_COMPOUND_LITERAL); - RECORD(EXPR_EXT_VECTOR_ELEMENT); - RECORD(EXPR_INIT_LIST); - RECORD(EXPR_DESIGNATED_INIT); - RECORD(EXPR_DESIGNATED_INIT_UPDATE); - RECORD(EXPR_IMPLICIT_VALUE_INIT); - RECORD(EXPR_NO_INIT); - RECORD(EXPR_VA_ARG); - RECORD(EXPR_ADDR_LABEL); - RECORD(EXPR_STMT); - RECORD(EXPR_CHOOSE); - RECORD(EXPR_GNU_NULL); - RECORD(EXPR_SHUFFLE_VECTOR); - RECORD(EXPR_BLOCK); - RECORD(EXPR_GENERIC_SELECTION); - RECORD(EXPR_OBJC_STRING_LITERAL); - RECORD(EXPR_OBJC_BOXED_EXPRESSION); - RECORD(EXPR_OBJC_ARRAY_LITERAL); - RECORD(EXPR_OBJC_DICTIONARY_LITERAL); - RECORD(EXPR_OBJC_ENCODE); - RECORD(EXPR_OBJC_SELECTOR_EXPR); - RECORD(EXPR_OBJC_PROTOCOL_EXPR); - RECORD(EXPR_OBJC_IVAR_REF_EXPR); - RECORD(EXPR_OBJC_PROPERTY_REF_EXPR); - RECORD(EXPR_OBJC_KVC_REF_EXPR); - RECORD(EXPR_OBJC_MESSAGE_EXPR); - RECORD(STMT_OBJC_FOR_COLLECTION); - RECORD(STMT_OBJC_CATCH); - RECORD(STMT_OBJC_FINALLY); - RECORD(STMT_OBJC_AT_TRY); - RECORD(STMT_OBJC_AT_SYNCHRONIZED); - RECORD(STMT_OBJC_AT_THROW); - RECORD(EXPR_OBJC_BOOL_LITERAL); - RECORD(STMT_CXX_CATCH); - RECORD(STMT_CXX_TRY); - RECORD(STMT_CXX_FOR_RANGE); - RECORD(EXPR_CXX_OPERATOR_CALL); - RECORD(EXPR_CXX_MEMBER_CALL); - RECORD(EXPR_CXX_CONSTRUCT); - RECORD(EXPR_CXX_TEMPORARY_OBJECT); - RECORD(EXPR_CXX_STATIC_CAST); - RECORD(EXPR_CXX_DYNAMIC_CAST); - RECORD(EXPR_CXX_REINTERPRET_CAST); - RECORD(EXPR_CXX_CONST_CAST); - RECORD(EXPR_CXX_FUNCTIONAL_CAST); - RECORD(EXPR_USER_DEFINED_LITERAL); - RECORD(EXPR_CXX_STD_INITIALIZER_LIST); - RECORD(EXPR_CXX_BOOL_LITERAL); - RECORD(EXPR_CXX_NULL_PTR_LITERAL); - RECORD(EXPR_CXX_TYPEID_EXPR); - RECORD(EXPR_CXX_TYPEID_TYPE); - RECORD(EXPR_CXX_THIS); - RECORD(EXPR_CXX_THROW); - RECORD(EXPR_CXX_DEFAULT_ARG); - RECORD(EXPR_CXX_DEFAULT_INIT); - RECORD(EXPR_CXX_BIND_TEMPORARY); - RECORD(EXPR_CXX_SCALAR_VALUE_INIT); - RECORD(EXPR_CXX_NEW); - RECORD(EXPR_CXX_DELETE); - RECORD(EXPR_CXX_PSEUDO_DESTRUCTOR); - RECORD(EXPR_EXPR_WITH_CLEANUPS); - RECORD(EXPR_CXX_DEPENDENT_SCOPE_MEMBER); - RECORD(EXPR_CXX_DEPENDENT_SCOPE_DECL_REF); - RECORD(EXPR_CXX_UNRESOLVED_CONSTRUCT); - RECORD(EXPR_CXX_UNRESOLVED_MEMBER); - RECORD(EXPR_CXX_UNRESOLVED_LOOKUP); - RECORD(EXPR_CXX_EXPRESSION_TRAIT); - RECORD(EXPR_CXX_NOEXCEPT); - RECORD(EXPR_OPAQUE_VALUE); - RECORD(EXPR_BINARY_CONDITIONAL_OPERATOR); - RECORD(EXPR_TYPE_TRAIT); - RECORD(EXPR_ARRAY_TYPE_TRAIT); - RECORD(EXPR_PACK_EXPANSION); - RECORD(EXPR_SIZEOF_PACK); - RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM); - RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK); - RECORD(EXPR_FUNCTION_PARM_PACK); - RECORD(EXPR_MATERIALIZE_TEMPORARY); - RECORD(EXPR_CUDA_KERNEL_CALL); - RECORD(EXPR_CXX_UUIDOF_EXPR); - RECORD(EXPR_CXX_UUIDOF_TYPE); - RECORD(EXPR_LAMBDA); -#undef RECORD -} - -void ASTWriter::WriteBlockInfoBlock() { - RecordData Record; - Stream.EnterBlockInfoBlock(); - -#define BLOCK(X) EmitBlockID(X ## _ID, #X, Stream, Record) -#define RECORD(X) EmitRecordID(X, #X, Stream, Record) - - // Control Block. - BLOCK(CONTROL_BLOCK); - RECORD(METADATA); - RECORD(MODULE_NAME); - RECORD(MODULE_DIRECTORY); - RECORD(MODULE_MAP_FILE); - RECORD(IMPORTS); - RECORD(ORIGINAL_FILE); - RECORD(ORIGINAL_PCH_DIR); - RECORD(ORIGINAL_FILE_ID); - RECORD(INPUT_FILE_OFFSETS); - - BLOCK(OPTIONS_BLOCK); - RECORD(LANGUAGE_OPTIONS); - RECORD(TARGET_OPTIONS); - RECORD(FILE_SYSTEM_OPTIONS); - RECORD(HEADER_SEARCH_OPTIONS); - RECORD(PREPROCESSOR_OPTIONS); - - BLOCK(INPUT_FILES_BLOCK); - RECORD(INPUT_FILE); - - // AST Top-Level Block. - BLOCK(AST_BLOCK); - RECORD(TYPE_OFFSET); - RECORD(DECL_OFFSET); - RECORD(IDENTIFIER_OFFSET); - RECORD(IDENTIFIER_TABLE); - RECORD(EAGERLY_DESERIALIZED_DECLS); - RECORD(MODULAR_CODEGEN_DECLS); - RECORD(SPECIAL_TYPES); - RECORD(STATISTICS); - RECORD(TENTATIVE_DEFINITIONS); - RECORD(SELECTOR_OFFSETS); - RECORD(METHOD_POOL); - RECORD(PP_COUNTER_VALUE); - RECORD(SOURCE_LOCATION_OFFSETS); - RECORD(SOURCE_LOCATION_PRELOADS); - RECORD(EXT_VECTOR_DECLS); - RECORD(UNUSED_FILESCOPED_DECLS); - RECORD(PPD_ENTITIES_OFFSETS); - RECORD(VTABLE_USES); - RECORD(PPD_SKIPPED_RANGES); - RECORD(REFERENCED_SELECTOR_POOL); - RECORD(TU_UPDATE_LEXICAL); - RECORD(SEMA_DECL_REFS); - RECORD(WEAK_UNDECLARED_IDENTIFIERS); - RECORD(PENDING_IMPLICIT_INSTANTIATIONS); - RECORD(UPDATE_VISIBLE); - RECORD(DECL_UPDATE_OFFSETS); - RECORD(DECL_UPDATES); - RECORD(CUDA_SPECIAL_DECL_REFS); - RECORD(HEADER_SEARCH_TABLE); - RECORD(FP_PRAGMA_OPTIONS); - RECORD(OPENCL_EXTENSIONS); - RECORD(OPENCL_EXTENSION_TYPES); - RECORD(OPENCL_EXTENSION_DECLS); - RECORD(DELEGATING_CTORS); - RECORD(KNOWN_NAMESPACES); - RECORD(MODULE_OFFSET_MAP); - RECORD(SOURCE_MANAGER_LINE_TABLE); - RECORD(OBJC_CATEGORIES_MAP); - RECORD(FILE_SORTED_DECLS); - RECORD(IMPORTED_MODULES); - RECORD(OBJC_CATEGORIES); - RECORD(MACRO_OFFSET); - RECORD(INTERESTING_IDENTIFIERS); - RECORD(UNDEFINED_BUT_USED); - RECORD(LATE_PARSED_TEMPLATE); - RECORD(OPTIMIZE_PRAGMA_OPTIONS); - RECORD(MSSTRUCT_PRAGMA_OPTIONS); - RECORD(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS); - RECORD(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES); - RECORD(DELETE_EXPRS_TO_ANALYZE); - RECORD(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH); - RECORD(PP_CONDITIONAL_STACK); - - // SourceManager Block. - BLOCK(SOURCE_MANAGER_BLOCK); - RECORD(SM_SLOC_FILE_ENTRY); - RECORD(SM_SLOC_BUFFER_ENTRY); - RECORD(SM_SLOC_BUFFER_BLOB); - RECORD(SM_SLOC_BUFFER_BLOB_COMPRESSED); - RECORD(SM_SLOC_EXPANSION_ENTRY); - - // Preprocessor Block. - BLOCK(PREPROCESSOR_BLOCK); - RECORD(PP_MACRO_DIRECTIVE_HISTORY); - RECORD(PP_MACRO_FUNCTION_LIKE); - RECORD(PP_MACRO_OBJECT_LIKE); - RECORD(PP_MODULE_MACRO); - RECORD(PP_TOKEN); - - // Submodule Block. - BLOCK(SUBMODULE_BLOCK); - RECORD(SUBMODULE_METADATA); - RECORD(SUBMODULE_DEFINITION); - RECORD(SUBMODULE_UMBRELLA_HEADER); - RECORD(SUBMODULE_HEADER); - RECORD(SUBMODULE_TOPHEADER); - RECORD(SUBMODULE_UMBRELLA_DIR); - RECORD(SUBMODULE_IMPORTS); - RECORD(SUBMODULE_EXPORTS); - RECORD(SUBMODULE_REQUIRES); - RECORD(SUBMODULE_EXCLUDED_HEADER); - RECORD(SUBMODULE_LINK_LIBRARY); - RECORD(SUBMODULE_CONFIG_MACRO); - RECORD(SUBMODULE_CONFLICT); - RECORD(SUBMODULE_PRIVATE_HEADER); - RECORD(SUBMODULE_TEXTUAL_HEADER); - RECORD(SUBMODULE_PRIVATE_TEXTUAL_HEADER); - RECORD(SUBMODULE_INITIALIZERS); - RECORD(SUBMODULE_EXPORT_AS); - - // Comments Block. - BLOCK(COMMENTS_BLOCK); - RECORD(COMMENTS_RAW_COMMENT); - - // Decls and Types block. - BLOCK(DECLTYPES_BLOCK); - RECORD(TYPE_EXT_QUAL); - RECORD(TYPE_COMPLEX); - RECORD(TYPE_POINTER); - RECORD(TYPE_BLOCK_POINTER); - RECORD(TYPE_LVALUE_REFERENCE); - RECORD(TYPE_RVALUE_REFERENCE); - RECORD(TYPE_MEMBER_POINTER); - RECORD(TYPE_CONSTANT_ARRAY); - RECORD(TYPE_INCOMPLETE_ARRAY); - RECORD(TYPE_VARIABLE_ARRAY); - RECORD(TYPE_VECTOR); - RECORD(TYPE_EXT_VECTOR); - RECORD(TYPE_FUNCTION_NO_PROTO); - RECORD(TYPE_FUNCTION_PROTO); - RECORD(TYPE_TYPEDEF); - RECORD(TYPE_TYPEOF_EXPR); - RECORD(TYPE_TYPEOF); - RECORD(TYPE_RECORD); - RECORD(TYPE_ENUM); - RECORD(TYPE_OBJC_INTERFACE); - RECORD(TYPE_OBJC_OBJECT_POINTER); - RECORD(TYPE_DECLTYPE); - RECORD(TYPE_ELABORATED); - RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM); - RECORD(TYPE_UNRESOLVED_USING); - RECORD(TYPE_INJECTED_CLASS_NAME); - RECORD(TYPE_OBJC_OBJECT); - RECORD(TYPE_TEMPLATE_TYPE_PARM); - RECORD(TYPE_TEMPLATE_SPECIALIZATION); - RECORD(TYPE_DEPENDENT_NAME); - RECORD(TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION); - RECORD(TYPE_DEPENDENT_SIZED_ARRAY); - RECORD(TYPE_PAREN); - RECORD(TYPE_PACK_EXPANSION); - RECORD(TYPE_ATTRIBUTED); - RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK); - RECORD(TYPE_AUTO); - RECORD(TYPE_UNARY_TRANSFORM); - RECORD(TYPE_ATOMIC); - RECORD(TYPE_DECAYED); - RECORD(TYPE_ADJUSTED); - RECORD(TYPE_OBJC_TYPE_PARAM); - RECORD(LOCAL_REDECLARATIONS); - RECORD(DECL_TYPEDEF); - RECORD(DECL_TYPEALIAS); - RECORD(DECL_ENUM); - RECORD(DECL_RECORD); - RECORD(DECL_ENUM_CONSTANT); - RECORD(DECL_FUNCTION); - RECORD(DECL_OBJC_METHOD); - RECORD(DECL_OBJC_INTERFACE); - RECORD(DECL_OBJC_PROTOCOL); - RECORD(DECL_OBJC_IVAR); - RECORD(DECL_OBJC_AT_DEFS_FIELD); - RECORD(DECL_OBJC_CATEGORY); - RECORD(DECL_OBJC_CATEGORY_IMPL); - RECORD(DECL_OBJC_IMPLEMENTATION); - RECORD(DECL_OBJC_COMPATIBLE_ALIAS); - RECORD(DECL_OBJC_PROPERTY); - RECORD(DECL_OBJC_PROPERTY_IMPL); - RECORD(DECL_FIELD); - RECORD(DECL_MS_PROPERTY); - RECORD(DECL_VAR); - RECORD(DECL_IMPLICIT_PARAM); - RECORD(DECL_PARM_VAR); - RECORD(DECL_FILE_SCOPE_ASM); - RECORD(DECL_BLOCK); - RECORD(DECL_CONTEXT_LEXICAL); - RECORD(DECL_CONTEXT_VISIBLE); - RECORD(DECL_NAMESPACE); - RECORD(DECL_NAMESPACE_ALIAS); - RECORD(DECL_USING); - RECORD(DECL_USING_SHADOW); - RECORD(DECL_USING_DIRECTIVE); - RECORD(DECL_UNRESOLVED_USING_VALUE); - RECORD(DECL_UNRESOLVED_USING_TYPENAME); - RECORD(DECL_LINKAGE_SPEC); - RECORD(DECL_CXX_RECORD); - RECORD(DECL_CXX_METHOD); - RECORD(DECL_CXX_CONSTRUCTOR); - RECORD(DECL_CXX_INHERITED_CONSTRUCTOR); - RECORD(DECL_CXX_DESTRUCTOR); - RECORD(DECL_CXX_CONVERSION); - RECORD(DECL_ACCESS_SPEC); - RECORD(DECL_FRIEND); - RECORD(DECL_FRIEND_TEMPLATE); - RECORD(DECL_CLASS_TEMPLATE); - RECORD(DECL_CLASS_TEMPLATE_SPECIALIZATION); - RECORD(DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION); - RECORD(DECL_VAR_TEMPLATE); - RECORD(DECL_VAR_TEMPLATE_SPECIALIZATION); - RECORD(DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION); - RECORD(DECL_FUNCTION_TEMPLATE); - RECORD(DECL_TEMPLATE_TYPE_PARM); - RECORD(DECL_NON_TYPE_TEMPLATE_PARM); - RECORD(DECL_TEMPLATE_TEMPLATE_PARM); - RECORD(DECL_TYPE_ALIAS_TEMPLATE); - RECORD(DECL_STATIC_ASSERT); - RECORD(DECL_CXX_BASE_SPECIFIERS); - RECORD(DECL_CXX_CTOR_INITIALIZERS); - RECORD(DECL_INDIRECTFIELD); - RECORD(DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK); - RECORD(DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK); - RECORD(DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION); - RECORD(DECL_IMPORT); - RECORD(DECL_OMP_THREADPRIVATE); - RECORD(DECL_EMPTY); - RECORD(DECL_OBJC_TYPE_PARAM); - RECORD(DECL_OMP_CAPTUREDEXPR); - RECORD(DECL_PRAGMA_COMMENT); - RECORD(DECL_PRAGMA_DETECT_MISMATCH); - RECORD(DECL_OMP_DECLARE_REDUCTION); - - // Statements and Exprs can occur in the Decls and Types block. - AddStmtsExprs(Stream, Record); - - BLOCK(PREPROCESSOR_DETAIL_BLOCK); - RECORD(PPD_MACRO_EXPANSION); - RECORD(PPD_MACRO_DEFINITION); - RECORD(PPD_INCLUSION_DIRECTIVE); - - // Decls and Types block. - BLOCK(EXTENSION_BLOCK); - RECORD(EXTENSION_METADATA); - - BLOCK(UNHASHED_CONTROL_BLOCK); - RECORD(SIGNATURE); - RECORD(DIAGNOSTIC_OPTIONS); - RECORD(DIAG_PRAGMA_MAPPINGS); - -#undef RECORD -#undef BLOCK - Stream.ExitBlock(); -} - -/// Prepares a path for being written to an AST file by converting it -/// to an absolute path and removing nested './'s. -/// -/// \return \c true if the path was changed. -static bool cleanPathForOutput(FileManager &FileMgr, - SmallVectorImpl<char> &Path) { - bool Changed = FileMgr.makeAbsolutePath(Path); - return Changed | llvm::sys::path::remove_dots(Path); -} - -/// Adjusts the given filename to only write out the portion of the -/// filename that is not part of the system root directory. -/// -/// \param Filename the file name to adjust. -/// -/// \param BaseDir When non-NULL, the PCH file is a relocatable AST file and -/// the returned filename will be adjusted by this root directory. -/// -/// \returns either the original filename (if it needs no adjustment) or the -/// adjusted filename (which points into the @p Filename parameter). -static const char * -adjustFilenameForRelocatableAST(const char *Filename, StringRef BaseDir) { - assert(Filename && "No file name to adjust?"); - - if (BaseDir.empty()) - return Filename; - - // Verify that the filename and the system root have the same prefix. - unsigned Pos = 0; - for (; Filename[Pos] && Pos < BaseDir.size(); ++Pos) - if (Filename[Pos] != BaseDir[Pos]) - return Filename; // Prefixes don't match. - - // We hit the end of the filename before we hit the end of the system root. - if (!Filename[Pos]) - return Filename; - - // If there's not a path separator at the end of the base directory nor - // immediately after it, then this isn't within the base directory. - if (!llvm::sys::path::is_separator(Filename[Pos])) { - if (!llvm::sys::path::is_separator(BaseDir.back())) - return Filename; - } else { - // If the file name has a '/' at the current position, skip over the '/'. - // We distinguish relative paths from absolute paths by the - // absence of '/' at the beginning of relative paths. - // - // FIXME: This is wrong. We distinguish them by asking if the path is - // absolute, which isn't the same thing. And there might be multiple '/'s - // in a row. Use a better mechanism to indicate whether we have emitted an - // absolute or relative path. - ++Pos; - } - - return Filename + Pos; -} - -ASTFileSignature ASTWriter::createSignature(StringRef Bytes) { - // Calculate the hash till start of UNHASHED_CONTROL_BLOCK. - llvm::SHA1 Hasher; - Hasher.update(ArrayRef<uint8_t>(Bytes.bytes_begin(), Bytes.size())); - auto Hash = Hasher.result(); - - // Convert to an array [5*i32]. - ASTFileSignature Signature; - auto LShift = [&](unsigned char Val, unsigned Shift) { - return (uint32_t)Val << Shift; - }; - for (int I = 0; I != 5; ++I) - Signature[I] = LShift(Hash[I * 4 + 0], 24) | LShift(Hash[I * 4 + 1], 16) | - LShift(Hash[I * 4 + 2], 8) | LShift(Hash[I * 4 + 3], 0); - - return Signature; -} - -ASTFileSignature ASTWriter::writeUnhashedControlBlock(Preprocessor &PP, - ASTContext &Context) { - // Flush first to prepare the PCM hash (signature). - Stream.FlushToWord(); - auto StartOfUnhashedControl = Stream.GetCurrentBitNo() >> 3; - - // Enter the block and prepare to write records. - RecordData Record; - Stream.EnterSubblock(UNHASHED_CONTROL_BLOCK_ID, 5); - - // For implicit modules, write the hash of the PCM as its signature. - ASTFileSignature Signature; - if (WritingModule && - PP.getHeaderSearchInfo().getHeaderSearchOpts().ModulesHashContent) { - Signature = createSignature(StringRef(Buffer.begin(), StartOfUnhashedControl)); - Record.append(Signature.begin(), Signature.end()); - Stream.EmitRecord(SIGNATURE, Record); - Record.clear(); - } - - // Diagnostic options. - const auto &Diags = Context.getDiagnostics(); - const DiagnosticOptions &DiagOpts = Diags.getDiagnosticOptions(); -#define DIAGOPT(Name, Bits, Default) Record.push_back(DiagOpts.Name); -#define ENUM_DIAGOPT(Name, Type, Bits, Default) \ - Record.push_back(static_cast<unsigned>(DiagOpts.get##Name())); -#include "clang/Basic/DiagnosticOptions.def" - Record.push_back(DiagOpts.Warnings.size()); - for (unsigned I = 0, N = DiagOpts.Warnings.size(); I != N; ++I) - AddString(DiagOpts.Warnings[I], Record); - Record.push_back(DiagOpts.Remarks.size()); - for (unsigned I = 0, N = DiagOpts.Remarks.size(); I != N; ++I) - AddString(DiagOpts.Remarks[I], Record); - // Note: we don't serialize the log or serialization file names, because they - // are generally transient files and will almost always be overridden. - Stream.EmitRecord(DIAGNOSTIC_OPTIONS, Record); - - // Write out the diagnostic/pragma mappings. - WritePragmaDiagnosticMappings(Diags, /* IsModule = */ WritingModule); - - // Leave the options block. - Stream.ExitBlock(); - return Signature; -} - -/// Write the control block. -void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, - StringRef isysroot, - const std::string &OutputFile) { - using namespace llvm; - - Stream.EnterSubblock(CONTROL_BLOCK_ID, 5); - RecordData Record; - - // Metadata - auto MetadataAbbrev = std::make_shared<BitCodeAbbrev>(); - MetadataAbbrev->Add(BitCodeAbbrevOp(METADATA)); - MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Major - MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Minor - MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang maj. - MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang min. - MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable - MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Timestamps - MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // PCHHasObjectFile - MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Errors - MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag - unsigned MetadataAbbrevCode = Stream.EmitAbbrev(std::move(MetadataAbbrev)); - assert((!WritingModule || isysroot.empty()) && - "writing module as a relocatable PCH?"); - { - RecordData::value_type Record[] = { - METADATA, - VERSION_MAJOR, - VERSION_MINOR, - CLANG_VERSION_MAJOR, - CLANG_VERSION_MINOR, - !isysroot.empty(), - IncludeTimestamps, - Context.getLangOpts().BuildingPCHWithObjectFile, - ASTHasCompilerErrors}; - Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record, - getClangFullRepositoryVersion()); - } - - if (WritingModule) { - // Module name - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name - unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev)); - RecordData::value_type Record[] = {MODULE_NAME}; - Stream.EmitRecordWithBlob(AbbrevCode, Record, WritingModule->Name); - } - - if (WritingModule && WritingModule->Directory) { - SmallString<128> BaseDir(WritingModule->Directory->getName()); - cleanPathForOutput(Context.getSourceManager().getFileManager(), BaseDir); - - // If the home of the module is the current working directory, then we - // want to pick up the cwd of the build process loading the module, not - // our cwd, when we load this module. - if (!PP.getHeaderSearchInfo() - .getHeaderSearchOpts() - .ModuleMapFileHomeIsCwd || - WritingModule->Directory->getName() != StringRef(".")) { - // Module directory. - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(MODULE_DIRECTORY)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Directory - unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev)); - - RecordData::value_type Record[] = {MODULE_DIRECTORY}; - Stream.EmitRecordWithBlob(AbbrevCode, Record, BaseDir); - } - - // Write out all other paths relative to the base directory if possible. - BaseDirectory.assign(BaseDir.begin(), BaseDir.end()); - } else if (!isysroot.empty()) { - // Write out paths relative to the sysroot if possible. - BaseDirectory = isysroot; - } - - // Module map file - if (WritingModule && WritingModule->Kind == Module::ModuleMapModule) { - Record.clear(); - - auto &Map = PP.getHeaderSearchInfo().getModuleMap(); - AddPath(WritingModule->PresumedModuleMapFile.empty() - ? Map.getModuleMapFileForUniquing(WritingModule)->getName() - : StringRef(WritingModule->PresumedModuleMapFile), - Record); - - // Additional module map files. - if (auto *AdditionalModMaps = - Map.getAdditionalModuleMapFiles(WritingModule)) { - Record.push_back(AdditionalModMaps->size()); - for (const FileEntry *F : *AdditionalModMaps) - AddPath(F->getName(), Record); - } else { - Record.push_back(0); - } - - Stream.EmitRecord(MODULE_MAP_FILE, Record); - } - - // Imports - if (Chain) { - serialization::ModuleManager &Mgr = Chain->getModuleManager(); - Record.clear(); - - for (ModuleFile &M : Mgr) { - // Skip modules that weren't directly imported. - if (!M.isDirectlyImported()) - continue; - - Record.push_back((unsigned)M.Kind); // FIXME: Stable encoding - AddSourceLocation(M.ImportLoc, Record); - - // If we have calculated signature, there is no need to store - // the size or timestamp. - Record.push_back(M.Signature ? 0 : M.File->getSize()); - Record.push_back(M.Signature ? 0 : getTimestampForOutput(M.File)); - - for (auto I : M.Signature) - Record.push_back(I); - - AddString(M.ModuleName, Record); - AddPath(M.FileName, Record); - } - Stream.EmitRecord(IMPORTS, Record); - } - - // Write the options block. - Stream.EnterSubblock(OPTIONS_BLOCK_ID, 4); - - // Language options. - Record.clear(); - const LangOptions &LangOpts = Context.getLangOpts(); -#define LANGOPT(Name, Bits, Default, Description) \ - Record.push_back(LangOpts.Name); -#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ - Record.push_back(static_cast<unsigned>(LangOpts.get##Name())); -#include "clang/Basic/LangOptions.def" -#define SANITIZER(NAME, ID) \ - Record.push_back(LangOpts.Sanitize.has(SanitizerKind::ID)); -#include "clang/Basic/Sanitizers.def" - - Record.push_back(LangOpts.ModuleFeatures.size()); - for (StringRef Feature : LangOpts.ModuleFeatures) - AddString(Feature, Record); - - Record.push_back((unsigned) LangOpts.ObjCRuntime.getKind()); - AddVersionTuple(LangOpts.ObjCRuntime.getVersion(), Record); - - AddString(LangOpts.CurrentModule, Record); - - // Comment options. - Record.push_back(LangOpts.CommentOpts.BlockCommandNames.size()); - for (const auto &I : LangOpts.CommentOpts.BlockCommandNames) { - AddString(I, Record); - } - Record.push_back(LangOpts.CommentOpts.ParseAllComments); - - // OpenMP offloading options. - Record.push_back(LangOpts.OMPTargetTriples.size()); - for (auto &T : LangOpts.OMPTargetTriples) - AddString(T.getTriple(), Record); - - AddString(LangOpts.OMPHostIRFile, Record); - - Stream.EmitRecord(LANGUAGE_OPTIONS, Record); - - // Target options. - Record.clear(); - const TargetInfo &Target = Context.getTargetInfo(); - const TargetOptions &TargetOpts = Target.getTargetOpts(); - AddString(TargetOpts.Triple, Record); - AddString(TargetOpts.CPU, Record); - AddString(TargetOpts.ABI, Record); - Record.push_back(TargetOpts.FeaturesAsWritten.size()); - for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); I != N; ++I) { - AddString(TargetOpts.FeaturesAsWritten[I], Record); - } - Record.push_back(TargetOpts.Features.size()); - for (unsigned I = 0, N = TargetOpts.Features.size(); I != N; ++I) { - AddString(TargetOpts.Features[I], Record); - } - Stream.EmitRecord(TARGET_OPTIONS, Record); - - // File system options. - Record.clear(); - const FileSystemOptions &FSOpts = - Context.getSourceManager().getFileManager().getFileSystemOpts(); - AddString(FSOpts.WorkingDir, Record); - Stream.EmitRecord(FILE_SYSTEM_OPTIONS, Record); - - // Header search options. - Record.clear(); - const HeaderSearchOptions &HSOpts - = PP.getHeaderSearchInfo().getHeaderSearchOpts(); - AddString(HSOpts.Sysroot, Record); - - // Include entries. - Record.push_back(HSOpts.UserEntries.size()); - for (unsigned I = 0, N = HSOpts.UserEntries.size(); I != N; ++I) { - const HeaderSearchOptions::Entry &Entry = HSOpts.UserEntries[I]; - AddString(Entry.Path, Record); - Record.push_back(static_cast<unsigned>(Entry.Group)); - Record.push_back(Entry.IsFramework); - Record.push_back(Entry.IgnoreSysRoot); - } - - // System header prefixes. - Record.push_back(HSOpts.SystemHeaderPrefixes.size()); - for (unsigned I = 0, N = HSOpts.SystemHeaderPrefixes.size(); I != N; ++I) { - AddString(HSOpts.SystemHeaderPrefixes[I].Prefix, Record); - Record.push_back(HSOpts.SystemHeaderPrefixes[I].IsSystemHeader); - } - - AddString(HSOpts.ResourceDir, Record); - AddString(HSOpts.ModuleCachePath, Record); - AddString(HSOpts.ModuleUserBuildPath, Record); - Record.push_back(HSOpts.DisableModuleHash); - Record.push_back(HSOpts.ImplicitModuleMaps); - Record.push_back(HSOpts.ModuleMapFileHomeIsCwd); - Record.push_back(HSOpts.UseBuiltinIncludes); - Record.push_back(HSOpts.UseStandardSystemIncludes); - Record.push_back(HSOpts.UseStandardCXXIncludes); - Record.push_back(HSOpts.UseLibcxx); - // Write out the specific module cache path that contains the module files. - AddString(PP.getHeaderSearchInfo().getModuleCachePath(), Record); - Stream.EmitRecord(HEADER_SEARCH_OPTIONS, Record); - - // Preprocessor options. - Record.clear(); - const PreprocessorOptions &PPOpts = PP.getPreprocessorOpts(); - - // Macro definitions. - Record.push_back(PPOpts.Macros.size()); - for (unsigned I = 0, N = PPOpts.Macros.size(); I != N; ++I) { - AddString(PPOpts.Macros[I].first, Record); - Record.push_back(PPOpts.Macros[I].second); - } - - // Includes - Record.push_back(PPOpts.Includes.size()); - for (unsigned I = 0, N = PPOpts.Includes.size(); I != N; ++I) - AddString(PPOpts.Includes[I], Record); - - // Macro includes - Record.push_back(PPOpts.MacroIncludes.size()); - for (unsigned I = 0, N = PPOpts.MacroIncludes.size(); I != N; ++I) - AddString(PPOpts.MacroIncludes[I], Record); - - Record.push_back(PPOpts.UsePredefines); - // Detailed record is important since it is used for the module cache hash. - Record.push_back(PPOpts.DetailedRecord); - AddString(PPOpts.ImplicitPCHInclude, Record); - Record.push_back(static_cast<unsigned>(PPOpts.ObjCXXARCStandardLibrary)); - Stream.EmitRecord(PREPROCESSOR_OPTIONS, Record); - - // Leave the options block. - Stream.ExitBlock(); - - // Original file name and file ID - SourceManager &SM = Context.getSourceManager(); - if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { - auto FileAbbrev = std::make_shared<BitCodeAbbrev>(); - FileAbbrev->Add(BitCodeAbbrevOp(ORIGINAL_FILE)); - FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File ID - FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name - unsigned FileAbbrevCode = Stream.EmitAbbrev(std::move(FileAbbrev)); - - Record.clear(); - Record.push_back(ORIGINAL_FILE); - Record.push_back(SM.getMainFileID().getOpaqueValue()); - EmitRecordWithPath(FileAbbrevCode, Record, MainFile->getName()); - } - - Record.clear(); - Record.push_back(SM.getMainFileID().getOpaqueValue()); - Stream.EmitRecord(ORIGINAL_FILE_ID, Record); - - // Original PCH directory - if (!OutputFile.empty() && OutputFile != "-") { - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(ORIGINAL_PCH_DIR)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name - unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev)); - - SmallString<128> OutputPath(OutputFile); - - SM.getFileManager().makeAbsolutePath(OutputPath); - StringRef origDir = llvm::sys::path::parent_path(OutputPath); - - RecordData::value_type Record[] = {ORIGINAL_PCH_DIR}; - Stream.EmitRecordWithBlob(AbbrevCode, Record, origDir); - } - - WriteInputFiles(Context.SourceMgr, - PP.getHeaderSearchInfo().getHeaderSearchOpts(), - PP.getLangOpts().Modules); - Stream.ExitBlock(); -} - -namespace { - -/// An input file. -struct InputFileEntry { - const FileEntry *File; - bool IsSystemFile; - bool IsTransient; - bool BufferOverridden; - bool IsTopLevelModuleMap; -}; - -} // namespace - -void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, - HeaderSearchOptions &HSOpts, - bool Modules) { - using namespace llvm; - - Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4); - - // Create input-file abbreviation. - auto IFAbbrev = std::make_shared<BitCodeAbbrev>(); - IFAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE)); - IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID - IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size - IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time - IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Overridden - IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Transient - IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Module map - IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name - unsigned IFAbbrevCode = Stream.EmitAbbrev(std::move(IFAbbrev)); - - // Get all ContentCache objects for files, sorted by whether the file is a - // system one or not. System files go at the back, users files at the front. - std::deque<InputFileEntry> SortedFiles; - for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size(); I != N; ++I) { - // Get this source location entry. - const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I); - assert(&SourceMgr.getSLocEntry(FileID::get(I)) == SLoc); - - // We only care about file entries that were not overridden. - if (!SLoc->isFile()) - continue; - const SrcMgr::FileInfo &File = SLoc->getFile(); - const SrcMgr::ContentCache *Cache = File.getContentCache(); - if (!Cache->OrigEntry) - continue; - - InputFileEntry Entry; - Entry.File = Cache->OrigEntry; - Entry.IsSystemFile = Cache->IsSystemFile; - Entry.IsTransient = Cache->IsTransient; - Entry.BufferOverridden = Cache->BufferOverridden; - Entry.IsTopLevelModuleMap = isModuleMap(File.getFileCharacteristic()) && - File.getIncludeLoc().isInvalid(); - if (Cache->IsSystemFile) - SortedFiles.push_back(Entry); - else - SortedFiles.push_front(Entry); - } - - unsigned UserFilesNum = 0; - // Write out all of the input files. - std::vector<uint64_t> InputFileOffsets; - for (const auto &Entry : SortedFiles) { - uint32_t &InputFileID = InputFileIDs[Entry.File]; - if (InputFileID != 0) - continue; // already recorded this file. - - // Record this entry's offset. - InputFileOffsets.push_back(Stream.GetCurrentBitNo()); - - InputFileID = InputFileOffsets.size(); - - if (!Entry.IsSystemFile) - ++UserFilesNum; - - // Emit size/modification time for this file. - // And whether this file was overridden. - RecordData::value_type Record[] = { - INPUT_FILE, - InputFileOffsets.size(), - (uint64_t)Entry.File->getSize(), - (uint64_t)getTimestampForOutput(Entry.File), - Entry.BufferOverridden, - Entry.IsTransient, - Entry.IsTopLevelModuleMap}; - - EmitRecordWithPath(IFAbbrevCode, Record, Entry.File->getName()); - } - - Stream.ExitBlock(); - - // Create input file offsets abbreviation. - auto OffsetsAbbrev = std::make_shared<BitCodeAbbrev>(); - OffsetsAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE_OFFSETS)); - OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # input files - OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # non-system - // input files - OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Array - unsigned OffsetsAbbrevCode = Stream.EmitAbbrev(std::move(OffsetsAbbrev)); - - // Write input file offsets. - RecordData::value_type Record[] = {INPUT_FILE_OFFSETS, - InputFileOffsets.size(), UserFilesNum}; - Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, bytes(InputFileOffsets)); -} - -//===----------------------------------------------------------------------===// -// Source Manager Serialization -//===----------------------------------------------------------------------===// - -/// Create an abbreviation for the SLocEntry that refers to a -/// file. -static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) { - using namespace llvm; - - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_FILE_ENTRY)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Characteristic - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives - // FileEntry fields. - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Input File ID - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumCreatedFIDs - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 24)); // FirstDeclIndex - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumDecls - return Stream.EmitAbbrev(std::move(Abbrev)); -} - -/// Create an abbreviation for the SLocEntry that refers to a -/// buffer. -static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) { - using namespace llvm; - - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_BUFFER_ENTRY)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Characteristic - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob - return Stream.EmitAbbrev(std::move(Abbrev)); -} - -/// Create an abbreviation for the SLocEntry that refers to a -/// buffer's blob. -static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream, - bool Compressed) { - using namespace llvm; - - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(Compressed ? SM_SLOC_BUFFER_BLOB_COMPRESSED - : SM_SLOC_BUFFER_BLOB)); - if (Compressed) - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Uncompressed size - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob - return Stream.EmitAbbrev(std::move(Abbrev)); -} - -/// Create an abbreviation for the SLocEntry that refers to a macro -/// expansion. -static unsigned CreateSLocExpansionAbbrev(llvm::BitstreamWriter &Stream) { - using namespace llvm; - - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_EXPANSION_ENTRY)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Is token range - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length - return Stream.EmitAbbrev(std::move(Abbrev)); -} - -namespace { - - // Trait used for the on-disk hash table of header search information. - class HeaderFileInfoTrait { - ASTWriter &Writer; - - // Keep track of the framework names we've used during serialization. - SmallVector<char, 128> FrameworkStringData; - llvm::StringMap<unsigned> FrameworkNameOffset; - - public: - HeaderFileInfoTrait(ASTWriter &Writer) : Writer(Writer) {} - - struct key_type { - StringRef Filename; - off_t Size; - time_t ModTime; - }; - using key_type_ref = const key_type &; - - using UnresolvedModule = - llvm::PointerIntPair<Module *, 2, ModuleMap::ModuleHeaderRole>; - - struct data_type { - const HeaderFileInfo &HFI; - ArrayRef<ModuleMap::KnownHeader> KnownHeaders; - UnresolvedModule Unresolved; - }; - using data_type_ref = const data_type &; - - using hash_value_type = unsigned; - using offset_type = unsigned; - - hash_value_type ComputeHash(key_type_ref key) { - // The hash is based only on size/time of the file, so that the reader can - // match even when symlinking or excess path elements ("foo/../", "../") - // change the form of the name. However, complete path is still the key. - return llvm::hash_combine(key.Size, key.ModTime); - } - - std::pair<unsigned, unsigned> - EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) { - using namespace llvm::support; - - endian::Writer LE(Out, little); - unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; - LE.write<uint16_t>(KeyLen); - unsigned DataLen = 1 + 2 + 4 + 4; - for (auto ModInfo : Data.KnownHeaders) - if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule())) - DataLen += 4; - if (Data.Unresolved.getPointer()) - DataLen += 4; - LE.write<uint8_t>(DataLen); - return std::make_pair(KeyLen, DataLen); - } - - void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) { - using namespace llvm::support; - - endian::Writer LE(Out, little); - LE.write<uint64_t>(key.Size); - KeyLen -= 8; - LE.write<uint64_t>(key.ModTime); - KeyLen -= 8; - Out.write(key.Filename.data(), KeyLen); - } - - void EmitData(raw_ostream &Out, key_type_ref key, - data_type_ref Data, unsigned DataLen) { - using namespace llvm::support; - - endian::Writer LE(Out, little); - uint64_t Start = Out.tell(); (void)Start; - - unsigned char Flags = (Data.HFI.isImport << 5) - | (Data.HFI.isPragmaOnce << 4) - | (Data.HFI.DirInfo << 1) - | Data.HFI.IndexHeaderMapHeader; - LE.write<uint8_t>(Flags); - LE.write<uint16_t>(Data.HFI.NumIncludes); - - if (!Data.HFI.ControllingMacro) - LE.write<uint32_t>(Data.HFI.ControllingMacroID); - else - LE.write<uint32_t>(Writer.getIdentifierRef(Data.HFI.ControllingMacro)); - - unsigned Offset = 0; - if (!Data.HFI.Framework.empty()) { - // If this header refers into a framework, save the framework name. - llvm::StringMap<unsigned>::iterator Pos - = FrameworkNameOffset.find(Data.HFI.Framework); - if (Pos == FrameworkNameOffset.end()) { - Offset = FrameworkStringData.size() + 1; - FrameworkStringData.append(Data.HFI.Framework.begin(), - Data.HFI.Framework.end()); - FrameworkStringData.push_back(0); - - FrameworkNameOffset[Data.HFI.Framework] = Offset; - } else - Offset = Pos->second; - } - LE.write<uint32_t>(Offset); - - auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { - if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { - uint32_t Value = (ModID << 2) | (unsigned)Role; - assert((Value >> 2) == ModID && "overflow in header module info"); - LE.write<uint32_t>(Value); - } - }; - - // FIXME: If the header is excluded, we should write out some - // record of that fact. - for (auto ModInfo : Data.KnownHeaders) - EmitModule(ModInfo.getModule(), ModInfo.getRole()); - if (Data.Unresolved.getPointer()) - EmitModule(Data.Unresolved.getPointer(), Data.Unresolved.getInt()); - - assert(Out.tell() - Start == DataLen && "Wrong data length"); - } - - const char *strings_begin() const { return FrameworkStringData.begin(); } - const char *strings_end() const { return FrameworkStringData.end(); } - }; - -} // namespace - -/// Write the header search block for the list of files that -/// -/// \param HS The header search structure to save. -void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { - HeaderFileInfoTrait GeneratorTrait(*this); - llvm::OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator; - SmallVector<const char *, 4> SavedStrings; - unsigned NumHeaderSearchEntries = 0; - - // Find all unresolved headers for the current module. We generally will - // have resolved them before we get here, but not necessarily: we might be - // compiling a preprocessed module, where there is no requirement for the - // original files to exist any more. - const HeaderFileInfo Empty; // So we can take a reference. - if (WritingModule) { - llvm::SmallVector<Module *, 16> Worklist(1, WritingModule); - while (!Worklist.empty()) { - Module *M = Worklist.pop_back_val(); - if (!M->isAvailable()) - continue; - - // Map to disk files where possible, to pick up any missing stat - // information. This also means we don't need to check the unresolved - // headers list when emitting resolved headers in the first loop below. - // FIXME: It'd be preferable to avoid doing this if we were given - // sufficient stat information in the module map. - HS.getModuleMap().resolveHeaderDirectives(M); - - // If the file didn't exist, we can still create a module if we were given - // enough information in the module map. - for (auto U : M->MissingHeaders) { - // Check that we were given enough information to build a module - // without this file existing on disk. - if (!U.Size || (!U.ModTime && IncludeTimestamps)) { - PP->Diag(U.FileNameLoc, diag::err_module_no_size_mtime_for_header) - << WritingModule->getFullModuleName() << U.Size.hasValue() - << U.FileName; - continue; - } - - // Form the effective relative pathname for the file. - SmallString<128> Filename(M->Directory->getName()); - llvm::sys::path::append(Filename, U.FileName); - PreparePathForOutput(Filename); - - StringRef FilenameDup = strdup(Filename.c_str()); - SavedStrings.push_back(FilenameDup.data()); - - HeaderFileInfoTrait::key_type Key = { - FilenameDup, *U.Size, IncludeTimestamps ? *U.ModTime : 0 - }; - HeaderFileInfoTrait::data_type Data = { - Empty, {}, {M, ModuleMap::headerKindToRole(U.Kind)} - }; - // FIXME: Deal with cases where there are multiple unresolved header - // directives in different submodules for the same header. - Generator.insert(Key, Data, GeneratorTrait); - ++NumHeaderSearchEntries; - } - - Worklist.append(M->submodule_begin(), M->submodule_end()); - } - } - - SmallVector<const FileEntry *, 16> FilesByUID; - HS.getFileMgr().GetUniqueIDMapping(FilesByUID); - - if (FilesByUID.size() > HS.header_file_size()) - FilesByUID.resize(HS.header_file_size()); - - for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) { - const FileEntry *File = FilesByUID[UID]; - if (!File) - continue; - - // Get the file info. This will load info from the external source if - // necessary. Skip emitting this file if we have no information on it - // as a header file (in which case HFI will be null) or if it hasn't - // changed since it was loaded. Also skip it if it's for a modular header - // from a different module; in that case, we rely on the module(s) - // containing the header to provide this information. - const HeaderFileInfo *HFI = - HS.getExistingFileInfo(File, /*WantExternal*/!Chain); - if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader)) - continue; - - // Massage the file path into an appropriate form. - StringRef Filename = File->getName(); - SmallString<128> FilenameTmp(Filename); - if (PreparePathForOutput(FilenameTmp)) { - // If we performed any translation on the file name at all, we need to - // save this string, since the generator will refer to it later. - Filename = StringRef(strdup(FilenameTmp.c_str())); - SavedStrings.push_back(Filename.data()); - } - - HeaderFileInfoTrait::key_type Key = { - Filename, File->getSize(), getTimestampForOutput(File) - }; - HeaderFileInfoTrait::data_type Data = { - *HFI, HS.getModuleMap().findAllModulesForHeader(File), {} - }; - Generator.insert(Key, Data, GeneratorTrait); - ++NumHeaderSearchEntries; - } - - // Create the on-disk hash table in a buffer. - SmallString<4096> TableData; - uint32_t BucketOffset; - { - using namespace llvm::support; - - llvm::raw_svector_ostream Out(TableData); - // Make sure that no bucket is at offset 0 - endian::write<uint32_t>(Out, 0, little); - BucketOffset = Generator.Emit(Out, GeneratorTrait); - } - - // Create a blob abbreviation - using namespace llvm; - - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(HEADER_SEARCH_TABLE)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned TableAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - // Write the header search table - RecordData::value_type Record[] = {HEADER_SEARCH_TABLE, BucketOffset, - NumHeaderSearchEntries, TableData.size()}; - TableData.append(GeneratorTrait.strings_begin(),GeneratorTrait.strings_end()); - Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData); - - // Free all of the strings we had to duplicate. - for (unsigned I = 0, N = SavedStrings.size(); I != N; ++I) - free(const_cast<char *>(SavedStrings[I])); -} - -static void emitBlob(llvm::BitstreamWriter &Stream, StringRef Blob, - unsigned SLocBufferBlobCompressedAbbrv, - unsigned SLocBufferBlobAbbrv) { - using RecordDataType = ASTWriter::RecordData::value_type; - - // Compress the buffer if possible. We expect that almost all PCM - // consumers will not want its contents. - SmallString<0> CompressedBuffer; - if (llvm::zlib::isAvailable()) { - llvm::Error E = llvm::zlib::compress(Blob.drop_back(1), CompressedBuffer); - if (!E) { - RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB_COMPRESSED, - Blob.size() - 1}; - Stream.EmitRecordWithBlob(SLocBufferBlobCompressedAbbrv, Record, - CompressedBuffer); - return; - } - llvm::consumeError(std::move(E)); - } - - RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB}; - Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, Blob); -} - -/// Writes the block containing the serialized form of the -/// source manager. -/// -/// TODO: We should probably use an on-disk hash table (stored in a -/// blob), indexed based on the file name, so that we only create -/// entries for files that we actually need. In the common case (no -/// errors), we probably won't have to create file entries for any of -/// the files in the AST. -void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, - const Preprocessor &PP) { - RecordData Record; - - // Enter the source manager block. - Stream.EnterSubblock(SOURCE_MANAGER_BLOCK_ID, 4); - - // Abbreviations for the various kinds of source-location entries. - unsigned SLocFileAbbrv = CreateSLocFileAbbrev(Stream); - unsigned SLocBufferAbbrv = CreateSLocBufferAbbrev(Stream); - unsigned SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream, false); - unsigned SLocBufferBlobCompressedAbbrv = - CreateSLocBufferBlobAbbrev(Stream, true); - unsigned SLocExpansionAbbrv = CreateSLocExpansionAbbrev(Stream); - - // Write out the source location entry table. We skip the first - // entry, which is always the same dummy entry. - std::vector<uint32_t> SLocEntryOffsets; - RecordData PreloadSLocs; - SLocEntryOffsets.reserve(SourceMgr.local_sloc_entry_size() - 1); - for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size(); - I != N; ++I) { - // Get this source location entry. - const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I); - FileID FID = FileID::get(I); - assert(&SourceMgr.getSLocEntry(FID) == SLoc); - - // Record the offset of this source-location entry. - SLocEntryOffsets.push_back(Stream.GetCurrentBitNo()); - - // Figure out which record code to use. - unsigned Code; - if (SLoc->isFile()) { - const SrcMgr::ContentCache *Cache = SLoc->getFile().getContentCache(); - if (Cache->OrigEntry) { - Code = SM_SLOC_FILE_ENTRY; - } else - Code = SM_SLOC_BUFFER_ENTRY; - } else - Code = SM_SLOC_EXPANSION_ENTRY; - Record.clear(); - Record.push_back(Code); - - // Starting offset of this entry within this module, so skip the dummy. - Record.push_back(SLoc->getOffset() - 2); - if (SLoc->isFile()) { - const SrcMgr::FileInfo &File = SLoc->getFile(); - AddSourceLocation(File.getIncludeLoc(), Record); - Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding - Record.push_back(File.hasLineDirectives()); - - const SrcMgr::ContentCache *Content = File.getContentCache(); - bool EmitBlob = false; - if (Content->OrigEntry) { - assert(Content->OrigEntry == Content->ContentsEntry && - "Writing to AST an overridden file is not supported"); - - // The source location entry is a file. Emit input file ID. - assert(InputFileIDs[Content->OrigEntry] != 0 && "Missed file entry"); - Record.push_back(InputFileIDs[Content->OrigEntry]); - - Record.push_back(File.NumCreatedFIDs); - - FileDeclIDsTy::iterator FDI = FileDeclIDs.find(FID); - if (FDI != FileDeclIDs.end()) { - Record.push_back(FDI->second->FirstDeclIndex); - Record.push_back(FDI->second->DeclIDs.size()); - } else { - Record.push_back(0); - Record.push_back(0); - } - - Stream.EmitRecordWithAbbrev(SLocFileAbbrv, Record); - - if (Content->BufferOverridden || Content->IsTransient) - EmitBlob = true; - } else { - // The source location entry is a buffer. The blob associated - // with this entry contains the contents of the buffer. - - // We add one to the size so that we capture the trailing NULL - // that is required by llvm::MemoryBuffer::getMemBuffer (on - // the reader side). - const llvm::MemoryBuffer *Buffer - = Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager()); - StringRef Name = Buffer->getBufferIdentifier(); - Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record, - StringRef(Name.data(), Name.size() + 1)); - EmitBlob = true; - - if (Name == "<built-in>") - PreloadSLocs.push_back(SLocEntryOffsets.size()); - } - - if (EmitBlob) { - // Include the implicit terminating null character in the on-disk buffer - // if we're writing it uncompressed. - const llvm::MemoryBuffer *Buffer = - Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager()); - StringRef Blob(Buffer->getBufferStart(), Buffer->getBufferSize() + 1); - emitBlob(Stream, Blob, SLocBufferBlobCompressedAbbrv, - SLocBufferBlobAbbrv); - } - } else { - // The source location entry is a macro expansion. - const SrcMgr::ExpansionInfo &Expansion = SLoc->getExpansion(); - AddSourceLocation(Expansion.getSpellingLoc(), Record); - AddSourceLocation(Expansion.getExpansionLocStart(), Record); - AddSourceLocation(Expansion.isMacroArgExpansion() - ? SourceLocation() - : Expansion.getExpansionLocEnd(), - Record); - Record.push_back(Expansion.isExpansionTokenRange()); - - // Compute the token length for this macro expansion. - unsigned NextOffset = SourceMgr.getNextLocalOffset(); - if (I + 1 != N) - NextOffset = SourceMgr.getLocalSLocEntry(I + 1).getOffset(); - Record.push_back(NextOffset - SLoc->getOffset() - 1); - Stream.EmitRecordWithAbbrev(SLocExpansionAbbrv, Record); - } - } - - Stream.ExitBlock(); - - if (SLocEntryOffsets.empty()) - return; - - // Write the source-location offsets table into the AST block. This - // table is used for lazily loading source-location information. - using namespace llvm; - - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SOURCE_LOCATION_OFFSETS)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // total size - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets - unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - { - RecordData::value_type Record[] = { - SOURCE_LOCATION_OFFSETS, SLocEntryOffsets.size(), - SourceMgr.getNextLocalOffset() - 1 /* skip dummy */}; - Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, - bytes(SLocEntryOffsets)); - } - // Write the source location entry preloads array, telling the AST - // reader which source locations entries it should load eagerly. - Stream.EmitRecord(SOURCE_LOCATION_PRELOADS, PreloadSLocs); - - // Write the line table. It depends on remapping working, so it must come - // after the source location offsets. - if (SourceMgr.hasLineTable()) { - LineTableInfo &LineTable = SourceMgr.getLineTable(); - - Record.clear(); - - // Emit the needed file names. - llvm::DenseMap<int, int> FilenameMap; - FilenameMap[-1] = -1; // For unspecified filenames. - for (const auto &L : LineTable) { - if (L.first.ID < 0) - continue; - for (auto &LE : L.second) { - if (FilenameMap.insert(std::make_pair(LE.FilenameID, - FilenameMap.size() - 1)).second) - AddPath(LineTable.getFilename(LE.FilenameID), Record); - } - } - Record.push_back(0); - - // Emit the line entries - for (const auto &L : LineTable) { - // Only emit entries for local files. - if (L.first.ID < 0) - continue; - - // Emit the file ID - Record.push_back(L.first.ID); - - // Emit the line entries - Record.push_back(L.second.size()); - for (const auto &LE : L.second) { - Record.push_back(LE.FileOffset); - Record.push_back(LE.LineNo); - Record.push_back(FilenameMap[LE.FilenameID]); - Record.push_back((unsigned)LE.FileKind); - Record.push_back(LE.IncludeOffset); - } - } - - Stream.EmitRecord(SOURCE_MANAGER_LINE_TABLE, Record); - } -} - -//===----------------------------------------------------------------------===// -// Preprocessor Serialization -//===----------------------------------------------------------------------===// - -static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule, - const Preprocessor &PP) { - if (MacroInfo *MI = MD->getMacroInfo()) - if (MI->isBuiltinMacro()) - return true; - - if (IsModule) { - SourceLocation Loc = MD->getLocation(); - if (Loc.isInvalid()) - return true; - if (PP.getSourceManager().getFileID(Loc) == PP.getPredefinesFileID()) - return true; - } - - return false; -} - -/// Writes the block containing the serialized form of the -/// preprocessor. -void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { - PreprocessingRecord *PPRec = PP.getPreprocessingRecord(); - if (PPRec) - WritePreprocessorDetail(*PPRec); - - RecordData Record; - RecordData ModuleMacroRecord; - - // If the preprocessor __COUNTER__ value has been bumped, remember it. - if (PP.getCounterValue() != 0) { - RecordData::value_type Record[] = {PP.getCounterValue()}; - Stream.EmitRecord(PP_COUNTER_VALUE, Record); - } - - if (PP.isRecordingPreamble() && PP.hasRecordedPreamble()) { - assert(!IsModule); - auto SkipInfo = PP.getPreambleSkipInfo(); - if (SkipInfo.hasValue()) { - Record.push_back(true); - AddSourceLocation(SkipInfo->HashTokenLoc, Record); - AddSourceLocation(SkipInfo->IfTokenLoc, Record); - Record.push_back(SkipInfo->FoundNonSkipPortion); - Record.push_back(SkipInfo->FoundElse); - AddSourceLocation(SkipInfo->ElseLoc, Record); - } else { - Record.push_back(false); - } - for (const auto &Cond : PP.getPreambleConditionalStack()) { - AddSourceLocation(Cond.IfLoc, Record); - Record.push_back(Cond.WasSkipping); - Record.push_back(Cond.FoundNonSkip); - Record.push_back(Cond.FoundElse); - } - Stream.EmitRecord(PP_CONDITIONAL_STACK, Record); - Record.clear(); - } - - // Enter the preprocessor block. - Stream.EnterSubblock(PREPROCESSOR_BLOCK_ID, 3); - - // If the AST file contains __DATE__ or __TIME__ emit a warning about this. - // FIXME: Include a location for the use, and say which one was used. - if (PP.SawDateOrTime()) - PP.Diag(SourceLocation(), diag::warn_module_uses_date_time) << IsModule; - - // Loop over all the macro directives that are live at the end of the file, - // emitting each to the PP section. - - // Construct the list of identifiers with macro directives that need to be - // serialized. - SmallVector<const IdentifierInfo *, 128> MacroIdentifiers; - for (auto &Id : PP.getIdentifierTable()) - if (Id.second->hadMacroDefinition() && - (!Id.second->isFromAST() || - Id.second->hasChangedSinceDeserialization())) - MacroIdentifiers.push_back(Id.second); - // Sort the set of macro definitions that need to be serialized by the - // name of the macro, to provide a stable ordering. - llvm::sort(MacroIdentifiers, llvm::less_ptr<IdentifierInfo>()); - - // Emit the macro directives as a list and associate the offset with the - // identifier they belong to. - for (const IdentifierInfo *Name : MacroIdentifiers) { - MacroDirective *MD = PP.getLocalMacroDirectiveHistory(Name); - auto StartOffset = Stream.GetCurrentBitNo(); - - // Emit the macro directives in reverse source order. - for (; MD; MD = MD->getPrevious()) { - // Once we hit an ignored macro, we're done: the rest of the chain - // will all be ignored macros. - if (shouldIgnoreMacro(MD, IsModule, PP)) - break; - - AddSourceLocation(MD->getLocation(), Record); - Record.push_back(MD->getKind()); - if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) { - Record.push_back(getMacroRef(DefMD->getInfo(), Name)); - } else if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) { - Record.push_back(VisMD->isPublic()); - } - } - - // Write out any exported module macros. - bool EmittedModuleMacros = false; - // We write out exported module macros for PCH as well. - auto Leafs = PP.getLeafModuleMacros(Name); - SmallVector<ModuleMacro*, 8> Worklist(Leafs.begin(), Leafs.end()); - llvm::DenseMap<ModuleMacro*, unsigned> Visits; - while (!Worklist.empty()) { - auto *Macro = Worklist.pop_back_val(); - - // Emit a record indicating this submodule exports this macro. - ModuleMacroRecord.push_back( - getSubmoduleID(Macro->getOwningModule())); - ModuleMacroRecord.push_back(getMacroRef(Macro->getMacroInfo(), Name)); - for (auto *M : Macro->overrides()) - ModuleMacroRecord.push_back(getSubmoduleID(M->getOwningModule())); - - Stream.EmitRecord(PP_MODULE_MACRO, ModuleMacroRecord); - ModuleMacroRecord.clear(); - - // Enqueue overridden macros once we've visited all their ancestors. - for (auto *M : Macro->overrides()) - if (++Visits[M] == M->getNumOverridingMacros()) - Worklist.push_back(M); - - EmittedModuleMacros = true; - } - - if (Record.empty() && !EmittedModuleMacros) - continue; - - IdentMacroDirectivesOffsetMap[Name] = StartOffset; - Stream.EmitRecord(PP_MACRO_DIRECTIVE_HISTORY, Record); - Record.clear(); - } - - /// Offsets of each of the macros into the bitstream, indexed by - /// the local macro ID - /// - /// For each identifier that is associated with a macro, this map - /// provides the offset into the bitstream where that macro is - /// defined. - std::vector<uint32_t> MacroOffsets; - - for (unsigned I = 0, N = MacroInfosToEmit.size(); I != N; ++I) { - const IdentifierInfo *Name = MacroInfosToEmit[I].Name; - MacroInfo *MI = MacroInfosToEmit[I].MI; - MacroID ID = MacroInfosToEmit[I].ID; - - if (ID < FirstMacroID) { - assert(0 && "Loaded MacroInfo entered MacroInfosToEmit ?"); - continue; - } - - // Record the local offset of this macro. - unsigned Index = ID - FirstMacroID; - if (Index == MacroOffsets.size()) - MacroOffsets.push_back(Stream.GetCurrentBitNo()); - else { - if (Index > MacroOffsets.size()) - MacroOffsets.resize(Index + 1); - - MacroOffsets[Index] = Stream.GetCurrentBitNo(); - } - - AddIdentifierRef(Name, Record); - AddSourceLocation(MI->getDefinitionLoc(), Record); - AddSourceLocation(MI->getDefinitionEndLoc(), Record); - Record.push_back(MI->isUsed()); - Record.push_back(MI->isUsedForHeaderGuard()); - unsigned Code; - if (MI->isObjectLike()) { - Code = PP_MACRO_OBJECT_LIKE; - } else { - Code = PP_MACRO_FUNCTION_LIKE; - - Record.push_back(MI->isC99Varargs()); - Record.push_back(MI->isGNUVarargs()); - Record.push_back(MI->hasCommaPasting()); - Record.push_back(MI->getNumParams()); - for (const IdentifierInfo *Param : MI->params()) - AddIdentifierRef(Param, Record); - } - - // If we have a detailed preprocessing record, record the macro definition - // ID that corresponds to this macro. - if (PPRec) - Record.push_back(MacroDefinitions[PPRec->findMacroDefinition(MI)]); - - Stream.EmitRecord(Code, Record); - Record.clear(); - - // Emit the tokens array. - for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) { - // Note that we know that the preprocessor does not have any annotation - // tokens in it because they are created by the parser, and thus can't - // be in a macro definition. - const Token &Tok = MI->getReplacementToken(TokNo); - AddToken(Tok, Record); - Stream.EmitRecord(PP_TOKEN, Record); - Record.clear(); - } - ++NumMacros; - } - - Stream.ExitBlock(); - - // Write the offsets table for macro IDs. - using namespace llvm; - - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(MACRO_OFFSET)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macros - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - - unsigned MacroOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - { - RecordData::value_type Record[] = {MACRO_OFFSET, MacroOffsets.size(), - FirstMacroID - NUM_PREDEF_MACRO_IDS}; - Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record, bytes(MacroOffsets)); - } -} - -void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { - if (PPRec.local_begin() == PPRec.local_end()) - return; - - SmallVector<PPEntityOffset, 64> PreprocessedEntityOffsets; - - // Enter the preprocessor block. - Stream.EnterSubblock(PREPROCESSOR_DETAIL_BLOCK_ID, 3); - - // If the preprocessor has a preprocessing record, emit it. - unsigned NumPreprocessingRecords = 0; - using namespace llvm; - - // Set up the abbreviation for - unsigned InclusionAbbrev = 0; - { - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(PPD_INCLUSION_DIRECTIVE)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // filename length - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // in quotes - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // kind - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // imported module - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - InclusionAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - } - - unsigned FirstPreprocessorEntityID - = (Chain ? PPRec.getNumLoadedPreprocessedEntities() : 0) - + NUM_PREDEF_PP_ENTITY_IDS; - unsigned NextPreprocessorEntityID = FirstPreprocessorEntityID; - RecordData Record; - for (PreprocessingRecord::iterator E = PPRec.local_begin(), - EEnd = PPRec.local_end(); - E != EEnd; - (void)++E, ++NumPreprocessingRecords, ++NextPreprocessorEntityID) { - Record.clear(); - - PreprocessedEntityOffsets.push_back( - PPEntityOffset((*E)->getSourceRange(), Stream.GetCurrentBitNo())); - - if (auto *MD = dyn_cast<MacroDefinitionRecord>(*E)) { - // Record this macro definition's ID. - MacroDefinitions[MD] = NextPreprocessorEntityID; - - AddIdentifierRef(MD->getName(), Record); - Stream.EmitRecord(PPD_MACRO_DEFINITION, Record); - continue; - } - - if (auto *ME = dyn_cast<MacroExpansion>(*E)) { - Record.push_back(ME->isBuiltinMacro()); - if (ME->isBuiltinMacro()) - AddIdentifierRef(ME->getName(), Record); - else - Record.push_back(MacroDefinitions[ME->getDefinition()]); - Stream.EmitRecord(PPD_MACRO_EXPANSION, Record); - continue; - } - - if (auto *ID = dyn_cast<InclusionDirective>(*E)) { - Record.push_back(PPD_INCLUSION_DIRECTIVE); - Record.push_back(ID->getFileName().size()); - Record.push_back(ID->wasInQuotes()); - Record.push_back(static_cast<unsigned>(ID->getKind())); - Record.push_back(ID->importedModule()); - SmallString<64> Buffer; - Buffer += ID->getFileName(); - // Check that the FileEntry is not null because it was not resolved and - // we create a PCH even with compiler errors. - if (ID->getFile()) - Buffer += ID->getFile()->getName(); - Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer); - continue; - } - - llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter"); - } - Stream.ExitBlock(); - - // Write the offsets table for the preprocessing record. - if (NumPreprocessingRecords > 0) { - assert(PreprocessedEntityOffsets.size() == NumPreprocessingRecords); - - // Write the offsets table for identifier IDs. - using namespace llvm; - - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(PPD_ENTITIES_OFFSETS)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first pp entity - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned PPEOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - RecordData::value_type Record[] = {PPD_ENTITIES_OFFSETS, - FirstPreprocessorEntityID - - NUM_PREDEF_PP_ENTITY_IDS}; - Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record, - bytes(PreprocessedEntityOffsets)); - } - - // Write the skipped region table for the preprocessing record. - ArrayRef<SourceRange> SkippedRanges = PPRec.getSkippedRanges(); - if (SkippedRanges.size() > 0) { - std::vector<PPSkippedRange> SerializedSkippedRanges; - SerializedSkippedRanges.reserve(SkippedRanges.size()); - for (auto const& Range : SkippedRanges) - SerializedSkippedRanges.emplace_back(Range); - - using namespace llvm; - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(PPD_SKIPPED_RANGES)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned PPESkippedRangeAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - Record.clear(); - Record.push_back(PPD_SKIPPED_RANGES); - Stream.EmitRecordWithBlob(PPESkippedRangeAbbrev, Record, - bytes(SerializedSkippedRanges)); - } -} - -unsigned ASTWriter::getLocalOrImportedSubmoduleID(Module *Mod) { - if (!Mod) - return 0; - - llvm::DenseMap<Module *, unsigned>::iterator Known = SubmoduleIDs.find(Mod); - if (Known != SubmoduleIDs.end()) - return Known->second; - - auto *Top = Mod->getTopLevelModule(); - if (Top != WritingModule && - (getLangOpts().CompilingPCH || - !Top->fullModuleNameIs(StringRef(getLangOpts().CurrentModule)))) - return 0; - - return SubmoduleIDs[Mod] = NextSubmoduleID++; -} - -unsigned ASTWriter::getSubmoduleID(Module *Mod) { - // FIXME: This can easily happen, if we have a reference to a submodule that - // did not result in us loading a module file for that submodule. For - // instance, a cross-top-level-module 'conflict' declaration will hit this. - unsigned ID = getLocalOrImportedSubmoduleID(Mod); - assert((ID || !Mod) && - "asked for module ID for non-local, non-imported module"); - return ID; -} - -/// Compute the number of modules within the given tree (including the -/// given module). -static unsigned getNumberOfModules(Module *Mod) { - unsigned ChildModules = 0; - for (auto Sub = Mod->submodule_begin(), SubEnd = Mod->submodule_end(); - Sub != SubEnd; ++Sub) - ChildModules += getNumberOfModules(*Sub); - - return ChildModules + 1; -} - -void ASTWriter::WriteSubmodules(Module *WritingModule) { - // Enter the submodule description block. - Stream.EnterSubblock(SUBMODULE_BLOCK_ID, /*bits for abbreviations*/5); - - // Write the abbreviations needed for the submodules block. - using namespace llvm; - - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_DEFINITION)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Kind - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExternC - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferSubmodules... - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit... - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild... - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ConfigMacrosExh... - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ModuleMapIsPriv... - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name - unsigned DefinitionAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_UMBRELLA_HEADER)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name - unsigned UmbrellaAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_HEADER)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name - unsigned HeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_TOPHEADER)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name - unsigned TopHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_UMBRELLA_DIR)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name - unsigned UmbrellaDirAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_REQUIRES)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // State - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Feature - unsigned RequiresAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_EXCLUDED_HEADER)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name - unsigned ExcludedHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_TEXTUAL_HEADER)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name - unsigned TextualHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_HEADER)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name - unsigned PrivateHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_TEXTUAL_HEADER)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name - unsigned PrivateTextualHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_LINK_LIBRARY)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name - unsigned LinkLibraryAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_CONFIG_MACRO)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Macro name - unsigned ConfigMacroAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_CONFLICT)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Other module - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Message - unsigned ConflictAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_EXPORT_AS)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Macro name - unsigned ExportAsAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - // Write the submodule metadata block. - RecordData::value_type Record[] = { - getNumberOfModules(WritingModule), - FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS}; - Stream.EmitRecord(SUBMODULE_METADATA, Record); - - // Write all of the submodules. - std::queue<Module *> Q; - Q.push(WritingModule); - while (!Q.empty()) { - Module *Mod = Q.front(); - Q.pop(); - unsigned ID = getSubmoduleID(Mod); - - uint64_t ParentID = 0; - if (Mod->Parent) { - assert(SubmoduleIDs[Mod->Parent] && "Submodule parent not written?"); - ParentID = SubmoduleIDs[Mod->Parent]; - } - - // Emit the definition of the block. - { - RecordData::value_type Record[] = {SUBMODULE_DEFINITION, - ID, - ParentID, - (RecordData::value_type)Mod->Kind, - Mod->IsFramework, - Mod->IsExplicit, - Mod->IsSystem, - Mod->IsExternC, - Mod->InferSubmodules, - Mod->InferExplicitSubmodules, - Mod->InferExportWildcard, - Mod->ConfigMacrosExhaustive, - Mod->ModuleMapIsPrivate}; - Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name); - } - - // Emit the requirements. - for (const auto &R : Mod->Requirements) { - RecordData::value_type Record[] = {SUBMODULE_REQUIRES, R.second}; - Stream.EmitRecordWithBlob(RequiresAbbrev, Record, R.first); - } - - // Emit the umbrella header, if there is one. - if (auto UmbrellaHeader = Mod->getUmbrellaHeader()) { - RecordData::value_type Record[] = {SUBMODULE_UMBRELLA_HEADER}; - Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record, - UmbrellaHeader.NameAsWritten); - } else if (auto UmbrellaDir = Mod->getUmbrellaDir()) { - RecordData::value_type Record[] = {SUBMODULE_UMBRELLA_DIR}; - Stream.EmitRecordWithBlob(UmbrellaDirAbbrev, Record, - UmbrellaDir.NameAsWritten); - } - - // Emit the headers. - struct { - unsigned RecordKind; - unsigned Abbrev; - Module::HeaderKind HeaderKind; - } HeaderLists[] = { - {SUBMODULE_HEADER, HeaderAbbrev, Module::HK_Normal}, - {SUBMODULE_TEXTUAL_HEADER, TextualHeaderAbbrev, Module::HK_Textual}, - {SUBMODULE_PRIVATE_HEADER, PrivateHeaderAbbrev, Module::HK_Private}, - {SUBMODULE_PRIVATE_TEXTUAL_HEADER, PrivateTextualHeaderAbbrev, - Module::HK_PrivateTextual}, - {SUBMODULE_EXCLUDED_HEADER, ExcludedHeaderAbbrev, Module::HK_Excluded} - }; - for (auto &HL : HeaderLists) { - RecordData::value_type Record[] = {HL.RecordKind}; - for (auto &H : Mod->Headers[HL.HeaderKind]) - Stream.EmitRecordWithBlob(HL.Abbrev, Record, H.NameAsWritten); - } - - // Emit the top headers. - { - auto TopHeaders = Mod->getTopHeaders(PP->getFileManager()); - RecordData::value_type Record[] = {SUBMODULE_TOPHEADER}; - for (auto *H : TopHeaders) - Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, H->getName()); - } - - // Emit the imports. - if (!Mod->Imports.empty()) { - RecordData Record; - for (auto *I : Mod->Imports) - Record.push_back(getSubmoduleID(I)); - Stream.EmitRecord(SUBMODULE_IMPORTS, Record); - } - - // Emit the exports. - if (!Mod->Exports.empty()) { - RecordData Record; - for (const auto &E : Mod->Exports) { - // FIXME: This may fail; we don't require that all exported modules - // are local or imported. - Record.push_back(getSubmoduleID(E.getPointer())); - Record.push_back(E.getInt()); - } - Stream.EmitRecord(SUBMODULE_EXPORTS, Record); - } - - //FIXME: How do we emit the 'use'd modules? They may not be submodules. - // Might be unnecessary as use declarations are only used to build the - // module itself. - - // Emit the link libraries. - for (const auto &LL : Mod->LinkLibraries) { - RecordData::value_type Record[] = {SUBMODULE_LINK_LIBRARY, - LL.IsFramework}; - Stream.EmitRecordWithBlob(LinkLibraryAbbrev, Record, LL.Library); - } - - // Emit the conflicts. - for (const auto &C : Mod->Conflicts) { - // FIXME: This may fail; we don't require that all conflicting modules - // are local or imported. - RecordData::value_type Record[] = {SUBMODULE_CONFLICT, - getSubmoduleID(C.Other)}; - Stream.EmitRecordWithBlob(ConflictAbbrev, Record, C.Message); - } - - // Emit the configuration macros. - for (const auto &CM : Mod->ConfigMacros) { - RecordData::value_type Record[] = {SUBMODULE_CONFIG_MACRO}; - Stream.EmitRecordWithBlob(ConfigMacroAbbrev, Record, CM); - } - - // Emit the initializers, if any. - RecordData Inits; - for (Decl *D : Context->getModuleInitializers(Mod)) - Inits.push_back(GetDeclRef(D)); - if (!Inits.empty()) - Stream.EmitRecord(SUBMODULE_INITIALIZERS, Inits); - - // Emit the name of the re-exported module, if any. - if (!Mod->ExportAsModule.empty()) { - RecordData::value_type Record[] = {SUBMODULE_EXPORT_AS}; - Stream.EmitRecordWithBlob(ExportAsAbbrev, Record, Mod->ExportAsModule); - } - - // Queue up the submodules of this module. - for (auto *M : Mod->submodules()) - Q.push(M); - } - - Stream.ExitBlock(); - - assert((NextSubmoduleID - FirstSubmoduleID == - getNumberOfModules(WritingModule)) && - "Wrong # of submodules; found a reference to a non-local, " - "non-imported submodule?"); -} - -void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, - bool isModule) { - llvm::SmallDenseMap<const DiagnosticsEngine::DiagState *, unsigned, 64> - DiagStateIDMap; - unsigned CurrID = 0; - RecordData Record; - - auto EncodeDiagStateFlags = - [](const DiagnosticsEngine::DiagState *DS) -> unsigned { - unsigned Result = (unsigned)DS->ExtBehavior; - for (unsigned Val : - {(unsigned)DS->IgnoreAllWarnings, (unsigned)DS->EnableAllWarnings, - (unsigned)DS->WarningsAsErrors, (unsigned)DS->ErrorsAsFatal, - (unsigned)DS->SuppressSystemWarnings}) - Result = (Result << 1) | Val; - return Result; - }; - - unsigned Flags = EncodeDiagStateFlags(Diag.DiagStatesByLoc.FirstDiagState); - Record.push_back(Flags); - - auto AddDiagState = [&](const DiagnosticsEngine::DiagState *State, - bool IncludeNonPragmaStates) { - // Ensure that the diagnostic state wasn't modified since it was created. - // We will not correctly round-trip this information otherwise. - assert(Flags == EncodeDiagStateFlags(State) && - "diag state flags vary in single AST file"); - - unsigned &DiagStateID = DiagStateIDMap[State]; - Record.push_back(DiagStateID); - - if (DiagStateID == 0) { - DiagStateID = ++CurrID; - - // Add a placeholder for the number of mappings. - auto SizeIdx = Record.size(); - Record.emplace_back(); - for (const auto &I : *State) { - if (I.second.isPragma() || IncludeNonPragmaStates) { - Record.push_back(I.first); - Record.push_back(I.second.serialize()); - } - } - // Update the placeholder. - Record[SizeIdx] = (Record.size() - SizeIdx) / 2; - } - }; - - AddDiagState(Diag.DiagStatesByLoc.FirstDiagState, isModule); - - // Reserve a spot for the number of locations with state transitions. - auto NumLocationsIdx = Record.size(); - Record.emplace_back(); - - // Emit the state transitions. - unsigned NumLocations = 0; - for (auto &FileIDAndFile : Diag.DiagStatesByLoc.Files) { - if (!FileIDAndFile.first.isValid() || - !FileIDAndFile.second.HasLocalTransitions) - continue; - ++NumLocations; - - SourceLocation Loc = Diag.SourceMgr->getComposedLoc(FileIDAndFile.first, 0); - assert(!Loc.isInvalid() && "start loc for valid FileID is invalid"); - AddSourceLocation(Loc, Record); - - Record.push_back(FileIDAndFile.second.StateTransitions.size()); - for (auto &StatePoint : FileIDAndFile.second.StateTransitions) { - Record.push_back(StatePoint.Offset); - AddDiagState(StatePoint.State, false); - } - } - - // Backpatch the number of locations. - Record[NumLocationsIdx] = NumLocations; - - // Emit CurDiagStateLoc. Do it last in order to match source order. - // - // This also protects against a hypothetical corner case with simulating - // -Werror settings for implicit modules in the ASTReader, where reading - // CurDiagState out of context could change whether warning pragmas are - // treated as errors. - AddSourceLocation(Diag.DiagStatesByLoc.CurDiagStateLoc, Record); - AddDiagState(Diag.DiagStatesByLoc.CurDiagState, false); - - Stream.EmitRecord(DIAG_PRAGMA_MAPPINGS, Record); -} - -//===----------------------------------------------------------------------===// -// Type Serialization -//===----------------------------------------------------------------------===// - -/// Write the representation of a type to the AST stream. -void ASTWriter::WriteType(QualType T) { - TypeIdx &IdxRef = TypeIdxs[T]; - if (IdxRef.getIndex() == 0) // we haven't seen this type before. - IdxRef = TypeIdx(NextTypeID++); - TypeIdx Idx = IdxRef; - - assert(Idx.getIndex() >= FirstTypeID && "Re-writing a type from a prior AST"); - - RecordData Record; - - // Emit the type's representation. - ASTTypeWriter W(*this, Record); - W.Visit(T); - uint64_t Offset = W.Emit(); - - // Record the offset for this type. - unsigned Index = Idx.getIndex() - FirstTypeID; - if (TypeOffsets.size() == Index) - TypeOffsets.push_back(Offset); - else if (TypeOffsets.size() < Index) { - TypeOffsets.resize(Index + 1); - TypeOffsets[Index] = Offset; - } else { - llvm_unreachable("Types emitted in wrong order"); - } -} - -//===----------------------------------------------------------------------===// -// Declaration Serialization -//===----------------------------------------------------------------------===// - -/// Write the block containing all of the declaration IDs -/// lexically declared within the given DeclContext. -/// -/// \returns the offset of the DECL_CONTEXT_LEXICAL block within the -/// bitstream, or 0 if no block was written. -uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, - DeclContext *DC) { - if (DC->decls_empty()) - return 0; - - uint64_t Offset = Stream.GetCurrentBitNo(); - SmallVector<uint32_t, 128> KindDeclPairs; - for (const auto *D : DC->decls()) { - KindDeclPairs.push_back(D->getKind()); - KindDeclPairs.push_back(GetDeclRef(D)); - } - - ++NumLexicalDeclContexts; - RecordData::value_type Record[] = {DECL_CONTEXT_LEXICAL}; - Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, - bytes(KindDeclPairs)); - return Offset; -} - -void ASTWriter::WriteTypeDeclOffsets() { - using namespace llvm; - - // Write the type offsets array - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(TYPE_OFFSET)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // base type index - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block - unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - { - RecordData::value_type Record[] = {TYPE_OFFSET, TypeOffsets.size(), - FirstTypeID - NUM_PREDEF_TYPE_IDS}; - Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, bytes(TypeOffsets)); - } - - // Write the declaration offsets array - Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(DECL_OFFSET)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // base decl ID - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block - unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - { - RecordData::value_type Record[] = {DECL_OFFSET, DeclOffsets.size(), - FirstDeclID - NUM_PREDEF_DECL_IDS}; - Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, bytes(DeclOffsets)); - } -} - -void ASTWriter::WriteFileDeclIDsMap() { - using namespace llvm; - - SmallVector<std::pair<FileID, DeclIDInFileInfo *>, 64> SortedFileDeclIDs( - FileDeclIDs.begin(), FileDeclIDs.end()); - llvm::sort(SortedFileDeclIDs, llvm::less_first()); - - // Join the vectors of DeclIDs from all files. - SmallVector<DeclID, 256> FileGroupedDeclIDs; - for (auto &FileDeclEntry : SortedFileDeclIDs) { - DeclIDInFileInfo &Info = *FileDeclEntry.second; - Info.FirstDeclIndex = FileGroupedDeclIDs.size(); - for (auto &LocDeclEntry : Info.DeclIDs) - FileGroupedDeclIDs.push_back(LocDeclEntry.second); - } - - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(FILE_SORTED_DECLS)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev)); - RecordData::value_type Record[] = {FILE_SORTED_DECLS, - FileGroupedDeclIDs.size()}; - Stream.EmitRecordWithBlob(AbbrevCode, Record, bytes(FileGroupedDeclIDs)); -} - -void ASTWriter::WriteComments() { - Stream.EnterSubblock(COMMENTS_BLOCK_ID, 3); - auto _ = llvm::make_scope_exit([this] { Stream.ExitBlock(); }); - if (!PP->getPreprocessorOpts().WriteCommentListToPCH) - return; - ArrayRef<RawComment *> RawComments = Context->Comments.getComments(); - RecordData Record; - for (const auto *I : RawComments) { - Record.clear(); - AddSourceRange(I->getSourceRange(), Record); - Record.push_back(I->getKind()); - Record.push_back(I->isTrailingComment()); - Record.push_back(I->isAlmostTrailingComment()); - Stream.EmitRecord(COMMENTS_RAW_COMMENT, Record); - } -} - -//===----------------------------------------------------------------------===// -// Global Method Pool and Selector Serialization -//===----------------------------------------------------------------------===// - -namespace { - -// Trait used for the on-disk hash table used in the method pool. -class ASTMethodPoolTrait { - ASTWriter &Writer; - -public: - using key_type = Selector; - using key_type_ref = key_type; - - struct data_type { - SelectorID ID; - ObjCMethodList Instance, Factory; - }; - using data_type_ref = const data_type &; - - using hash_value_type = unsigned; - using offset_type = unsigned; - - explicit ASTMethodPoolTrait(ASTWriter &Writer) : Writer(Writer) {} - - static hash_value_type ComputeHash(Selector Sel) { - return serialization::ComputeHash(Sel); - } - - std::pair<unsigned, unsigned> - EmitKeyDataLength(raw_ostream& Out, Selector Sel, - data_type_ref Methods) { - using namespace llvm::support; - - endian::Writer LE(Out, little); - unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4); - LE.write<uint16_t>(KeyLen); - unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts - for (const ObjCMethodList *Method = &Methods.Instance; Method; - Method = Method->getNext()) - if (Method->getMethod()) - DataLen += 4; - for (const ObjCMethodList *Method = &Methods.Factory; Method; - Method = Method->getNext()) - if (Method->getMethod()) - DataLen += 4; - LE.write<uint16_t>(DataLen); - return std::make_pair(KeyLen, DataLen); - } - - void EmitKey(raw_ostream& Out, Selector Sel, unsigned) { - using namespace llvm::support; - - endian::Writer LE(Out, little); - uint64_t Start = Out.tell(); - assert((Start >> 32) == 0 && "Selector key offset too large"); - Writer.SetSelectorOffset(Sel, Start); - unsigned N = Sel.getNumArgs(); - LE.write<uint16_t>(N); - if (N == 0) - N = 1; - for (unsigned I = 0; I != N; ++I) - LE.write<uint32_t>( - Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I))); - } - - void EmitData(raw_ostream& Out, key_type_ref, - data_type_ref Methods, unsigned DataLen) { - using namespace llvm::support; - - endian::Writer LE(Out, little); - uint64_t Start = Out.tell(); (void)Start; - LE.write<uint32_t>(Methods.ID); - unsigned NumInstanceMethods = 0; - for (const ObjCMethodList *Method = &Methods.Instance; Method; - Method = Method->getNext()) - if (Method->getMethod()) - ++NumInstanceMethods; - - unsigned NumFactoryMethods = 0; - for (const ObjCMethodList *Method = &Methods.Factory; Method; - Method = Method->getNext()) - if (Method->getMethod()) - ++NumFactoryMethods; - - unsigned InstanceBits = Methods.Instance.getBits(); - assert(InstanceBits < 4); - unsigned InstanceHasMoreThanOneDeclBit = - Methods.Instance.hasMoreThanOneDecl(); - unsigned FullInstanceBits = (NumInstanceMethods << 3) | - (InstanceHasMoreThanOneDeclBit << 2) | - InstanceBits; - unsigned FactoryBits = Methods.Factory.getBits(); - assert(FactoryBits < 4); - unsigned FactoryHasMoreThanOneDeclBit = - Methods.Factory.hasMoreThanOneDecl(); - unsigned FullFactoryBits = (NumFactoryMethods << 3) | - (FactoryHasMoreThanOneDeclBit << 2) | - FactoryBits; - LE.write<uint16_t>(FullInstanceBits); - LE.write<uint16_t>(FullFactoryBits); - for (const ObjCMethodList *Method = &Methods.Instance; Method; - Method = Method->getNext()) - if (Method->getMethod()) - LE.write<uint32_t>(Writer.getDeclID(Method->getMethod())); - for (const ObjCMethodList *Method = &Methods.Factory; Method; - Method = Method->getNext()) - if (Method->getMethod()) - LE.write<uint32_t>(Writer.getDeclID(Method->getMethod())); - - assert(Out.tell() - Start == DataLen && "Data length is wrong"); - } -}; - -} // namespace - -/// Write ObjC data: selectors and the method pool. -/// -/// The method pool contains both instance and factory methods, stored -/// in an on-disk hash table indexed by the selector. The hash table also -/// contains an empty entry for every other selector known to Sema. -void ASTWriter::WriteSelectors(Sema &SemaRef) { - using namespace llvm; - - // Do we have to do anything at all? - if (SemaRef.MethodPool.empty() && SelectorIDs.empty()) - return; - unsigned NumTableEntries = 0; - // Create and write out the blob that contains selectors and the method pool. - { - llvm::OnDiskChainedHashTableGenerator<ASTMethodPoolTrait> Generator; - ASTMethodPoolTrait Trait(*this); - - // Create the on-disk hash table representation. We walk through every - // selector we've seen and look it up in the method pool. - SelectorOffsets.resize(NextSelectorID - FirstSelectorID); - for (auto &SelectorAndID : SelectorIDs) { - Selector S = SelectorAndID.first; - SelectorID ID = SelectorAndID.second; - Sema::GlobalMethodPool::iterator F = SemaRef.MethodPool.find(S); - ASTMethodPoolTrait::data_type Data = { - ID, - ObjCMethodList(), - ObjCMethodList() - }; - if (F != SemaRef.MethodPool.end()) { - Data.Instance = F->second.first; - Data.Factory = F->second.second; - } - // Only write this selector if it's not in an existing AST or something - // changed. - if (Chain && ID < FirstSelectorID) { - // Selector already exists. Did it change? - bool changed = false; - for (ObjCMethodList *M = &Data.Instance; - !changed && M && M->getMethod(); M = M->getNext()) { - if (!M->getMethod()->isFromASTFile()) - changed = true; - } - for (ObjCMethodList *M = &Data.Factory; !changed && M && M->getMethod(); - M = M->getNext()) { - if (!M->getMethod()->isFromASTFile()) - changed = true; - } - if (!changed) - continue; - } else if (Data.Instance.getMethod() || Data.Factory.getMethod()) { - // A new method pool entry. - ++NumTableEntries; - } - Generator.insert(S, Data, Trait); - } - - // Create the on-disk hash table in a buffer. - SmallString<4096> MethodPool; - uint32_t BucketOffset; - { - using namespace llvm::support; - - ASTMethodPoolTrait Trait(*this); - llvm::raw_svector_ostream Out(MethodPool); - // Make sure that no bucket is at offset 0 - endian::write<uint32_t>(Out, 0, little); - BucketOffset = Generator.Emit(Out, Trait); - } - - // Create a blob abbreviation - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(METHOD_POOL)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned MethodPoolAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - // Write the method pool - { - RecordData::value_type Record[] = {METHOD_POOL, BucketOffset, - NumTableEntries}; - Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool); - } - - // Create a blob abbreviation for the selector table offsets. - Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(SELECTOR_OFFSETS)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - // Write the selector offsets table. - { - RecordData::value_type Record[] = { - SELECTOR_OFFSETS, SelectorOffsets.size(), - FirstSelectorID - NUM_PREDEF_SELECTOR_IDS}; - Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record, - bytes(SelectorOffsets)); - } - } -} - -/// Write the selectors referenced in @selector expression into AST file. -void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) { - using namespace llvm; - - if (SemaRef.ReferencedSelectors.empty()) - return; - - RecordData Record; - ASTRecordWriter Writer(*this, Record); - - // Note: this writes out all references even for a dependent AST. But it is - // very tricky to fix, and given that @selector shouldn't really appear in - // headers, probably not worth it. It's not a correctness issue. - for (auto &SelectorAndLocation : SemaRef.ReferencedSelectors) { - Selector Sel = SelectorAndLocation.first; - SourceLocation Loc = SelectorAndLocation.second; - Writer.AddSelectorRef(Sel); - Writer.AddSourceLocation(Loc); - } - Writer.Emit(REFERENCED_SELECTOR_POOL); -} - -//===----------------------------------------------------------------------===// -// Identifier Table Serialization -//===----------------------------------------------------------------------===// - -/// Determine the declaration that should be put into the name lookup table to -/// represent the given declaration in this module. This is usually D itself, -/// but if D was imported and merged into a local declaration, we want the most -/// recent local declaration instead. The chosen declaration will be the most -/// recent declaration in any module that imports this one. -static NamedDecl *getDeclForLocalLookup(const LangOptions &LangOpts, - NamedDecl *D) { - if (!LangOpts.Modules || !D->isFromASTFile()) - return D; - - if (Decl *Redecl = D->getPreviousDecl()) { - // For Redeclarable decls, a prior declaration might be local. - for (; Redecl; Redecl = Redecl->getPreviousDecl()) { - // If we find a local decl, we're done. - if (!Redecl->isFromASTFile()) { - // Exception: in very rare cases (for injected-class-names), not all - // redeclarations are in the same semantic context. Skip ones in a - // different context. They don't go in this lookup table at all. - if (!Redecl->getDeclContext()->getRedeclContext()->Equals( - D->getDeclContext()->getRedeclContext())) - continue; - return cast<NamedDecl>(Redecl); - } - - // If we find a decl from a (chained-)PCH stop since we won't find a - // local one. - if (Redecl->getOwningModuleID() == 0) - break; - } - } else if (Decl *First = D->getCanonicalDecl()) { - // For Mergeable decls, the first decl might be local. - if (!First->isFromASTFile()) - return cast<NamedDecl>(First); - } - - // All declarations are imported. Our most recent declaration will also be - // the most recent one in anyone who imports us. - return D; -} - -namespace { - -class ASTIdentifierTableTrait { - ASTWriter &Writer; - Preprocessor &PP; - IdentifierResolver &IdResolver; - bool IsModule; - bool NeedDecls; - ASTWriter::RecordData *InterestingIdentifierOffsets; - - /// Determines whether this is an "interesting" identifier that needs a - /// full IdentifierInfo structure written into the hash table. Notably, this - /// doesn't check whether the name has macros defined; use PublicMacroIterator - /// to check that. - bool isInterestingIdentifier(const IdentifierInfo *II, uint64_t MacroOffset) { - if (MacroOffset || - II->isPoisoned() || - (IsModule ? II->hasRevertedBuiltin() : II->getObjCOrBuiltinID()) || - II->hasRevertedTokenIDToIdentifier() || - (NeedDecls && II->getFETokenInfo())) - return true; - - return false; - } - -public: - using key_type = IdentifierInfo *; - using key_type_ref = key_type; - - using data_type = IdentID; - using data_type_ref = data_type; - - using hash_value_type = unsigned; - using offset_type = unsigned; - - ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP, - IdentifierResolver &IdResolver, bool IsModule, - ASTWriter::RecordData *InterestingIdentifierOffsets) - : Writer(Writer), PP(PP), IdResolver(IdResolver), IsModule(IsModule), - NeedDecls(!IsModule || !Writer.getLangOpts().CPlusPlus), - InterestingIdentifierOffsets(InterestingIdentifierOffsets) {} - - bool needDecls() const { return NeedDecls; } - - static hash_value_type ComputeHash(const IdentifierInfo* II) { - return llvm::djbHash(II->getName()); - } - - bool isInterestingIdentifier(const IdentifierInfo *II) { - auto MacroOffset = Writer.getMacroDirectivesOffset(II); - return isInterestingIdentifier(II, MacroOffset); - } - - bool isInterestingNonMacroIdentifier(const IdentifierInfo *II) { - return isInterestingIdentifier(II, 0); - } - - std::pair<unsigned, unsigned> - EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) { - unsigned KeyLen = II->getLength() + 1; - unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 - auto MacroOffset = Writer.getMacroDirectivesOffset(II); - if (isInterestingIdentifier(II, MacroOffset)) { - DataLen += 2; // 2 bytes for builtin ID - DataLen += 2; // 2 bytes for flags - if (MacroOffset) - DataLen += 4; // MacroDirectives offset. - - if (NeedDecls) { - for (IdentifierResolver::iterator D = IdResolver.begin(II), - DEnd = IdResolver.end(); - D != DEnd; ++D) - DataLen += 4; - } - } - - using namespace llvm::support; - - endian::Writer LE(Out, little); - - assert((uint16_t)DataLen == DataLen && (uint16_t)KeyLen == KeyLen); - LE.write<uint16_t>(DataLen); - // We emit the key length after the data length so that every - // string is preceded by a 16-bit length. This matches the PTH - // format for storing identifiers. - LE.write<uint16_t>(KeyLen); - return std::make_pair(KeyLen, DataLen); - } - - void EmitKey(raw_ostream& Out, const IdentifierInfo* II, - unsigned KeyLen) { - // Record the location of the key data. This is used when generating - // the mapping from persistent IDs to strings. - Writer.SetIdentifierOffset(II, Out.tell()); - - // Emit the offset of the key/data length information to the interesting - // identifiers table if necessary. - if (InterestingIdentifierOffsets && isInterestingIdentifier(II)) - InterestingIdentifierOffsets->push_back(Out.tell() - 4); - - Out.write(II->getNameStart(), KeyLen); - } - - void EmitData(raw_ostream& Out, IdentifierInfo* II, - IdentID ID, unsigned) { - using namespace llvm::support; - - endian::Writer LE(Out, little); - - auto MacroOffset = Writer.getMacroDirectivesOffset(II); - if (!isInterestingIdentifier(II, MacroOffset)) { - LE.write<uint32_t>(ID << 1); - return; - } - - LE.write<uint32_t>((ID << 1) | 0x01); - uint32_t Bits = (uint32_t)II->getObjCOrBuiltinID(); - assert((Bits & 0xffff) == Bits && "ObjCOrBuiltinID too big for ASTReader."); - LE.write<uint16_t>(Bits); - Bits = 0; - bool HadMacroDefinition = MacroOffset != 0; - Bits = (Bits << 1) | unsigned(HadMacroDefinition); - Bits = (Bits << 1) | unsigned(II->isExtensionToken()); - Bits = (Bits << 1) | unsigned(II->isPoisoned()); - Bits = (Bits << 1) | unsigned(II->hasRevertedBuiltin()); - Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier()); - Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword()); - LE.write<uint16_t>(Bits); - - if (HadMacroDefinition) - LE.write<uint32_t>(MacroOffset); - - if (NeedDecls) { - // Emit the declaration IDs in reverse order, because the - // IdentifierResolver provides the declarations as they would be - // visible (e.g., the function "stat" would come before the struct - // "stat"), but the ASTReader adds declarations to the end of the list - // (so we need to see the struct "stat" before the function "stat"). - // Only emit declarations that aren't from a chained PCH, though. - SmallVector<NamedDecl *, 16> Decls(IdResolver.begin(II), - IdResolver.end()); - for (SmallVectorImpl<NamedDecl *>::reverse_iterator D = Decls.rbegin(), - DEnd = Decls.rend(); - D != DEnd; ++D) - LE.write<uint32_t>( - Writer.getDeclID(getDeclForLocalLookup(PP.getLangOpts(), *D))); - } - } -}; - -} // namespace - -/// Write the identifier table into the AST file. -/// -/// The identifier table consists of a blob containing string data -/// (the actual identifiers themselves) and a separate "offsets" index -/// that maps identifier IDs to locations within the blob. -void ASTWriter::WriteIdentifierTable(Preprocessor &PP, - IdentifierResolver &IdResolver, - bool IsModule) { - using namespace llvm; - - RecordData InterestingIdents; - - // Create and write out the blob that contains the identifier - // strings. - { - llvm::OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator; - ASTIdentifierTableTrait Trait( - *this, PP, IdResolver, IsModule, - (getLangOpts().CPlusPlus && IsModule) ? &InterestingIdents : nullptr); - - // Look for any identifiers that were named while processing the - // headers, but are otherwise not needed. We add these to the hash - // table to enable checking of the predefines buffer in the case - // where the user adds new macro definitions when building the AST - // file. - SmallVector<const IdentifierInfo *, 128> IIs; - for (const auto &ID : PP.getIdentifierTable()) - IIs.push_back(ID.second); - // Sort the identifiers lexicographically before getting them references so - // that their order is stable. - llvm::sort(IIs, llvm::less_ptr<IdentifierInfo>()); - for (const IdentifierInfo *II : IIs) - if (Trait.isInterestingNonMacroIdentifier(II)) - getIdentifierRef(II); - - // Create the on-disk hash table representation. We only store offsets - // for identifiers that appear here for the first time. - IdentifierOffsets.resize(NextIdentID - FirstIdentID); - for (auto IdentIDPair : IdentifierIDs) { - auto *II = const_cast<IdentifierInfo *>(IdentIDPair.first); - IdentID ID = IdentIDPair.second; - assert(II && "NULL identifier in identifier table"); - // Write out identifiers if either the ID is local or the identifier has - // changed since it was loaded. - if (ID >= FirstIdentID || !Chain || !II->isFromAST() - || II->hasChangedSinceDeserialization() || - (Trait.needDecls() && - II->hasFETokenInfoChangedSinceDeserialization())) - Generator.insert(II, ID, Trait); - } - - // Create the on-disk hash table in a buffer. - SmallString<4096> IdentifierTable; - uint32_t BucketOffset; - { - using namespace llvm::support; - - llvm::raw_svector_ostream Out(IdentifierTable); - // Make sure that no bucket is at offset 0 - endian::write<uint32_t>(Out, 0, little); - BucketOffset = Generator.Emit(Out, Trait); - } - - // Create a blob abbreviation - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_TABLE)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned IDTableAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - // Write the identifier table - RecordData::value_type Record[] = {IDENTIFIER_TABLE, BucketOffset}; - Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable); - } - - // Write the offsets table for identifier IDs. - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_OFFSET)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - -#ifndef NDEBUG - for (unsigned I = 0, N = IdentifierOffsets.size(); I != N; ++I) - assert(IdentifierOffsets[I] && "Missing identifier offset?"); -#endif - - RecordData::value_type Record[] = {IDENTIFIER_OFFSET, - IdentifierOffsets.size(), - FirstIdentID - NUM_PREDEF_IDENT_IDS}; - Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record, - bytes(IdentifierOffsets)); - - // In C++, write the list of interesting identifiers (those that are - // defined as macros, poisoned, or similar unusual things). - if (!InterestingIdents.empty()) - Stream.EmitRecord(INTERESTING_IDENTIFIERS, InterestingIdents); -} - -//===----------------------------------------------------------------------===// -// DeclContext's Name Lookup Table Serialization -//===----------------------------------------------------------------------===// - -namespace { - -// Trait used for the on-disk hash table used in the method pool. -class ASTDeclContextNameLookupTrait { - ASTWriter &Writer; - llvm::SmallVector<DeclID, 64> DeclIDs; - -public: - using key_type = DeclarationNameKey; - using key_type_ref = key_type; - - /// A start and end index into DeclIDs, representing a sequence of decls. - using data_type = std::pair<unsigned, unsigned>; - using data_type_ref = const data_type &; - - using hash_value_type = unsigned; - using offset_type = unsigned; - - explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) {} - - template<typename Coll> - data_type getData(const Coll &Decls) { - unsigned Start = DeclIDs.size(); - for (NamedDecl *D : Decls) { - DeclIDs.push_back( - Writer.GetDeclRef(getDeclForLocalLookup(Writer.getLangOpts(), D))); - } - return std::make_pair(Start, DeclIDs.size()); - } - - data_type ImportData(const reader::ASTDeclContextNameLookupTrait::data_type &FromReader) { - unsigned Start = DeclIDs.size(); - for (auto ID : FromReader) - DeclIDs.push_back(ID); - return std::make_pair(Start, DeclIDs.size()); - } - - static bool EqualKey(key_type_ref a, key_type_ref b) { - return a == b; - } - - hash_value_type ComputeHash(DeclarationNameKey Name) { - return Name.getHash(); - } - - void EmitFileRef(raw_ostream &Out, ModuleFile *F) const { - assert(Writer.hasChain() && - "have reference to loaded module file but no chain?"); - - using namespace llvm::support; - - endian::write<uint32_t>(Out, Writer.getChain()->getModuleFileID(F), little); - } - - std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &Out, - DeclarationNameKey Name, - data_type_ref Lookup) { - using namespace llvm::support; - - endian::Writer LE(Out, little); - unsigned KeyLen = 1; - switch (Name.getKind()) { - case DeclarationName::Identifier: - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - case DeclarationName::CXXLiteralOperatorName: - case DeclarationName::CXXDeductionGuideName: - KeyLen += 4; - break; - case DeclarationName::CXXOperatorName: - KeyLen += 1; - break; - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - case DeclarationName::CXXUsingDirective: - break; - } - LE.write<uint16_t>(KeyLen); - - // 4 bytes for each DeclID. - unsigned DataLen = 4 * (Lookup.second - Lookup.first); - assert(uint16_t(DataLen) == DataLen && - "too many decls for serialized lookup result"); - LE.write<uint16_t>(DataLen); - - return std::make_pair(KeyLen, DataLen); - } - - void EmitKey(raw_ostream &Out, DeclarationNameKey Name, unsigned) { - using namespace llvm::support; - - endian::Writer LE(Out, little); - LE.write<uint8_t>(Name.getKind()); - switch (Name.getKind()) { - case DeclarationName::Identifier: - case DeclarationName::CXXLiteralOperatorName: - case DeclarationName::CXXDeductionGuideName: - LE.write<uint32_t>(Writer.getIdentifierRef(Name.getIdentifier())); - return; - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - LE.write<uint32_t>(Writer.getSelectorRef(Name.getSelector())); - return; - case DeclarationName::CXXOperatorName: - assert(Name.getOperatorKind() < NUM_OVERLOADED_OPERATORS && - "Invalid operator?"); - LE.write<uint8_t>(Name.getOperatorKind()); - return; - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - case DeclarationName::CXXUsingDirective: - return; - } - - llvm_unreachable("Invalid name kind?"); - } - - void EmitData(raw_ostream &Out, key_type_ref, data_type Lookup, - unsigned DataLen) { - using namespace llvm::support; - - endian::Writer LE(Out, little); - uint64_t Start = Out.tell(); (void)Start; - for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I) - LE.write<uint32_t>(DeclIDs[I]); - assert(Out.tell() - Start == DataLen && "Data length is wrong"); - } -}; - -} // namespace - -bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result, - DeclContext *DC) { - return Result.hasExternalDecls() && - DC->hasNeedToReconcileExternalVisibleStorage(); -} - -bool ASTWriter::isLookupResultEntirelyExternal(StoredDeclsList &Result, - DeclContext *DC) { - for (auto *D : Result.getLookupResult()) - if (!getDeclForLocalLookup(getLangOpts(), D)->isFromASTFile()) - return false; - - return true; -} - -void -ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC, - llvm::SmallVectorImpl<char> &LookupTable) { - assert(!ConstDC->hasLazyLocalLexicalLookups() && - !ConstDC->hasLazyExternalLexicalLookups() && - "must call buildLookups first"); - - // FIXME: We need to build the lookups table, which is logically const. - auto *DC = const_cast<DeclContext*>(ConstDC); - assert(DC == DC->getPrimaryContext() && "only primary DC has lookup table"); - - // Create the on-disk hash table representation. - MultiOnDiskHashTableGenerator<reader::ASTDeclContextNameLookupTrait, - ASTDeclContextNameLookupTrait> Generator; - ASTDeclContextNameLookupTrait Trait(*this); - - // The first step is to collect the declaration names which we need to - // serialize into the name lookup table, and to collect them in a stable - // order. - SmallVector<DeclarationName, 16> Names; - - // We also build up small sets of the constructor and conversion function - // names which are visible. - llvm::SmallSet<DeclarationName, 8> ConstructorNameSet, ConversionNameSet; - - for (auto &Lookup : *DC->buildLookup()) { - auto &Name = Lookup.first; - auto &Result = Lookup.second; - - // If there are no local declarations in our lookup result, we - // don't need to write an entry for the name at all. If we can't - // write out a lookup set without performing more deserialization, - // just skip this entry. - if (isLookupResultExternal(Result, DC) && - isLookupResultEntirelyExternal(Result, DC)) - continue; - - // We also skip empty results. If any of the results could be external and - // the currently available results are empty, then all of the results are - // external and we skip it above. So the only way we get here with an empty - // results is when no results could have been external *and* we have - // external results. - // - // FIXME: While we might want to start emitting on-disk entries for negative - // lookups into a decl context as an optimization, today we *have* to skip - // them because there are names with empty lookup results in decl contexts - // which we can't emit in any stable ordering: we lookup constructors and - // conversion functions in the enclosing namespace scope creating empty - // results for them. This in almost certainly a bug in Clang's name lookup, - // but that is likely to be hard or impossible to fix and so we tolerate it - // here by omitting lookups with empty results. - if (Lookup.second.getLookupResult().empty()) - continue; - - switch (Lookup.first.getNameKind()) { - default: - Names.push_back(Lookup.first); - break; - - case DeclarationName::CXXConstructorName: - assert(isa<CXXRecordDecl>(DC) && - "Cannot have a constructor name outside of a class!"); - ConstructorNameSet.insert(Name); - break; - - case DeclarationName::CXXConversionFunctionName: - assert(isa<CXXRecordDecl>(DC) && - "Cannot have a conversion function name outside of a class!"); - ConversionNameSet.insert(Name); - break; - } - } - - // Sort the names into a stable order. - llvm::sort(Names); - - if (auto *D = dyn_cast<CXXRecordDecl>(DC)) { - // We need to establish an ordering of constructor and conversion function - // names, and they don't have an intrinsic ordering. - - // First we try the easy case by forming the current context's constructor - // name and adding that name first. This is a very useful optimization to - // avoid walking the lexical declarations in many cases, and it also - // handles the only case where a constructor name can come from some other - // lexical context -- when that name is an implicit constructor merged from - // another declaration in the redecl chain. Any non-implicit constructor or - // conversion function which doesn't occur in all the lexical contexts - // would be an ODR violation. - auto ImplicitCtorName = Context->DeclarationNames.getCXXConstructorName( - Context->getCanonicalType(Context->getRecordType(D))); - if (ConstructorNameSet.erase(ImplicitCtorName)) - Names.push_back(ImplicitCtorName); - - // If we still have constructors or conversion functions, we walk all the - // names in the decl and add the constructors and conversion functions - // which are visible in the order they lexically occur within the context. - if (!ConstructorNameSet.empty() || !ConversionNameSet.empty()) - for (Decl *ChildD : cast<CXXRecordDecl>(DC)->decls()) - if (auto *ChildND = dyn_cast<NamedDecl>(ChildD)) { - auto Name = ChildND->getDeclName(); - switch (Name.getNameKind()) { - default: - continue; - - case DeclarationName::CXXConstructorName: - if (ConstructorNameSet.erase(Name)) - Names.push_back(Name); - break; - - case DeclarationName::CXXConversionFunctionName: - if (ConversionNameSet.erase(Name)) - Names.push_back(Name); - break; - } - - if (ConstructorNameSet.empty() && ConversionNameSet.empty()) - break; - } - - assert(ConstructorNameSet.empty() && "Failed to find all of the visible " - "constructors by walking all the " - "lexical members of the context."); - assert(ConversionNameSet.empty() && "Failed to find all of the visible " - "conversion functions by walking all " - "the lexical members of the context."); - } - - // Next we need to do a lookup with each name into this decl context to fully - // populate any results from external sources. We don't actually use the - // results of these lookups because we only want to use the results after all - // results have been loaded and the pointers into them will be stable. - for (auto &Name : Names) - DC->lookup(Name); - - // Now we need to insert the results for each name into the hash table. For - // constructor names and conversion function names, we actually need to merge - // all of the results for them into one list of results each and insert - // those. - SmallVector<NamedDecl *, 8> ConstructorDecls; - SmallVector<NamedDecl *, 8> ConversionDecls; - - // Now loop over the names, either inserting them or appending for the two - // special cases. - for (auto &Name : Names) { - DeclContext::lookup_result Result = DC->noload_lookup(Name); - - switch (Name.getNameKind()) { - default: - Generator.insert(Name, Trait.getData(Result), Trait); - break; - - case DeclarationName::CXXConstructorName: - ConstructorDecls.append(Result.begin(), Result.end()); - break; - - case DeclarationName::CXXConversionFunctionName: - ConversionDecls.append(Result.begin(), Result.end()); - break; - } - } - - // Handle our two special cases if we ended up having any. We arbitrarily use - // the first declaration's name here because the name itself isn't part of - // the key, only the kind of name is used. - if (!ConstructorDecls.empty()) - Generator.insert(ConstructorDecls.front()->getDeclName(), - Trait.getData(ConstructorDecls), Trait); - if (!ConversionDecls.empty()) - Generator.insert(ConversionDecls.front()->getDeclName(), - Trait.getData(ConversionDecls), Trait); - - // Create the on-disk hash table. Also emit the existing imported and - // merged table if there is one. - auto *Lookups = Chain ? Chain->getLoadedLookupTables(DC) : nullptr; - Generator.emit(LookupTable, Trait, Lookups ? &Lookups->Table : nullptr); -} - -/// Write the block containing all of the declaration IDs -/// visible from the given DeclContext. -/// -/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the -/// bitstream, or 0 if no block was written. -uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, - DeclContext *DC) { - // If we imported a key declaration of this namespace, write the visible - // lookup results as an update record for it rather than including them - // on this declaration. We will only look at key declarations on reload. - if (isa<NamespaceDecl>(DC) && Chain && - Chain->getKeyDeclaration(cast<Decl>(DC))->isFromASTFile()) { - // Only do this once, for the first local declaration of the namespace. - for (auto *Prev = cast<NamespaceDecl>(DC)->getPreviousDecl(); Prev; - Prev = Prev->getPreviousDecl()) - if (!Prev->isFromASTFile()) - return 0; - - // Note that we need to emit an update record for the primary context. - UpdatedDeclContexts.insert(DC->getPrimaryContext()); - - // Make sure all visible decls are written. They will be recorded later. We - // do this using a side data structure so we can sort the names into - // a deterministic order. - StoredDeclsMap *Map = DC->getPrimaryContext()->buildLookup(); - SmallVector<std::pair<DeclarationName, DeclContext::lookup_result>, 16> - LookupResults; - if (Map) { - LookupResults.reserve(Map->size()); - for (auto &Entry : *Map) - LookupResults.push_back( - std::make_pair(Entry.first, Entry.second.getLookupResult())); - } - - llvm::sort(LookupResults, llvm::less_first()); - for (auto &NameAndResult : LookupResults) { - DeclarationName Name = NameAndResult.first; - DeclContext::lookup_result Result = NameAndResult.second; - if (Name.getNameKind() == DeclarationName::CXXConstructorName || - Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { - // We have to work around a name lookup bug here where negative lookup - // results for these names get cached in namespace lookup tables (these - // names should never be looked up in a namespace). - assert(Result.empty() && "Cannot have a constructor or conversion " - "function name in a namespace!"); - continue; - } - - for (NamedDecl *ND : Result) - if (!ND->isFromASTFile()) - GetDeclRef(ND); - } - - return 0; - } - - if (DC->getPrimaryContext() != DC) - return 0; - - // Skip contexts which don't support name lookup. - if (!DC->isLookupContext()) - return 0; - - // If not in C++, we perform name lookup for the translation unit via the - // IdentifierInfo chains, don't bother to build a visible-declarations table. - if (DC->isTranslationUnit() && !Context.getLangOpts().CPlusPlus) - return 0; - - // Serialize the contents of the mapping used for lookup. Note that, - // although we have two very different code paths, the serialized - // representation is the same for both cases: a declaration name, - // followed by a size, followed by references to the visible - // declarations that have that name. - uint64_t Offset = Stream.GetCurrentBitNo(); - StoredDeclsMap *Map = DC->buildLookup(); - if (!Map || Map->empty()) - return 0; - - // Create the on-disk hash table in a buffer. - SmallString<4096> LookupTable; - GenerateNameLookupTable(DC, LookupTable); - - // Write the lookup table - RecordData::value_type Record[] = {DECL_CONTEXT_VISIBLE}; - Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record, - LookupTable); - ++NumVisibleDeclContexts; - return Offset; -} - -/// Write an UPDATE_VISIBLE block for the given context. -/// -/// UPDATE_VISIBLE blocks contain the declarations that are added to an existing -/// DeclContext in a dependent AST file. As such, they only exist for the TU -/// (in C++), for namespaces, and for classes with forward-declared unscoped -/// enumeration members (in C++11). -void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) { - StoredDeclsMap *Map = DC->getLookupPtr(); - if (!Map || Map->empty()) - return; - - // Create the on-disk hash table in a buffer. - SmallString<4096> LookupTable; - GenerateNameLookupTable(DC, LookupTable); - - // If we're updating a namespace, select a key declaration as the key for the - // update record; those are the only ones that will be checked on reload. - if (isa<NamespaceDecl>(DC)) - DC = cast<DeclContext>(Chain->getKeyDeclaration(cast<Decl>(DC))); - - // Write the lookup table - RecordData::value_type Record[] = {UPDATE_VISIBLE, getDeclID(cast<Decl>(DC))}; - Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable); -} - -/// Write an FP_PRAGMA_OPTIONS block for the given FPOptions. -void ASTWriter::WriteFPPragmaOptions(const FPOptions &Opts) { - RecordData::value_type Record[] = {Opts.getInt()}; - Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record); -} - -/// Write an OPENCL_EXTENSIONS block for the given OpenCLOptions. -void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) { - if (!SemaRef.Context.getLangOpts().OpenCL) - return; - - const OpenCLOptions &Opts = SemaRef.getOpenCLOptions(); - RecordData Record; - for (const auto &I:Opts.OptMap) { - AddString(I.getKey(), Record); - auto V = I.getValue(); - Record.push_back(V.Supported ? 1 : 0); - Record.push_back(V.Enabled ? 1 : 0); - Record.push_back(V.Avail); - Record.push_back(V.Core); - } - Stream.EmitRecord(OPENCL_EXTENSIONS, Record); -} - -void ASTWriter::WriteOpenCLExtensionTypes(Sema &SemaRef) { - if (!SemaRef.Context.getLangOpts().OpenCL) - return; - - RecordData Record; - for (const auto &I : SemaRef.OpenCLTypeExtMap) { - Record.push_back( - static_cast<unsigned>(getTypeID(I.first->getCanonicalTypeInternal()))); - Record.push_back(I.second.size()); - for (auto Ext : I.second) - AddString(Ext, Record); - } - Stream.EmitRecord(OPENCL_EXTENSION_TYPES, Record); -} - -void ASTWriter::WriteOpenCLExtensionDecls(Sema &SemaRef) { - if (!SemaRef.Context.getLangOpts().OpenCL) - return; - - RecordData Record; - for (const auto &I : SemaRef.OpenCLDeclExtMap) { - Record.push_back(getDeclID(I.first)); - Record.push_back(static_cast<unsigned>(I.second.size())); - for (auto Ext : I.second) - AddString(Ext, Record); - } - Stream.EmitRecord(OPENCL_EXTENSION_DECLS, Record); -} - -void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) { - if (SemaRef.ForceCUDAHostDeviceDepth > 0) { - RecordData::value_type Record[] = {SemaRef.ForceCUDAHostDeviceDepth}; - Stream.EmitRecord(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH, Record); - } -} - -void ASTWriter::WriteObjCCategories() { - SmallVector<ObjCCategoriesInfo, 2> CategoriesMap; - RecordData Categories; - - for (unsigned I = 0, N = ObjCClassesWithCategories.size(); I != N; ++I) { - unsigned Size = 0; - unsigned StartIndex = Categories.size(); - - ObjCInterfaceDecl *Class = ObjCClassesWithCategories[I]; - - // Allocate space for the size. - Categories.push_back(0); - - // Add the categories. - for (ObjCInterfaceDecl::known_categories_iterator - Cat = Class->known_categories_begin(), - CatEnd = Class->known_categories_end(); - Cat != CatEnd; ++Cat, ++Size) { - assert(getDeclID(*Cat) != 0 && "Bogus category"); - AddDeclRef(*Cat, Categories); - } - - // Update the size. - Categories[StartIndex] = Size; - - // Record this interface -> category map. - ObjCCategoriesInfo CatInfo = { getDeclID(Class), StartIndex }; - CategoriesMap.push_back(CatInfo); - } - - // Sort the categories map by the definition ID, since the reader will be - // performing binary searches on this information. - llvm::array_pod_sort(CategoriesMap.begin(), CategoriesMap.end()); - - // Emit the categories map. - using namespace llvm; - - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(OBJC_CATEGORIES_MAP)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned AbbrevID = Stream.EmitAbbrev(std::move(Abbrev)); - - RecordData::value_type Record[] = {OBJC_CATEGORIES_MAP, CategoriesMap.size()}; - Stream.EmitRecordWithBlob(AbbrevID, Record, - reinterpret_cast<char *>(CategoriesMap.data()), - CategoriesMap.size() * sizeof(ObjCCategoriesInfo)); - - // Emit the category lists. - Stream.EmitRecord(OBJC_CATEGORIES, Categories); -} - -void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) { - Sema::LateParsedTemplateMapT &LPTMap = SemaRef.LateParsedTemplateMap; - - if (LPTMap.empty()) - return; - - RecordData Record; - for (auto &LPTMapEntry : LPTMap) { - const FunctionDecl *FD = LPTMapEntry.first; - LateParsedTemplate &LPT = *LPTMapEntry.second; - AddDeclRef(FD, Record); - AddDeclRef(LPT.D, Record); - Record.push_back(LPT.Toks.size()); - - for (const auto &Tok : LPT.Toks) { - AddToken(Tok, Record); - } - } - Stream.EmitRecord(LATE_PARSED_TEMPLATE, Record); -} - -/// Write the state of 'pragma clang optimize' at the end of the module. -void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) { - RecordData Record; - SourceLocation PragmaLoc = SemaRef.getOptimizeOffPragmaLocation(); - AddSourceLocation(PragmaLoc, Record); - Stream.EmitRecord(OPTIMIZE_PRAGMA_OPTIONS, Record); -} - -/// Write the state of 'pragma ms_struct' at the end of the module. -void ASTWriter::WriteMSStructPragmaOptions(Sema &SemaRef) { - RecordData Record; - Record.push_back(SemaRef.MSStructPragmaOn ? PMSST_ON : PMSST_OFF); - Stream.EmitRecord(MSSTRUCT_PRAGMA_OPTIONS, Record); -} - -/// Write the state of 'pragma pointers_to_members' at the end of the -//module. -void ASTWriter::WriteMSPointersToMembersPragmaOptions(Sema &SemaRef) { - RecordData Record; - Record.push_back(SemaRef.MSPointerToMemberRepresentationMethod); - AddSourceLocation(SemaRef.ImplicitMSInheritanceAttrLoc, Record); - Stream.EmitRecord(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS, Record); -} - -/// Write the state of 'pragma pack' at the end of the module. -void ASTWriter::WritePackPragmaOptions(Sema &SemaRef) { - // Don't serialize pragma pack state for modules, since it should only take - // effect on a per-submodule basis. - if (WritingModule) - return; - - RecordData Record; - Record.push_back(SemaRef.PackStack.CurrentValue); - AddSourceLocation(SemaRef.PackStack.CurrentPragmaLocation, Record); - Record.push_back(SemaRef.PackStack.Stack.size()); - for (const auto &StackEntry : SemaRef.PackStack.Stack) { - Record.push_back(StackEntry.Value); - AddSourceLocation(StackEntry.PragmaLocation, Record); - AddSourceLocation(StackEntry.PragmaPushLocation, Record); - AddString(StackEntry.StackSlotLabel, Record); - } - Stream.EmitRecord(PACK_PRAGMA_OPTIONS, Record); -} - -void ASTWriter::WriteModuleFileExtension(Sema &SemaRef, - ModuleFileExtensionWriter &Writer) { - // Enter the extension block. - Stream.EnterSubblock(EXTENSION_BLOCK_ID, 4); - - // Emit the metadata record abbreviation. - auto Abv = std::make_shared<llvm::BitCodeAbbrev>(); - Abv->Add(llvm::BitCodeAbbrevOp(EXTENSION_METADATA)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); - unsigned Abbrev = Stream.EmitAbbrev(std::move(Abv)); - - // Emit the metadata record. - RecordData Record; - auto Metadata = Writer.getExtension()->getExtensionMetadata(); - Record.push_back(EXTENSION_METADATA); - Record.push_back(Metadata.MajorVersion); - Record.push_back(Metadata.MinorVersion); - Record.push_back(Metadata.BlockName.size()); - Record.push_back(Metadata.UserInfo.size()); - SmallString<64> Buffer; - Buffer += Metadata.BlockName; - Buffer += Metadata.UserInfo; - Stream.EmitRecordWithBlob(Abbrev, Record, Buffer); - - // Emit the contents of the extension block. - Writer.writeExtensionContents(SemaRef, Stream); - - // Exit the extension block. - Stream.ExitBlock(); -} - -//===----------------------------------------------------------------------===// -// General Serialization Routines -//===----------------------------------------------------------------------===// - -void ASTRecordWriter::AddAttr(const Attr *A) { - auto &Record = *this; - if (!A) - return Record.push_back(0); - Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs - Record.AddSourceRange(A->getRange()); - -#include "clang/Serialization/AttrPCHWrite.inc" -} - -/// Emit the list of attributes to the specified record. -void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) { - push_back(Attrs.size()); - for (const auto *A : Attrs) - AddAttr(A); -} - -void ASTWriter::AddToken(const Token &Tok, RecordDataImpl &Record) { - AddSourceLocation(Tok.getLocation(), Record); - Record.push_back(Tok.getLength()); - - // FIXME: When reading literal tokens, reconstruct the literal pointer - // if it is needed. - AddIdentifierRef(Tok.getIdentifierInfo(), Record); - // FIXME: Should translate token kind to a stable encoding. - Record.push_back(Tok.getKind()); - // FIXME: Should translate token flags to a stable encoding. - Record.push_back(Tok.getFlags()); -} - -void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) { - Record.push_back(Str.size()); - Record.insert(Record.end(), Str.begin(), Str.end()); -} - -bool ASTWriter::PreparePathForOutput(SmallVectorImpl<char> &Path) { - assert(Context && "should have context when outputting path"); - - bool Changed = - cleanPathForOutput(Context->getSourceManager().getFileManager(), Path); - - // Remove a prefix to make the path relative, if relevant. - const char *PathBegin = Path.data(); - const char *PathPtr = - adjustFilenameForRelocatableAST(PathBegin, BaseDirectory); - if (PathPtr != PathBegin) { - Path.erase(Path.begin(), Path.begin() + (PathPtr - PathBegin)); - Changed = true; - } - - return Changed; -} - -void ASTWriter::AddPath(StringRef Path, RecordDataImpl &Record) { - SmallString<128> FilePath(Path); - PreparePathForOutput(FilePath); - AddString(FilePath, Record); -} - -void ASTWriter::EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record, - StringRef Path) { - SmallString<128> FilePath(Path); - PreparePathForOutput(FilePath); - Stream.EmitRecordWithBlob(Abbrev, Record, FilePath); -} - -void ASTWriter::AddVersionTuple(const VersionTuple &Version, - RecordDataImpl &Record) { - Record.push_back(Version.getMajor()); - if (Optional<unsigned> Minor = Version.getMinor()) - Record.push_back(*Minor + 1); - else - Record.push_back(0); - if (Optional<unsigned> Subminor = Version.getSubminor()) - Record.push_back(*Subminor + 1); - else - Record.push_back(0); -} - -/// Note that the identifier II occurs at the given offset -/// within the identifier table. -void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) { - IdentID ID = IdentifierIDs[II]; - // Only store offsets new to this AST file. Other identifier names are looked - // up earlier in the chain and thus don't need an offset. - if (ID >= FirstIdentID) - IdentifierOffsets[ID - FirstIdentID] = Offset; -} - -/// Note that the selector Sel occurs at the given offset -/// within the method pool/selector table. -void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { - unsigned ID = SelectorIDs[Sel]; - assert(ID && "Unknown selector"); - // Don't record offsets for selectors that are also available in a different - // file. - if (ID < FirstSelectorID) - return; - SelectorOffsets[ID - FirstSelectorID] = Offset; -} - -ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream, - SmallVectorImpl<char> &Buffer, MemoryBufferCache &PCMCache, - ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, - bool IncludeTimestamps) - : Stream(Stream), Buffer(Buffer), PCMCache(PCMCache), - IncludeTimestamps(IncludeTimestamps) { - for (const auto &Ext : Extensions) { - if (auto Writer = Ext->createExtensionWriter(*this)) - ModuleFileExtensionWriters.push_back(std::move(Writer)); - } -} - -ASTWriter::~ASTWriter() { - llvm::DeleteContainerSeconds(FileDeclIDs); -} - -const LangOptions &ASTWriter::getLangOpts() const { - assert(WritingAST && "can't determine lang opts when not writing AST"); - return Context->getLangOpts(); -} - -time_t ASTWriter::getTimestampForOutput(const FileEntry *E) const { - return IncludeTimestamps ? E->getModificationTime() : 0; -} - -ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, - const std::string &OutputFile, - Module *WritingModule, StringRef isysroot, - bool hasErrors) { - WritingAST = true; - - ASTHasCompilerErrors = hasErrors; - - // Emit the file header. - Stream.Emit((unsigned)'C', 8); - Stream.Emit((unsigned)'P', 8); - Stream.Emit((unsigned)'C', 8); - Stream.Emit((unsigned)'H', 8); - - WriteBlockInfoBlock(); - - Context = &SemaRef.Context; - PP = &SemaRef.PP; - this->WritingModule = WritingModule; - ASTFileSignature Signature = - WriteASTCore(SemaRef, isysroot, OutputFile, WritingModule); - Context = nullptr; - PP = nullptr; - this->WritingModule = nullptr; - this->BaseDirectory.clear(); - - WritingAST = false; - if (SemaRef.Context.getLangOpts().ImplicitModules && WritingModule) { - // Construct MemoryBuffer and update buffer manager. - PCMCache.addBuffer(OutputFile, - llvm::MemoryBuffer::getMemBufferCopy( - StringRef(Buffer.begin(), Buffer.size()))); - } - return Signature; -} - -template<typename Vector> -static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec, - ASTWriter::RecordData &Record) { - for (typename Vector::iterator I = Vec.begin(nullptr, true), E = Vec.end(); - I != E; ++I) { - Writer.AddDeclRef(*I, Record); - } -} - -ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, - const std::string &OutputFile, - Module *WritingModule) { - using namespace llvm; - - bool isModule = WritingModule != nullptr; - - // Make sure that the AST reader knows to finalize itself. - if (Chain) - Chain->finalizeForWriting(); - - ASTContext &Context = SemaRef.Context; - Preprocessor &PP = SemaRef.PP; - - // Set up predefined declaration IDs. - auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) { - if (D) { - assert(D->isCanonicalDecl() && "predefined decl is not canonical"); - DeclIDs[D] = ID; - } - }; - RegisterPredefDecl(Context.getTranslationUnitDecl(), - PREDEF_DECL_TRANSLATION_UNIT_ID); - RegisterPredefDecl(Context.ObjCIdDecl, PREDEF_DECL_OBJC_ID_ID); - RegisterPredefDecl(Context.ObjCSelDecl, PREDEF_DECL_OBJC_SEL_ID); - RegisterPredefDecl(Context.ObjCClassDecl, PREDEF_DECL_OBJC_CLASS_ID); - RegisterPredefDecl(Context.ObjCProtocolClassDecl, - PREDEF_DECL_OBJC_PROTOCOL_ID); - RegisterPredefDecl(Context.Int128Decl, PREDEF_DECL_INT_128_ID); - RegisterPredefDecl(Context.UInt128Decl, PREDEF_DECL_UNSIGNED_INT_128_ID); - RegisterPredefDecl(Context.ObjCInstanceTypeDecl, - PREDEF_DECL_OBJC_INSTANCETYPE_ID); - RegisterPredefDecl(Context.BuiltinVaListDecl, PREDEF_DECL_BUILTIN_VA_LIST_ID); - RegisterPredefDecl(Context.VaListTagDecl, PREDEF_DECL_VA_LIST_TAG); - RegisterPredefDecl(Context.BuiltinMSVaListDecl, - PREDEF_DECL_BUILTIN_MS_VA_LIST_ID); - RegisterPredefDecl(Context.ExternCContext, PREDEF_DECL_EXTERN_C_CONTEXT_ID); - RegisterPredefDecl(Context.MakeIntegerSeqDecl, - PREDEF_DECL_MAKE_INTEGER_SEQ_ID); - RegisterPredefDecl(Context.CFConstantStringTypeDecl, - PREDEF_DECL_CF_CONSTANT_STRING_ID); - RegisterPredefDecl(Context.CFConstantStringTagDecl, - PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID); - RegisterPredefDecl(Context.TypePackElementDecl, - PREDEF_DECL_TYPE_PACK_ELEMENT_ID); - - // Build a record containing all of the tentative definitions in this file, in - // TentativeDefinitions order. Generally, this record will be empty for - // headers. - RecordData TentativeDefinitions; - AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions, TentativeDefinitions); - - // Build a record containing all of the file scoped decls in this file. - RecordData UnusedFileScopedDecls; - if (!isModule) - AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls, - UnusedFileScopedDecls); - - // Build a record containing all of the delegating constructors we still need - // to resolve. - RecordData DelegatingCtorDecls; - if (!isModule) - AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls, DelegatingCtorDecls); - - // Write the set of weak, undeclared identifiers. We always write the - // entire table, since later PCH files in a PCH chain are only interested in - // the results at the end of the chain. - RecordData WeakUndeclaredIdentifiers; - for (auto &WeakUndeclaredIdentifier : SemaRef.WeakUndeclaredIdentifiers) { - IdentifierInfo *II = WeakUndeclaredIdentifier.first; - WeakInfo &WI = WeakUndeclaredIdentifier.second; - AddIdentifierRef(II, WeakUndeclaredIdentifiers); - AddIdentifierRef(WI.getAlias(), WeakUndeclaredIdentifiers); - AddSourceLocation(WI.getLocation(), WeakUndeclaredIdentifiers); - WeakUndeclaredIdentifiers.push_back(WI.getUsed()); - } - - // Build a record containing all of the ext_vector declarations. - RecordData ExtVectorDecls; - AddLazyVectorDecls(*this, SemaRef.ExtVectorDecls, ExtVectorDecls); - - // Build a record containing all of the VTable uses information. - RecordData VTableUses; - if (!SemaRef.VTableUses.empty()) { - for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) { - AddDeclRef(SemaRef.VTableUses[I].first, VTableUses); - AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses); - VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]); - } - } - - // Build a record containing all of the UnusedLocalTypedefNameCandidates. - RecordData UnusedLocalTypedefNameCandidates; - for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates) - AddDeclRef(TD, UnusedLocalTypedefNameCandidates); - - // Build a record containing all of pending implicit instantiations. - RecordData PendingInstantiations; - for (const auto &I : SemaRef.PendingInstantiations) { - AddDeclRef(I.first, PendingInstantiations); - AddSourceLocation(I.second, PendingInstantiations); - } - assert(SemaRef.PendingLocalImplicitInstantiations.empty() && - "There are local ones at end of translation unit!"); - - // Build a record containing some declaration references. - RecordData SemaDeclRefs; - if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) { - AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs); - AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs); - AddDeclRef(SemaRef.getStdAlignValT(), SemaDeclRefs); - } - - RecordData CUDASpecialDeclRefs; - if (Context.getcudaConfigureCallDecl()) { - AddDeclRef(Context.getcudaConfigureCallDecl(), CUDASpecialDeclRefs); - } - - // Build a record containing all of the known namespaces. - RecordData KnownNamespaces; - for (const auto &I : SemaRef.KnownNamespaces) { - if (!I.second) - AddDeclRef(I.first, KnownNamespaces); - } - - // Build a record of all used, undefined objects that require definitions. - RecordData UndefinedButUsed; - - SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined; - SemaRef.getUndefinedButUsed(Undefined); - for (const auto &I : Undefined) { - AddDeclRef(I.first, UndefinedButUsed); - AddSourceLocation(I.second, UndefinedButUsed); - } - - // Build a record containing all delete-expressions that we would like to - // analyze later in AST. - RecordData DeleteExprsToAnalyze; - - if (!isModule) { - for (const auto &DeleteExprsInfo : - SemaRef.getMismatchingDeleteExpressions()) { - AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze); - DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size()); - for (const auto &DeleteLoc : DeleteExprsInfo.second) { - AddSourceLocation(DeleteLoc.first, DeleteExprsToAnalyze); - DeleteExprsToAnalyze.push_back(DeleteLoc.second); - } - } - } - - // Write the control block - WriteControlBlock(PP, Context, isysroot, OutputFile); - - // Write the remaining AST contents. - Stream.EnterSubblock(AST_BLOCK_ID, 5); - - // This is so that older clang versions, before the introduction - // of the control block, can read and reject the newer PCH format. - { - RecordData Record = {VERSION_MAJOR}; - Stream.EmitRecord(METADATA_OLD_FORMAT, Record); - } - - // Create a lexical update block containing all of the declarations in the - // translation unit that do not come from other AST files. - const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); - SmallVector<uint32_t, 128> NewGlobalKindDeclPairs; - for (const auto *D : TU->noload_decls()) { - if (!D->isFromASTFile()) { - NewGlobalKindDeclPairs.push_back(D->getKind()); - NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); - } - } - - auto Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); - unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv)); - { - RecordData::value_type Record[] = {TU_UPDATE_LEXICAL}; - Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, - bytes(NewGlobalKindDeclPairs)); - } - - // And a visible updates block for the translation unit. - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); - UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv)); - WriteDeclContextVisibleUpdate(TU); - - // If we have any extern "C" names, write out a visible update for them. - if (Context.ExternCContext) - WriteDeclContextVisibleUpdate(Context.ExternCContext); - - // If the translation unit has an anonymous namespace, and we don't already - // have an update block for it, write it as an update block. - // FIXME: Why do we not do this if there's already an update block? - if (NamespaceDecl *NS = TU->getAnonymousNamespace()) { - ASTWriter::UpdateRecord &Record = DeclUpdates[TU]; - if (Record.empty()) - Record.push_back(DeclUpdate(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, NS)); - } - - // Add update records for all mangling numbers and static local numbers. - // These aren't really update records, but this is a convenient way of - // tagging this rare extra data onto the declarations. - for (const auto &Number : Context.MangleNumbers) - if (!Number.first->isFromASTFile()) - DeclUpdates[Number.first].push_back(DeclUpdate(UPD_MANGLING_NUMBER, - Number.second)); - for (const auto &Number : Context.StaticLocalNumbers) - if (!Number.first->isFromASTFile()) - DeclUpdates[Number.first].push_back(DeclUpdate(UPD_STATIC_LOCAL_NUMBER, - Number.second)); - - // Make sure visible decls, added to DeclContexts previously loaded from - // an AST file, are registered for serialization. Likewise for template - // specializations added to imported templates. - for (const auto *I : DeclsToEmitEvenIfUnreferenced) { - GetDeclRef(I); - } - - // Make sure all decls associated with an identifier are registered for - // serialization, if we're storing decls with identifiers. - if (!WritingModule || !getLangOpts().CPlusPlus) { - llvm::SmallVector<const IdentifierInfo*, 256> IIs; - for (const auto &ID : PP.getIdentifierTable()) { - const IdentifierInfo *II = ID.second; - if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization()) - IIs.push_back(II); - } - // Sort the identifiers to visit based on their name. - llvm::sort(IIs, llvm::less_ptr<IdentifierInfo>()); - for (const IdentifierInfo *II : IIs) { - for (IdentifierResolver::iterator D = SemaRef.IdResolver.begin(II), - DEnd = SemaRef.IdResolver.end(); - D != DEnd; ++D) { - GetDeclRef(*D); - } - } - } - - // For method pool in the module, if it contains an entry for a selector, - // the entry should be complete, containing everything introduced by that - // module and all modules it imports. It's possible that the entry is out of - // date, so we need to pull in the new content here. - - // It's possible that updateOutOfDateSelector can update SelectorIDs. To be - // safe, we copy all selectors out. - llvm::SmallVector<Selector, 256> AllSelectors; - for (auto &SelectorAndID : SelectorIDs) - AllSelectors.push_back(SelectorAndID.first); - for (auto &Selector : AllSelectors) - SemaRef.updateOutOfDateSelector(Selector); - - // Form the record of special types. - RecordData SpecialTypes; - AddTypeRef(Context.getRawCFConstantStringType(), SpecialTypes); - AddTypeRef(Context.getFILEType(), SpecialTypes); - AddTypeRef(Context.getjmp_bufType(), SpecialTypes); - AddTypeRef(Context.getsigjmp_bufType(), SpecialTypes); - AddTypeRef(Context.ObjCIdRedefinitionType, SpecialTypes); - AddTypeRef(Context.ObjCClassRedefinitionType, SpecialTypes); - AddTypeRef(Context.ObjCSelRedefinitionType, SpecialTypes); - AddTypeRef(Context.getucontext_tType(), SpecialTypes); - - if (Chain) { - // Write the mapping information describing our module dependencies and how - // each of those modules were mapped into our own offset/ID space, so that - // the reader can build the appropriate mapping to its own offset/ID space. - // The map consists solely of a blob with the following format: - // *(module-kind:i8 - // module-name-len:i16 module-name:len*i8 - // source-location-offset:i32 - // identifier-id:i32 - // preprocessed-entity-id:i32 - // macro-definition-id:i32 - // submodule-id:i32 - // selector-id:i32 - // declaration-id:i32 - // c++-base-specifiers-id:i32 - // type-id:i32) - // - // module-kind is the ModuleKind enum value. If it is MK_PrebuiltModule or - // MK_ExplicitModule, then the module-name is the module name. Otherwise, - // it is the module file name. - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(MODULE_OFFSET_MAP)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned ModuleOffsetMapAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - SmallString<2048> Buffer; - { - llvm::raw_svector_ostream Out(Buffer); - for (ModuleFile &M : Chain->ModuleMgr) { - using namespace llvm::support; - - endian::Writer LE(Out, little); - LE.write<uint8_t>(static_cast<uint8_t>(M.Kind)); - StringRef Name = - M.Kind == MK_PrebuiltModule || M.Kind == MK_ExplicitModule - ? M.ModuleName - : M.FileName; - LE.write<uint16_t>(Name.size()); - Out.write(Name.data(), Name.size()); - - // Note: if a base ID was uint max, it would not be possible to load - // another module after it or have more than one entity inside it. - uint32_t None = std::numeric_limits<uint32_t>::max(); - - auto writeBaseIDOrNone = [&](uint32_t BaseID, bool ShouldWrite) { - assert(BaseID < std::numeric_limits<uint32_t>::max() && "base id too high"); - if (ShouldWrite) - LE.write<uint32_t>(BaseID); - else - LE.write<uint32_t>(None); - }; - - // These values should be unique within a chain, since they will be read - // as keys into ContinuousRangeMaps. - writeBaseIDOrNone(M.SLocEntryBaseOffset, M.LocalNumSLocEntries); - writeBaseIDOrNone(M.BaseIdentifierID, M.LocalNumIdentifiers); - writeBaseIDOrNone(M.BaseMacroID, M.LocalNumMacros); - writeBaseIDOrNone(M.BasePreprocessedEntityID, - M.NumPreprocessedEntities); - writeBaseIDOrNone(M.BaseSubmoduleID, M.LocalNumSubmodules); - writeBaseIDOrNone(M.BaseSelectorID, M.LocalNumSelectors); - writeBaseIDOrNone(M.BaseDeclID, M.LocalNumDecls); - writeBaseIDOrNone(M.BaseTypeIndex, M.LocalNumTypes); - } - } - RecordData::value_type Record[] = {MODULE_OFFSET_MAP}; - Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record, - Buffer.data(), Buffer.size()); - } - - RecordData DeclUpdatesOffsetsRecord; - - // Keep writing types, declarations, and declaration update records - // until we've emitted all of them. - Stream.EnterSubblock(DECLTYPES_BLOCK_ID, /*bits for abbreviations*/5); - WriteTypeAbbrevs(); - WriteDeclAbbrevs(); - do { - WriteDeclUpdatesBlocks(DeclUpdatesOffsetsRecord); - while (!DeclTypesToEmit.empty()) { - DeclOrType DOT = DeclTypesToEmit.front(); - DeclTypesToEmit.pop(); - if (DOT.isType()) - WriteType(DOT.getType()); - else - WriteDecl(Context, DOT.getDecl()); - } - } while (!DeclUpdates.empty()); - Stream.ExitBlock(); - - DoneWritingDeclsAndTypes = true; - - // These things can only be done once we've written out decls and types. - WriteTypeDeclOffsets(); - if (!DeclUpdatesOffsetsRecord.empty()) - Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord); - WriteFileDeclIDsMap(); - WriteSourceManagerBlock(Context.getSourceManager(), PP); - WriteComments(); - WritePreprocessor(PP, isModule); - WriteHeaderSearch(PP.getHeaderSearchInfo()); - WriteSelectors(SemaRef); - WriteReferencedSelectorsPool(SemaRef); - WriteLateParsedTemplates(SemaRef); - WriteIdentifierTable(PP, SemaRef.IdResolver, isModule); - WriteFPPragmaOptions(SemaRef.getFPOptions()); - WriteOpenCLExtensions(SemaRef); - WriteOpenCLExtensionTypes(SemaRef); - WriteCUDAPragmas(SemaRef); - - // If we're emitting a module, write out the submodule information. - if (WritingModule) - WriteSubmodules(WritingModule); - - // We need to have information about submodules to correctly deserialize - // decls from OpenCLExtensionDecls block - WriteOpenCLExtensionDecls(SemaRef); - - Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes); - - // Write the record containing external, unnamed definitions. - if (!EagerlyDeserializedDecls.empty()) - Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls); - - if (!ModularCodegenDecls.empty()) - Stream.EmitRecord(MODULAR_CODEGEN_DECLS, ModularCodegenDecls); - - // Write the record containing tentative definitions. - if (!TentativeDefinitions.empty()) - Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions); - - // Write the record containing unused file scoped decls. - if (!UnusedFileScopedDecls.empty()) - Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls); - - // Write the record containing weak undeclared identifiers. - if (!WeakUndeclaredIdentifiers.empty()) - Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS, - WeakUndeclaredIdentifiers); - - // Write the record containing ext_vector type names. - if (!ExtVectorDecls.empty()) - Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls); - - // Write the record containing VTable uses information. - if (!VTableUses.empty()) - Stream.EmitRecord(VTABLE_USES, VTableUses); - - // Write the record containing potentially unused local typedefs. - if (!UnusedLocalTypedefNameCandidates.empty()) - Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES, - UnusedLocalTypedefNameCandidates); - - // Write the record containing pending implicit instantiations. - if (!PendingInstantiations.empty()) - Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations); - - // Write the record containing declaration references of Sema. - if (!SemaDeclRefs.empty()) - Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs); - - // Write the record containing CUDA-specific declaration references. - if (!CUDASpecialDeclRefs.empty()) - Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs); - - // Write the delegating constructors. - if (!DelegatingCtorDecls.empty()) - Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls); - - // Write the known namespaces. - if (!KnownNamespaces.empty()) - Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces); - - // Write the undefined internal functions and variables, and inline functions. - if (!UndefinedButUsed.empty()) - Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed); - - if (!DeleteExprsToAnalyze.empty()) - Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze); - - // Write the visible updates to DeclContexts. - for (auto *DC : UpdatedDeclContexts) - WriteDeclContextVisibleUpdate(DC); - - if (!WritingModule) { - // Write the submodules that were imported, if any. - struct ModuleInfo { - uint64_t ID; - Module *M; - ModuleInfo(uint64_t ID, Module *M) : ID(ID), M(M) {} - }; - llvm::SmallVector<ModuleInfo, 64> Imports; - for (const auto *I : Context.local_imports()) { - assert(SubmoduleIDs.find(I->getImportedModule()) != SubmoduleIDs.end()); - Imports.push_back(ModuleInfo(SubmoduleIDs[I->getImportedModule()], - I->getImportedModule())); - } - - if (!Imports.empty()) { - auto Cmp = [](const ModuleInfo &A, const ModuleInfo &B) { - return A.ID < B.ID; - }; - auto Eq = [](const ModuleInfo &A, const ModuleInfo &B) { - return A.ID == B.ID; - }; - - // Sort and deduplicate module IDs. - llvm::sort(Imports, Cmp); - Imports.erase(std::unique(Imports.begin(), Imports.end(), Eq), - Imports.end()); - - RecordData ImportedModules; - for (const auto &Import : Imports) { - ImportedModules.push_back(Import.ID); - // FIXME: If the module has macros imported then later has declarations - // imported, this location won't be the right one as a location for the - // declaration imports. - AddSourceLocation(PP.getModuleImportLoc(Import.M), ImportedModules); - } - - Stream.EmitRecord(IMPORTED_MODULES, ImportedModules); - } - } - - WriteObjCCategories(); - if(!WritingModule) { - WriteOptimizePragmaOptions(SemaRef); - WriteMSStructPragmaOptions(SemaRef); - WriteMSPointersToMembersPragmaOptions(SemaRef); - } - WritePackPragmaOptions(SemaRef); - - // Some simple statistics - RecordData::value_type Record[] = { - NumStatements, NumMacros, NumLexicalDeclContexts, NumVisibleDeclContexts}; - Stream.EmitRecord(STATISTICS, Record); - Stream.ExitBlock(); - - // Write the module file extension blocks. - for (const auto &ExtWriter : ModuleFileExtensionWriters) - WriteModuleFileExtension(SemaRef, *ExtWriter); - - return writeUnhashedControlBlock(PP, Context); -} - -void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { - if (DeclUpdates.empty()) - return; - - DeclUpdateMap LocalUpdates; - LocalUpdates.swap(DeclUpdates); - - for (auto &DeclUpdate : LocalUpdates) { - const Decl *D = DeclUpdate.first; - - bool HasUpdatedBody = false; - RecordData RecordData; - ASTRecordWriter Record(*this, RecordData); - for (auto &Update : DeclUpdate.second) { - DeclUpdateKind Kind = (DeclUpdateKind)Update.getKind(); - - // An updated body is emitted last, so that the reader doesn't need - // to skip over the lazy body to reach statements for other records. - if (Kind == UPD_CXX_ADDED_FUNCTION_DEFINITION) - HasUpdatedBody = true; - else - Record.push_back(Kind); - - switch (Kind) { - case UPD_CXX_ADDED_IMPLICIT_MEMBER: - case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: - case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: - assert(Update.getDecl() && "no decl to add?"); - Record.push_back(GetDeclRef(Update.getDecl())); - break; - - case UPD_CXX_ADDED_FUNCTION_DEFINITION: - break; - - case UPD_CXX_POINT_OF_INSTANTIATION: - // FIXME: Do we need to also save the template specialization kind here? - Record.AddSourceLocation(Update.getLoc()); - break; - - case UPD_CXX_ADDED_VAR_DEFINITION: { - const VarDecl *VD = cast<VarDecl>(D); - Record.push_back(VD->isInline()); - Record.push_back(VD->isInlineSpecified()); - if (VD->getInit()) { - Record.push_back(!VD->isInitKnownICE() ? 1 - : (VD->isInitICE() ? 3 : 2)); - Record.AddStmt(const_cast<Expr*>(VD->getInit())); - } else { - Record.push_back(0); - } - break; - } - - case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: - Record.AddStmt(const_cast<Expr *>( - cast<ParmVarDecl>(Update.getDecl())->getDefaultArg())); - break; - - case UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER: - Record.AddStmt( - cast<FieldDecl>(Update.getDecl())->getInClassInitializer()); - break; - - case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: { - auto *RD = cast<CXXRecordDecl>(D); - UpdatedDeclContexts.insert(RD->getPrimaryContext()); - Record.push_back(RD->isParamDestroyedInCallee()); - Record.push_back(RD->getArgPassingRestrictions()); - Record.AddCXXDefinitionData(RD); - Record.AddOffset(WriteDeclContextLexicalBlock( - *Context, const_cast<CXXRecordDecl *>(RD))); - - // This state is sometimes updated by template instantiation, when we - // switch from the specialization referring to the template declaration - // to it referring to the template definition. - if (auto *MSInfo = RD->getMemberSpecializationInfo()) { - Record.push_back(MSInfo->getTemplateSpecializationKind()); - Record.AddSourceLocation(MSInfo->getPointOfInstantiation()); - } else { - auto *Spec = cast<ClassTemplateSpecializationDecl>(RD); - Record.push_back(Spec->getTemplateSpecializationKind()); - Record.AddSourceLocation(Spec->getPointOfInstantiation()); - - // The instantiation might have been resolved to a partial - // specialization. If so, record which one. - auto From = Spec->getInstantiatedFrom(); - if (auto PartialSpec = - From.dyn_cast<ClassTemplatePartialSpecializationDecl*>()) { - Record.push_back(true); - Record.AddDeclRef(PartialSpec); - Record.AddTemplateArgumentList( - &Spec->getTemplateInstantiationArgs()); - } else { - Record.push_back(false); - } - } - Record.push_back(RD->getTagKind()); - Record.AddSourceLocation(RD->getLocation()); - Record.AddSourceLocation(RD->getBeginLoc()); - Record.AddSourceRange(RD->getBraceRange()); - - // Instantiation may change attributes; write them all out afresh. - Record.push_back(D->hasAttrs()); - if (D->hasAttrs()) - Record.AddAttributes(D->getAttrs()); - - // FIXME: Ensure we don't get here for explicit instantiations. - break; - } - - case UPD_CXX_RESOLVED_DTOR_DELETE: - Record.AddDeclRef(Update.getDecl()); - Record.AddStmt(cast<CXXDestructorDecl>(D)->getOperatorDeleteThisArg()); - break; - - case UPD_CXX_RESOLVED_EXCEPTION_SPEC: - addExceptionSpec( - cast<FunctionDecl>(D)->getType()->castAs<FunctionProtoType>(), - Record); - break; - - case UPD_CXX_DEDUCED_RETURN_TYPE: - Record.push_back(GetOrCreateTypeID(Update.getType())); - break; - - case UPD_DECL_MARKED_USED: - break; - - case UPD_MANGLING_NUMBER: - case UPD_STATIC_LOCAL_NUMBER: - Record.push_back(Update.getNumber()); - break; - - case UPD_DECL_MARKED_OPENMP_THREADPRIVATE: - Record.AddSourceRange( - D->getAttr<OMPThreadPrivateDeclAttr>()->getRange()); - break; - - case UPD_DECL_MARKED_OPENMP_DECLARETARGET: - Record.push_back(D->getAttr<OMPDeclareTargetDeclAttr>()->getMapType()); - Record.AddSourceRange( - D->getAttr<OMPDeclareTargetDeclAttr>()->getRange()); - break; - - case UPD_DECL_EXPORTED: - Record.push_back(getSubmoduleID(Update.getModule())); - break; - - case UPD_ADDED_ATTR_TO_RECORD: - Record.AddAttributes(llvm::makeArrayRef(Update.getAttr())); - break; - } - } - - if (HasUpdatedBody) { - const auto *Def = cast<FunctionDecl>(D); - Record.push_back(UPD_CXX_ADDED_FUNCTION_DEFINITION); - Record.push_back(Def->isInlined()); - Record.AddSourceLocation(Def->getInnerLocStart()); - Record.AddFunctionDefinition(Def); - } - - OffsetsRecord.push_back(GetDeclRef(D)); - OffsetsRecord.push_back(Record.Emit(DECL_UPDATES)); - } -} - -void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record) { - uint32_t Raw = Loc.getRawEncoding(); - Record.push_back((Raw << 1) | (Raw >> 31)); -} - -void ASTWriter::AddSourceRange(SourceRange Range, RecordDataImpl &Record) { - AddSourceLocation(Range.getBegin(), Record); - AddSourceLocation(Range.getEnd(), Record); -} - -void ASTRecordWriter::AddAPInt(const llvm::APInt &Value) { - Record->push_back(Value.getBitWidth()); - const uint64_t *Words = Value.getRawData(); - Record->append(Words, Words + Value.getNumWords()); -} - -void ASTRecordWriter::AddAPSInt(const llvm::APSInt &Value) { - Record->push_back(Value.isUnsigned()); - AddAPInt(Value); -} - -void ASTRecordWriter::AddAPFloat(const llvm::APFloat &Value) { - AddAPInt(Value.bitcastToAPInt()); -} - -void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record) { - Record.push_back(getIdentifierRef(II)); -} - -IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { - if (!II) - return 0; - - IdentID &ID = IdentifierIDs[II]; - if (ID == 0) - ID = NextIdentID++; - return ID; -} - -MacroID ASTWriter::getMacroRef(MacroInfo *MI, const IdentifierInfo *Name) { - // Don't emit builtin macros like __LINE__ to the AST file unless they - // have been redefined by the header (in which case they are not - // isBuiltinMacro). - if (!MI || MI->isBuiltinMacro()) - return 0; - - MacroID &ID = MacroIDs[MI]; - if (ID == 0) { - ID = NextMacroID++; - MacroInfoToEmitData Info = { Name, MI, ID }; - MacroInfosToEmit.push_back(Info); - } - return ID; -} - -MacroID ASTWriter::getMacroID(MacroInfo *MI) { - if (!MI || MI->isBuiltinMacro()) - return 0; - - assert(MacroIDs.find(MI) != MacroIDs.end() && "Macro not emitted!"); - return MacroIDs[MI]; -} - -uint64_t ASTWriter::getMacroDirectivesOffset(const IdentifierInfo *Name) { - return IdentMacroDirectivesOffsetMap.lookup(Name); -} - -void ASTRecordWriter::AddSelectorRef(const Selector SelRef) { - Record->push_back(Writer->getSelectorRef(SelRef)); -} - -SelectorID ASTWriter::getSelectorRef(Selector Sel) { - if (Sel.getAsOpaquePtr() == nullptr) { - return 0; - } - - SelectorID SID = SelectorIDs[Sel]; - if (SID == 0 && Chain) { - // This might trigger a ReadSelector callback, which will set the ID for - // this selector. - Chain->LoadSelector(Sel); - SID = SelectorIDs[Sel]; - } - if (SID == 0) { - SID = NextSelectorID++; - SelectorIDs[Sel] = SID; - } - return SID; -} - -void ASTRecordWriter::AddCXXTemporary(const CXXTemporary *Temp) { - AddDeclRef(Temp->getDestructor()); -} - -void ASTRecordWriter::AddTemplateArgumentLocInfo( - TemplateArgument::ArgKind Kind, const TemplateArgumentLocInfo &Arg) { - switch (Kind) { - case TemplateArgument::Expression: - AddStmt(Arg.getAsExpr()); - break; - case TemplateArgument::Type: - AddTypeSourceInfo(Arg.getAsTypeSourceInfo()); - break; - case TemplateArgument::Template: - AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc()); - AddSourceLocation(Arg.getTemplateNameLoc()); - break; - case TemplateArgument::TemplateExpansion: - AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc()); - AddSourceLocation(Arg.getTemplateNameLoc()); - AddSourceLocation(Arg.getTemplateEllipsisLoc()); - break; - case TemplateArgument::Null: - case TemplateArgument::Integral: - case TemplateArgument::Declaration: - case TemplateArgument::NullPtr: - case TemplateArgument::Pack: - // FIXME: Is this right? - break; - } -} - -void ASTRecordWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg) { - AddTemplateArgument(Arg.getArgument()); - - if (Arg.getArgument().getKind() == TemplateArgument::Expression) { - bool InfoHasSameExpr - = Arg.getArgument().getAsExpr() == Arg.getLocInfo().getAsExpr(); - Record->push_back(InfoHasSameExpr); - if (InfoHasSameExpr) - return; // Avoid storing the same expr twice. - } - AddTemplateArgumentLocInfo(Arg.getArgument().getKind(), Arg.getLocInfo()); -} - -void ASTRecordWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo) { - if (!TInfo) { - AddTypeRef(QualType()); - return; - } - - AddTypeRef(TInfo->getType()); - AddTypeLoc(TInfo->getTypeLoc()); -} - -void ASTRecordWriter::AddTypeLoc(TypeLoc TL) { - TypeLocWriter TLW(*this); - for (; !TL.isNull(); TL = TL.getNextTypeLoc()) - TLW.Visit(TL); -} - -void ASTWriter::AddTypeRef(QualType T, RecordDataImpl &Record) { - Record.push_back(GetOrCreateTypeID(T)); -} - -TypeID ASTWriter::GetOrCreateTypeID(QualType T) { - assert(Context); - return MakeTypeID(*Context, T, [&](QualType T) -> TypeIdx { - if (T.isNull()) - return TypeIdx(); - assert(!T.getLocalFastQualifiers()); - - TypeIdx &Idx = TypeIdxs[T]; - if (Idx.getIndex() == 0) { - if (DoneWritingDeclsAndTypes) { - assert(0 && "New type seen after serializing all the types to emit!"); - return TypeIdx(); - } - - // We haven't seen this type before. Assign it a new ID and put it - // into the queue of types to emit. - Idx = TypeIdx(NextTypeID++); - DeclTypesToEmit.push(T); - } - return Idx; - }); -} - -TypeID ASTWriter::getTypeID(QualType T) const { - assert(Context); - return MakeTypeID(*Context, T, [&](QualType T) -> TypeIdx { - if (T.isNull()) - return TypeIdx(); - assert(!T.getLocalFastQualifiers()); - - TypeIdxMap::const_iterator I = TypeIdxs.find(T); - assert(I != TypeIdxs.end() && "Type not emitted!"); - return I->second; - }); -} - -void ASTWriter::AddDeclRef(const Decl *D, RecordDataImpl &Record) { - Record.push_back(GetDeclRef(D)); -} - -DeclID ASTWriter::GetDeclRef(const Decl *D) { - assert(WritingAST && "Cannot request a declaration ID before AST writing"); - - if (!D) { - return 0; - } - - // If D comes from an AST file, its declaration ID is already known and - // fixed. - if (D->isFromASTFile()) - return D->getGlobalID(); - - assert(!(reinterpret_cast<uintptr_t>(D) & 0x01) && "Invalid decl pointer"); - DeclID &ID = DeclIDs[D]; - if (ID == 0) { - if (DoneWritingDeclsAndTypes) { - assert(0 && "New decl seen after serializing all the decls to emit!"); - return 0; - } - - // We haven't seen this declaration before. Give it a new ID and - // enqueue it in the list of declarations to emit. - ID = NextDeclID++; - DeclTypesToEmit.push(const_cast<Decl *>(D)); - } - - return ID; -} - -DeclID ASTWriter::getDeclID(const Decl *D) { - if (!D) - return 0; - - // If D comes from an AST file, its declaration ID is already known and - // fixed. - if (D->isFromASTFile()) - return D->getGlobalID(); - - assert(DeclIDs.find(D) != DeclIDs.end() && "Declaration not emitted!"); - return DeclIDs[D]; -} - -void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) { - assert(ID); - assert(D); - - SourceLocation Loc = D->getLocation(); - if (Loc.isInvalid()) - return; - - // We only keep track of the file-level declarations of each file. - if (!D->getLexicalDeclContext()->isFileContext()) - return; - // FIXME: ParmVarDecls that are part of a function type of a parameter of - // a function/objc method, should not have TU as lexical context. - // TemplateTemplateParmDecls that are part of an alias template, should not - // have TU as lexical context. - if (isa<ParmVarDecl>(D) || isa<TemplateTemplateParmDecl>(D)) - return; - - SourceManager &SM = Context->getSourceManager(); - SourceLocation FileLoc = SM.getFileLoc(Loc); - assert(SM.isLocalSourceLocation(FileLoc)); - FileID FID; - unsigned Offset; - std::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc); - if (FID.isInvalid()) - return; - assert(SM.getSLocEntry(FID).isFile()); - - DeclIDInFileInfo *&Info = FileDeclIDs[FID]; - if (!Info) - Info = new DeclIDInFileInfo(); - - std::pair<unsigned, serialization::DeclID> LocDecl(Offset, ID); - LocDeclIDsTy &Decls = Info->DeclIDs; - - if (Decls.empty() || Decls.back().first <= Offset) { - Decls.push_back(LocDecl); - return; - } - - LocDeclIDsTy::iterator I = - std::upper_bound(Decls.begin(), Decls.end(), LocDecl, llvm::less_first()); - - Decls.insert(I, LocDecl); -} - -void ASTRecordWriter::AddDeclarationName(DeclarationName Name) { - // FIXME: Emit a stable enum for NameKind. 0 = Identifier etc. - Record->push_back(Name.getNameKind()); - switch (Name.getNameKind()) { - case DeclarationName::Identifier: - AddIdentifierRef(Name.getAsIdentifierInfo()); - break; - - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - AddSelectorRef(Name.getObjCSelector()); - break; - - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - AddTypeRef(Name.getCXXNameType()); - break; - - case DeclarationName::CXXDeductionGuideName: - AddDeclRef(Name.getCXXDeductionGuideTemplate()); - break; - - case DeclarationName::CXXOperatorName: - Record->push_back(Name.getCXXOverloadedOperator()); - break; - - case DeclarationName::CXXLiteralOperatorName: - AddIdentifierRef(Name.getCXXLiteralIdentifier()); - break; - - case DeclarationName::CXXUsingDirective: - // No extra data to emit - break; - } -} - -unsigned ASTWriter::getAnonymousDeclarationNumber(const NamedDecl *D) { - assert(needsAnonymousDeclarationNumber(D) && - "expected an anonymous declaration"); - - // Number the anonymous declarations within this context, if we've not - // already done so. - auto It = AnonymousDeclarationNumbers.find(D); - if (It == AnonymousDeclarationNumbers.end()) { - auto *DC = D->getLexicalDeclContext(); - numberAnonymousDeclsWithin(DC, [&](const NamedDecl *ND, unsigned Number) { - AnonymousDeclarationNumbers[ND] = Number; - }); - - It = AnonymousDeclarationNumbers.find(D); - assert(It != AnonymousDeclarationNumbers.end() && - "declaration not found within its lexical context"); - } - - return It->second; -} - -void ASTRecordWriter::AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc, - DeclarationName Name) { - switch (Name.getNameKind()) { - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - AddTypeSourceInfo(DNLoc.NamedType.TInfo); - break; - - case DeclarationName::CXXOperatorName: - AddSourceLocation(SourceLocation::getFromRawEncoding( - DNLoc.CXXOperatorName.BeginOpNameLoc)); - AddSourceLocation( - SourceLocation::getFromRawEncoding(DNLoc.CXXOperatorName.EndOpNameLoc)); - break; - - case DeclarationName::CXXLiteralOperatorName: - AddSourceLocation(SourceLocation::getFromRawEncoding( - DNLoc.CXXLiteralOperatorName.OpNameLoc)); - break; - - case DeclarationName::Identifier: - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - case DeclarationName::CXXUsingDirective: - case DeclarationName::CXXDeductionGuideName: - break; - } -} - -void ASTRecordWriter::AddDeclarationNameInfo( - const DeclarationNameInfo &NameInfo) { - AddDeclarationName(NameInfo.getName()); - AddSourceLocation(NameInfo.getLoc()); - AddDeclarationNameLoc(NameInfo.getInfo(), NameInfo.getName()); -} - -void ASTRecordWriter::AddQualifierInfo(const QualifierInfo &Info) { - AddNestedNameSpecifierLoc(Info.QualifierLoc); - Record->push_back(Info.NumTemplParamLists); - for (unsigned i = 0, e = Info.NumTemplParamLists; i != e; ++i) - AddTemplateParameterList(Info.TemplParamLists[i]); -} - -void ASTRecordWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS) { - // Nested name specifiers usually aren't too long. I think that 8 would - // typically accommodate the vast majority. - SmallVector<NestedNameSpecifier *, 8> NestedNames; - - // Push each of the NNS's onto a stack for serialization in reverse order. - while (NNS) { - NestedNames.push_back(NNS); - NNS = NNS->getPrefix(); - } - - Record->push_back(NestedNames.size()); - while(!NestedNames.empty()) { - NNS = NestedNames.pop_back_val(); - NestedNameSpecifier::SpecifierKind Kind = NNS->getKind(); - Record->push_back(Kind); - switch (Kind) { - case NestedNameSpecifier::Identifier: - AddIdentifierRef(NNS->getAsIdentifier()); - break; - - case NestedNameSpecifier::Namespace: - AddDeclRef(NNS->getAsNamespace()); - break; - - case NestedNameSpecifier::NamespaceAlias: - AddDeclRef(NNS->getAsNamespaceAlias()); - break; - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - AddTypeRef(QualType(NNS->getAsType(), 0)); - Record->push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate); - break; - - case NestedNameSpecifier::Global: - // Don't need to write an associated value. - break; - - case NestedNameSpecifier::Super: - AddDeclRef(NNS->getAsRecordDecl()); - break; - } - } -} - -void ASTRecordWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { - // Nested name specifiers usually aren't too long. I think that 8 would - // typically accommodate the vast majority. - SmallVector<NestedNameSpecifierLoc , 8> NestedNames; - - // Push each of the nested-name-specifiers's onto a stack for - // serialization in reverse order. - while (NNS) { - NestedNames.push_back(NNS); - NNS = NNS.getPrefix(); - } - - Record->push_back(NestedNames.size()); - while(!NestedNames.empty()) { - NNS = NestedNames.pop_back_val(); - NestedNameSpecifier::SpecifierKind Kind - = NNS.getNestedNameSpecifier()->getKind(); - Record->push_back(Kind); - switch (Kind) { - case NestedNameSpecifier::Identifier: - AddIdentifierRef(NNS.getNestedNameSpecifier()->getAsIdentifier()); - AddSourceRange(NNS.getLocalSourceRange()); - break; - - case NestedNameSpecifier::Namespace: - AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespace()); - AddSourceRange(NNS.getLocalSourceRange()); - break; - - case NestedNameSpecifier::NamespaceAlias: - AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespaceAlias()); - AddSourceRange(NNS.getLocalSourceRange()); - break; - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - Record->push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate); - AddTypeRef(NNS.getTypeLoc().getType()); - AddTypeLoc(NNS.getTypeLoc()); - AddSourceLocation(NNS.getLocalSourceRange().getEnd()); - break; - - case NestedNameSpecifier::Global: - AddSourceLocation(NNS.getLocalSourceRange().getEnd()); - break; - - case NestedNameSpecifier::Super: - AddDeclRef(NNS.getNestedNameSpecifier()->getAsRecordDecl()); - AddSourceRange(NNS.getLocalSourceRange()); - break; - } - } -} - -void ASTRecordWriter::AddTemplateName(TemplateName Name) { - TemplateName::NameKind Kind = Name.getKind(); - Record->push_back(Kind); - switch (Kind) { - case TemplateName::Template: - AddDeclRef(Name.getAsTemplateDecl()); - break; - - case TemplateName::OverloadedTemplate: { - OverloadedTemplateStorage *OvT = Name.getAsOverloadedTemplate(); - Record->push_back(OvT->size()); - for (const auto &I : *OvT) - AddDeclRef(I); - break; - } - - case TemplateName::QualifiedTemplate: { - QualifiedTemplateName *QualT = Name.getAsQualifiedTemplateName(); - AddNestedNameSpecifier(QualT->getQualifier()); - Record->push_back(QualT->hasTemplateKeyword()); - AddDeclRef(QualT->getTemplateDecl()); - break; - } - - case TemplateName::DependentTemplate: { - DependentTemplateName *DepT = Name.getAsDependentTemplateName(); - AddNestedNameSpecifier(DepT->getQualifier()); - Record->push_back(DepT->isIdentifier()); - if (DepT->isIdentifier()) - AddIdentifierRef(DepT->getIdentifier()); - else - Record->push_back(DepT->getOperator()); - break; - } - - case TemplateName::SubstTemplateTemplateParm: { - SubstTemplateTemplateParmStorage *subst - = Name.getAsSubstTemplateTemplateParm(); - AddDeclRef(subst->getParameter()); - AddTemplateName(subst->getReplacement()); - break; - } - - case TemplateName::SubstTemplateTemplateParmPack: { - SubstTemplateTemplateParmPackStorage *SubstPack - = Name.getAsSubstTemplateTemplateParmPack(); - AddDeclRef(SubstPack->getParameterPack()); - AddTemplateArgument(SubstPack->getArgumentPack()); - break; - } - } -} - -void ASTRecordWriter::AddTemplateArgument(const TemplateArgument &Arg) { - Record->push_back(Arg.getKind()); - switch (Arg.getKind()) { - case TemplateArgument::Null: - break; - case TemplateArgument::Type: - AddTypeRef(Arg.getAsType()); - break; - case TemplateArgument::Declaration: - AddDeclRef(Arg.getAsDecl()); - AddTypeRef(Arg.getParamTypeForDecl()); - break; - case TemplateArgument::NullPtr: - AddTypeRef(Arg.getNullPtrType()); - break; - case TemplateArgument::Integral: - AddAPSInt(Arg.getAsIntegral()); - AddTypeRef(Arg.getIntegralType()); - break; - case TemplateArgument::Template: - AddTemplateName(Arg.getAsTemplateOrTemplatePattern()); - break; - case TemplateArgument::TemplateExpansion: - AddTemplateName(Arg.getAsTemplateOrTemplatePattern()); - if (Optional<unsigned> NumExpansions = Arg.getNumTemplateExpansions()) - Record->push_back(*NumExpansions + 1); - else - Record->push_back(0); - break; - case TemplateArgument::Expression: - AddStmt(Arg.getAsExpr()); - break; - case TemplateArgument::Pack: - Record->push_back(Arg.pack_size()); - for (const auto &P : Arg.pack_elements()) - AddTemplateArgument(P); - break; - } -} - -void ASTRecordWriter::AddTemplateParameterList( - const TemplateParameterList *TemplateParams) { - assert(TemplateParams && "No TemplateParams!"); - AddSourceLocation(TemplateParams->getTemplateLoc()); - AddSourceLocation(TemplateParams->getLAngleLoc()); - AddSourceLocation(TemplateParams->getRAngleLoc()); - // TODO: Concepts - Record->push_back(TemplateParams->size()); - for (const auto &P : *TemplateParams) - AddDeclRef(P); -} - -/// Emit a template argument list. -void ASTRecordWriter::AddTemplateArgumentList( - const TemplateArgumentList *TemplateArgs) { - assert(TemplateArgs && "No TemplateArgs!"); - Record->push_back(TemplateArgs->size()); - for (int i = 0, e = TemplateArgs->size(); i != e; ++i) - AddTemplateArgument(TemplateArgs->get(i)); -} - -void ASTRecordWriter::AddASTTemplateArgumentListInfo( - const ASTTemplateArgumentListInfo *ASTTemplArgList) { - assert(ASTTemplArgList && "No ASTTemplArgList!"); - AddSourceLocation(ASTTemplArgList->LAngleLoc); - AddSourceLocation(ASTTemplArgList->RAngleLoc); - Record->push_back(ASTTemplArgList->NumTemplateArgs); - const TemplateArgumentLoc *TemplArgs = ASTTemplArgList->getTemplateArgs(); - for (int i = 0, e = ASTTemplArgList->NumTemplateArgs; i != e; ++i) - AddTemplateArgumentLoc(TemplArgs[i]); -} - -void ASTRecordWriter::AddUnresolvedSet(const ASTUnresolvedSet &Set) { - Record->push_back(Set.size()); - for (ASTUnresolvedSet::const_iterator - I = Set.begin(), E = Set.end(); I != E; ++I) { - AddDeclRef(I.getDecl()); - Record->push_back(I.getAccess()); - } -} - -// FIXME: Move this out of the main ASTRecordWriter interface. -void ASTRecordWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base) { - Record->push_back(Base.isVirtual()); - Record->push_back(Base.isBaseOfClass()); - Record->push_back(Base.getAccessSpecifierAsWritten()); - Record->push_back(Base.getInheritConstructors()); - AddTypeSourceInfo(Base.getTypeSourceInfo()); - AddSourceRange(Base.getSourceRange()); - AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc() - : SourceLocation()); -} - -static uint64_t EmitCXXBaseSpecifiers(ASTWriter &W, - ArrayRef<CXXBaseSpecifier> Bases) { - ASTWriter::RecordData Record; - ASTRecordWriter Writer(W, Record); - Writer.push_back(Bases.size()); - - for (auto &Base : Bases) - Writer.AddCXXBaseSpecifier(Base); - - return Writer.Emit(serialization::DECL_CXX_BASE_SPECIFIERS); -} - -// FIXME: Move this out of the main ASTRecordWriter interface. -void ASTRecordWriter::AddCXXBaseSpecifiers(ArrayRef<CXXBaseSpecifier> Bases) { - AddOffset(EmitCXXBaseSpecifiers(*Writer, Bases)); -} - -static uint64_t -EmitCXXCtorInitializers(ASTWriter &W, - ArrayRef<CXXCtorInitializer *> CtorInits) { - ASTWriter::RecordData Record; - ASTRecordWriter Writer(W, Record); - Writer.push_back(CtorInits.size()); - - for (auto *Init : CtorInits) { - if (Init->isBaseInitializer()) { - Writer.push_back(CTOR_INITIALIZER_BASE); - Writer.AddTypeSourceInfo(Init->getTypeSourceInfo()); - Writer.push_back(Init->isBaseVirtual()); - } else if (Init->isDelegatingInitializer()) { - Writer.push_back(CTOR_INITIALIZER_DELEGATING); - Writer.AddTypeSourceInfo(Init->getTypeSourceInfo()); - } else if (Init->isMemberInitializer()){ - Writer.push_back(CTOR_INITIALIZER_MEMBER); - Writer.AddDeclRef(Init->getMember()); - } else { - Writer.push_back(CTOR_INITIALIZER_INDIRECT_MEMBER); - Writer.AddDeclRef(Init->getIndirectMember()); - } - - Writer.AddSourceLocation(Init->getMemberLocation()); - Writer.AddStmt(Init->getInit()); - Writer.AddSourceLocation(Init->getLParenLoc()); - Writer.AddSourceLocation(Init->getRParenLoc()); - Writer.push_back(Init->isWritten()); - if (Init->isWritten()) - Writer.push_back(Init->getSourceOrder()); - } - - return Writer.Emit(serialization::DECL_CXX_CTOR_INITIALIZERS); -} - -// FIXME: Move this out of the main ASTRecordWriter interface. -void ASTRecordWriter::AddCXXCtorInitializers( - ArrayRef<CXXCtorInitializer *> CtorInits) { - AddOffset(EmitCXXCtorInitializers(*Writer, CtorInits)); -} - -void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { - auto &Data = D->data(); - Record->push_back(Data.IsLambda); - Record->push_back(Data.UserDeclaredConstructor); - Record->push_back(Data.UserDeclaredSpecialMembers); - Record->push_back(Data.Aggregate); - Record->push_back(Data.PlainOldData); - Record->push_back(Data.Empty); - Record->push_back(Data.Polymorphic); - Record->push_back(Data.Abstract); - Record->push_back(Data.IsStandardLayout); - Record->push_back(Data.IsCXX11StandardLayout); - Record->push_back(Data.HasBasesWithFields); - Record->push_back(Data.HasBasesWithNonStaticDataMembers); - Record->push_back(Data.HasPrivateFields); - Record->push_back(Data.HasProtectedFields); - Record->push_back(Data.HasPublicFields); - Record->push_back(Data.HasMutableFields); - Record->push_back(Data.HasVariantMembers); - Record->push_back(Data.HasOnlyCMembers); - Record->push_back(Data.HasInClassInitializer); - Record->push_back(Data.HasUninitializedReferenceMember); - Record->push_back(Data.HasUninitializedFields); - Record->push_back(Data.HasInheritedConstructor); - Record->push_back(Data.HasInheritedAssignment); - Record->push_back(Data.NeedOverloadResolutionForCopyConstructor); - Record->push_back(Data.NeedOverloadResolutionForMoveConstructor); - Record->push_back(Data.NeedOverloadResolutionForMoveAssignment); - Record->push_back(Data.NeedOverloadResolutionForDestructor); - Record->push_back(Data.DefaultedCopyConstructorIsDeleted); - Record->push_back(Data.DefaultedMoveConstructorIsDeleted); - Record->push_back(Data.DefaultedMoveAssignmentIsDeleted); - Record->push_back(Data.DefaultedDestructorIsDeleted); - Record->push_back(Data.HasTrivialSpecialMembers); - Record->push_back(Data.HasTrivialSpecialMembersForCall); - Record->push_back(Data.DeclaredNonTrivialSpecialMembers); - Record->push_back(Data.DeclaredNonTrivialSpecialMembersForCall); - Record->push_back(Data.HasIrrelevantDestructor); - Record->push_back(Data.HasConstexprNonCopyMoveConstructor); - Record->push_back(Data.HasDefaultedDefaultConstructor); - Record->push_back(Data.DefaultedDefaultConstructorIsConstexpr); - Record->push_back(Data.HasConstexprDefaultConstructor); - Record->push_back(Data.HasNonLiteralTypeFieldsOrBases); - Record->push_back(Data.ComputedVisibleConversions); - Record->push_back(Data.UserProvidedDefaultConstructor); - Record->push_back(Data.DeclaredSpecialMembers); - Record->push_back(Data.ImplicitCopyConstructorCanHaveConstParamForVBase); - Record->push_back(Data.ImplicitCopyConstructorCanHaveConstParamForNonVBase); - Record->push_back(Data.ImplicitCopyAssignmentHasConstParam); - Record->push_back(Data.HasDeclaredCopyConstructorWithConstParam); - Record->push_back(Data.HasDeclaredCopyAssignmentWithConstParam); - - // getODRHash will compute the ODRHash if it has not been previously computed. - Record->push_back(D->getODRHash()); - bool ModulesDebugInfo = Writer->Context->getLangOpts().ModulesDebugInfo && - Writer->WritingModule && !D->isDependentType(); - Record->push_back(ModulesDebugInfo); - if (ModulesDebugInfo) - Writer->ModularCodegenDecls.push_back(Writer->GetDeclRef(D)); - - // IsLambda bit is already saved. - - Record->push_back(Data.NumBases); - if (Data.NumBases > 0) - AddCXXBaseSpecifiers(Data.bases()); - - // FIXME: Make VBases lazily computed when needed to avoid storing them. - Record->push_back(Data.NumVBases); - if (Data.NumVBases > 0) - AddCXXBaseSpecifiers(Data.vbases()); - - AddUnresolvedSet(Data.Conversions.get(*Writer->Context)); - AddUnresolvedSet(Data.VisibleConversions.get(*Writer->Context)); - // Data.Definition is the owning decl, no need to write it. - AddDeclRef(D->getFirstFriend()); - - // Add lambda-specific data. - if (Data.IsLambda) { - auto &Lambda = D->getLambdaData(); - Record->push_back(Lambda.Dependent); - Record->push_back(Lambda.IsGenericLambda); - Record->push_back(Lambda.CaptureDefault); - Record->push_back(Lambda.NumCaptures); - Record->push_back(Lambda.NumExplicitCaptures); - Record->push_back(Lambda.ManglingNumber); - AddDeclRef(D->getLambdaContextDecl()); - AddTypeSourceInfo(Lambda.MethodTyInfo); - for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { - const LambdaCapture &Capture = Lambda.Captures[I]; - AddSourceLocation(Capture.getLocation()); - Record->push_back(Capture.isImplicit()); - Record->push_back(Capture.getCaptureKind()); - switch (Capture.getCaptureKind()) { - case LCK_StarThis: - case LCK_This: - case LCK_VLAType: - break; - case LCK_ByCopy: - case LCK_ByRef: - VarDecl *Var = - Capture.capturesVariable() ? Capture.getCapturedVar() : nullptr; - AddDeclRef(Var); - AddSourceLocation(Capture.isPackExpansion() ? Capture.getEllipsisLoc() - : SourceLocation()); - break; - } - } - } -} - -void ASTWriter::ReaderInitialized(ASTReader *Reader) { - assert(Reader && "Cannot remove chain"); - assert((!Chain || Chain == Reader) && "Cannot replace chain"); - assert(FirstDeclID == NextDeclID && - FirstTypeID == NextTypeID && - FirstIdentID == NextIdentID && - FirstMacroID == NextMacroID && - FirstSubmoduleID == NextSubmoduleID && - FirstSelectorID == NextSelectorID && - "Setting chain after writing has started."); - - Chain = Reader; - - // Note, this will get called multiple times, once one the reader starts up - // and again each time it's done reading a PCH or module. - FirstDeclID = NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls(); - FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes(); - FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers(); - FirstMacroID = NUM_PREDEF_MACRO_IDS + Chain->getTotalNumMacros(); - FirstSubmoduleID = NUM_PREDEF_SUBMODULE_IDS + Chain->getTotalNumSubmodules(); - FirstSelectorID = NUM_PREDEF_SELECTOR_IDS + Chain->getTotalNumSelectors(); - NextDeclID = FirstDeclID; - NextTypeID = FirstTypeID; - NextIdentID = FirstIdentID; - NextMacroID = FirstMacroID; - NextSelectorID = FirstSelectorID; - NextSubmoduleID = FirstSubmoduleID; -} - -void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) { - // Always keep the highest ID. See \p TypeRead() for more information. - IdentID &StoredID = IdentifierIDs[II]; - if (ID > StoredID) - StoredID = ID; -} - -void ASTWriter::MacroRead(serialization::MacroID ID, MacroInfo *MI) { - // Always keep the highest ID. See \p TypeRead() for more information. - MacroID &StoredID = MacroIDs[MI]; - if (ID > StoredID) - StoredID = ID; -} - -void ASTWriter::TypeRead(TypeIdx Idx, QualType T) { - // Always take the highest-numbered type index. This copes with an interesting - // case for chained AST writing where we schedule writing the type and then, - // later, deserialize the type from another AST. In this case, we want to - // keep the higher-numbered entry so that we can properly write it out to - // the AST file. - TypeIdx &StoredIdx = TypeIdxs[T]; - if (Idx.getIndex() >= StoredIdx.getIndex()) - StoredIdx = Idx; -} - -void ASTWriter::SelectorRead(SelectorID ID, Selector S) { - // Always keep the highest ID. See \p TypeRead() for more information. - SelectorID &StoredID = SelectorIDs[S]; - if (ID > StoredID) - StoredID = ID; -} - -void ASTWriter::MacroDefinitionRead(serialization::PreprocessedEntityID ID, - MacroDefinitionRecord *MD) { - assert(MacroDefinitions.find(MD) == MacroDefinitions.end()); - MacroDefinitions[MD] = ID; -} - -void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) { - assert(SubmoduleIDs.find(Mod) == SubmoduleIDs.end()); - SubmoduleIDs[Mod] = ID; -} - -void ASTWriter::CompletedTagDefinition(const TagDecl *D) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(D->isCompleteDefinition()); - assert(!WritingAST && "Already writing the AST!"); - if (auto *RD = dyn_cast<CXXRecordDecl>(D)) { - // We are interested when a PCH decl is modified. - if (RD->isFromASTFile()) { - // A forward reference was mutated into a definition. Rewrite it. - // FIXME: This happens during template instantiation, should we - // have created a new definition decl instead ? - assert(isTemplateInstantiation(RD->getTemplateSpecializationKind()) && - "completed a tag from another module but not by instantiation?"); - DeclUpdates[RD].push_back( - DeclUpdate(UPD_CXX_INSTANTIATED_CLASS_DEFINITION)); - } - } -} - -static bool isImportedDeclContext(ASTReader *Chain, const Decl *D) { - if (D->isFromASTFile()) - return true; - - // The predefined __va_list_tag struct is imported if we imported any decls. - // FIXME: This is a gross hack. - return D == D->getASTContext().getVaListTagDecl(); -} - -void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(DC->isLookupContext() && - "Should not add lookup results to non-lookup contexts!"); - - // TU is handled elsewhere. - if (isa<TranslationUnitDecl>(DC)) - return; - - // Namespaces are handled elsewhere, except for template instantiations of - // FunctionTemplateDecls in namespaces. We are interested in cases where the - // local instantiations are added to an imported context. Only happens when - // adding ADL lookup candidates, for example templated friends. - if (isa<NamespaceDecl>(DC) && D->getFriendObjectKind() == Decl::FOK_None && - !isa<FunctionTemplateDecl>(D)) - return; - - // We're only interested in cases where a local declaration is added to an - // imported context. - if (D->isFromASTFile() || !isImportedDeclContext(Chain, cast<Decl>(DC))) - return; - - assert(DC == DC->getPrimaryContext() && "added to non-primary context"); - assert(!getDefinitiveDeclContext(DC) && "DeclContext not definitive!"); - assert(!WritingAST && "Already writing the AST!"); - if (UpdatedDeclContexts.insert(DC) && !cast<Decl>(DC)->isFromASTFile()) { - // We're adding a visible declaration to a predefined decl context. Ensure - // that we write out all of its lookup results so we don't get a nasty - // surprise when we try to emit its lookup table. - for (auto *Child : DC->decls()) - DeclsToEmitEvenIfUnreferenced.push_back(Child); - } - DeclsToEmitEvenIfUnreferenced.push_back(D); -} - -void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(D->isImplicit()); - - // We're only interested in cases where a local declaration is added to an - // imported context. - if (D->isFromASTFile() || !isImportedDeclContext(Chain, RD)) - return; - - if (!isa<CXXMethodDecl>(D)) - return; - - // A decl coming from PCH was modified. - assert(RD->isCompleteDefinition()); - assert(!WritingAST && "Already writing the AST!"); - DeclUpdates[RD].push_back(DeclUpdate(UPD_CXX_ADDED_IMPLICIT_MEMBER, D)); -} - -void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(!DoneWritingDeclsAndTypes && "Already done writing updates!"); - if (!Chain) return; - Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) { - // If we don't already know the exception specification for this redecl - // chain, add an update record for it. - if (isUnresolvedExceptionSpec(cast<FunctionDecl>(D) - ->getType() - ->castAs<FunctionProtoType>() - ->getExceptionSpecType())) - DeclUpdates[D].push_back(UPD_CXX_RESOLVED_EXCEPTION_SPEC); - }); -} - -void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(!WritingAST && "Already writing the AST!"); - if (!Chain) return; - Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) { - DeclUpdates[D].push_back( - DeclUpdate(UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType)); - }); -} - -void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD, - const FunctionDecl *Delete, - Expr *ThisArg) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(!WritingAST && "Already writing the AST!"); - assert(Delete && "Not given an operator delete"); - if (!Chain) return; - Chain->forEachImportedKeyDecl(DD, [&](const Decl *D) { - DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_RESOLVED_DTOR_DELETE, Delete)); - }); -} - -void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(!WritingAST && "Already writing the AST!"); - if (!D->isFromASTFile()) - return; // Declaration not imported from PCH. - - // Implicit function decl from a PCH was defined. - DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION)); -} - -void ASTWriter::VariableDefinitionInstantiated(const VarDecl *D) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(!WritingAST && "Already writing the AST!"); - if (!D->isFromASTFile()) - return; - - DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_VAR_DEFINITION)); -} - -void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(!WritingAST && "Already writing the AST!"); - if (!D->isFromASTFile()) - return; - - DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION)); -} - -void ASTWriter::InstantiationRequested(const ValueDecl *D) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(!WritingAST && "Already writing the AST!"); - if (!D->isFromASTFile()) - return; - - // Since the actual instantiation is delayed, this really means that we need - // to update the instantiation location. - SourceLocation POI; - if (auto *VD = dyn_cast<VarDecl>(D)) - POI = VD->getPointOfInstantiation(); - else - POI = cast<FunctionDecl>(D)->getPointOfInstantiation(); - DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_POINT_OF_INSTANTIATION, POI)); -} - -void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(!WritingAST && "Already writing the AST!"); - if (!D->isFromASTFile()) - return; - - DeclUpdates[D].push_back( - DeclUpdate(UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT, D)); -} - -void ASTWriter::DefaultMemberInitializerInstantiated(const FieldDecl *D) { - assert(!WritingAST && "Already writing the AST!"); - if (!D->isFromASTFile()) - return; - - DeclUpdates[D].push_back( - DeclUpdate(UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER, D)); -} - -void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, - const ObjCInterfaceDecl *IFD) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(!WritingAST && "Already writing the AST!"); - if (!IFD->isFromASTFile()) - return; // Declaration not imported from PCH. - - assert(IFD->getDefinition() && "Category on a class without a definition?"); - ObjCClassesWithCategories.insert( - const_cast<ObjCInterfaceDecl *>(IFD->getDefinition())); -} - -void ASTWriter::DeclarationMarkedUsed(const Decl *D) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(!WritingAST && "Already writing the AST!"); - - // If there is *any* declaration of the entity that's not from an AST file, - // we can skip writing the update record. We make sure that isUsed() triggers - // completion of the redeclaration chain of the entity. - for (auto Prev = D->getMostRecentDecl(); Prev; Prev = Prev->getPreviousDecl()) - if (IsLocalDecl(Prev)) - return; - - DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_USED)); -} - -void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(!WritingAST && "Already writing the AST!"); - if (!D->isFromASTFile()) - return; - - DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_THREADPRIVATE)); -} - -void ASTWriter::DeclarationMarkedOpenMPDeclareTarget(const Decl *D, - const Attr *Attr) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(!WritingAST && "Already writing the AST!"); - if (!D->isFromASTFile()) - return; - - DeclUpdates[D].push_back( - DeclUpdate(UPD_DECL_MARKED_OPENMP_DECLARETARGET, Attr)); -} - -void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(!WritingAST && "Already writing the AST!"); - assert(D->isHidden() && "expected a hidden declaration"); - DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_EXPORTED, M)); -} - -void ASTWriter::AddedAttributeToRecord(const Attr *Attr, - const RecordDecl *Record) { - if (Chain && Chain->isProcessingUpdateRecords()) return; - assert(!WritingAST && "Already writing the AST!"); - if (!Record->isFromASTFile()) - return; - DeclUpdates[Record].push_back(DeclUpdate(UPD_ADDED_ATTR_TO_RECORD, Attr)); -} - -void ASTWriter::AddedCXXTemplateSpecialization( - const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) { - assert(!WritingAST && "Already writing the AST!"); - - if (!TD->getFirstDecl()->isFromASTFile()) - return; - if (Chain && Chain->isProcessingUpdateRecords()) - return; - - DeclsToEmitEvenIfUnreferenced.push_back(D); -} - -void ASTWriter::AddedCXXTemplateSpecialization( - const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) { - assert(!WritingAST && "Already writing the AST!"); - - if (!TD->getFirstDecl()->isFromASTFile()) - return; - if (Chain && Chain->isProcessingUpdateRecords()) - return; - - DeclsToEmitEvenIfUnreferenced.push_back(D); -} - -void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, - const FunctionDecl *D) { - assert(!WritingAST && "Already writing the AST!"); - - if (!TD->getFirstDecl()->isFromASTFile()) - return; - if (Chain && Chain->isProcessingUpdateRecords()) - return; - - DeclsToEmitEvenIfUnreferenced.push_back(D); -} - -//===----------------------------------------------------------------------===// -//// OMPClause Serialization -////===----------------------------------------------------------------------===// - -void OMPClauseWriter::writeClause(OMPClause *C) { - Record.push_back(C->getClauseKind()); - Visit(C); - Record.AddSourceLocation(C->getBeginLoc()); - Record.AddSourceLocation(C->getEndLoc()); -} - -void OMPClauseWriter::VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C) { - Record.push_back(C->getCaptureRegion()); - Record.AddStmt(C->getPreInitStmt()); -} - -void OMPClauseWriter::VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C) { - VisitOMPClauseWithPreInit(C); - Record.AddStmt(C->getPostUpdateExpr()); -} - -void OMPClauseWriter::VisitOMPIfClause(OMPIfClause *C) { - VisitOMPClauseWithPreInit(C); - Record.push_back(C->getNameModifier()); - Record.AddSourceLocation(C->getNameModifierLoc()); - Record.AddSourceLocation(C->getColonLoc()); - Record.AddStmt(C->getCondition()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPFinalClause(OMPFinalClause *C) { - Record.AddStmt(C->getCondition()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { - VisitOMPClauseWithPreInit(C); - Record.AddStmt(C->getNumThreads()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPSafelenClause(OMPSafelenClause *C) { - Record.AddStmt(C->getSafelen()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPSimdlenClause(OMPSimdlenClause *C) { - Record.AddStmt(C->getSimdlen()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPCollapseClause(OMPCollapseClause *C) { - Record.AddStmt(C->getNumForLoops()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) { - Record.push_back(C->getDefaultKind()); - Record.AddSourceLocation(C->getLParenLoc()); - Record.AddSourceLocation(C->getDefaultKindKwLoc()); -} - -void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) { - Record.push_back(C->getProcBindKind()); - Record.AddSourceLocation(C->getLParenLoc()); - Record.AddSourceLocation(C->getProcBindKindKwLoc()); -} - -void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) { - VisitOMPClauseWithPreInit(C); - Record.push_back(C->getScheduleKind()); - Record.push_back(C->getFirstScheduleModifier()); - Record.push_back(C->getSecondScheduleModifier()); - Record.AddStmt(C->getChunkSize()); - Record.AddSourceLocation(C->getLParenLoc()); - Record.AddSourceLocation(C->getFirstScheduleModifierLoc()); - Record.AddSourceLocation(C->getSecondScheduleModifierLoc()); - Record.AddSourceLocation(C->getScheduleKindLoc()); - Record.AddSourceLocation(C->getCommaLoc()); -} - -void OMPClauseWriter::VisitOMPOrderedClause(OMPOrderedClause *C) { - Record.push_back(C->getLoopNumIterations().size()); - Record.AddStmt(C->getNumForLoops()); - for (Expr *NumIter : C->getLoopNumIterations()) - Record.AddStmt(NumIter); - for (unsigned I = 0, E = C->getLoopNumIterations().size(); I <E; ++I) - Record.AddStmt(C->getLoopCounter(I)); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPNowaitClause(OMPNowaitClause *) {} - -void OMPClauseWriter::VisitOMPUntiedClause(OMPUntiedClause *) {} - -void OMPClauseWriter::VisitOMPMergeableClause(OMPMergeableClause *) {} - -void OMPClauseWriter::VisitOMPReadClause(OMPReadClause *) {} - -void OMPClauseWriter::VisitOMPWriteClause(OMPWriteClause *) {} - -void OMPClauseWriter::VisitOMPUpdateClause(OMPUpdateClause *) {} - -void OMPClauseWriter::VisitOMPCaptureClause(OMPCaptureClause *) {} - -void OMPClauseWriter::VisitOMPSeqCstClause(OMPSeqCstClause *) {} - -void OMPClauseWriter::VisitOMPThreadsClause(OMPThreadsClause *) {} - -void OMPClauseWriter::VisitOMPSIMDClause(OMPSIMDClause *) {} - -void OMPClauseWriter::VisitOMPNogroupClause(OMPNogroupClause *) {} - -void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) { - Record.push_back(C->varlist_size()); - Record.AddSourceLocation(C->getLParenLoc()); - for (auto *VE : C->varlists()) { - Record.AddStmt(VE); - } - for (auto *VE : C->private_copies()) { - Record.AddStmt(VE); - } -} - -void OMPClauseWriter::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) { - Record.push_back(C->varlist_size()); - VisitOMPClauseWithPreInit(C); - Record.AddSourceLocation(C->getLParenLoc()); - for (auto *VE : C->varlists()) { - Record.AddStmt(VE); - } - for (auto *VE : C->private_copies()) { - Record.AddStmt(VE); - } - for (auto *VE : C->inits()) { - Record.AddStmt(VE); - } -} - -void OMPClauseWriter::VisitOMPLastprivateClause(OMPLastprivateClause *C) { - Record.push_back(C->varlist_size()); - VisitOMPClauseWithPostUpdate(C); - Record.AddSourceLocation(C->getLParenLoc()); - for (auto *VE : C->varlists()) - Record.AddStmt(VE); - for (auto *E : C->private_copies()) - Record.AddStmt(E); - for (auto *E : C->source_exprs()) - Record.AddStmt(E); - for (auto *E : C->destination_exprs()) - Record.AddStmt(E); - for (auto *E : C->assignment_ops()) - Record.AddStmt(E); -} - -void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) { - Record.push_back(C->varlist_size()); - Record.AddSourceLocation(C->getLParenLoc()); - for (auto *VE : C->varlists()) - Record.AddStmt(VE); -} - -void OMPClauseWriter::VisitOMPReductionClause(OMPReductionClause *C) { - Record.push_back(C->varlist_size()); - VisitOMPClauseWithPostUpdate(C); - Record.AddSourceLocation(C->getLParenLoc()); - Record.AddSourceLocation(C->getColonLoc()); - Record.AddNestedNameSpecifierLoc(C->getQualifierLoc()); - Record.AddDeclarationNameInfo(C->getNameInfo()); - for (auto *VE : C->varlists()) - Record.AddStmt(VE); - for (auto *VE : C->privates()) - Record.AddStmt(VE); - for (auto *E : C->lhs_exprs()) - Record.AddStmt(E); - for (auto *E : C->rhs_exprs()) - Record.AddStmt(E); - for (auto *E : C->reduction_ops()) - Record.AddStmt(E); -} - -void OMPClauseWriter::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) { - Record.push_back(C->varlist_size()); - VisitOMPClauseWithPostUpdate(C); - Record.AddSourceLocation(C->getLParenLoc()); - Record.AddSourceLocation(C->getColonLoc()); - Record.AddNestedNameSpecifierLoc(C->getQualifierLoc()); - Record.AddDeclarationNameInfo(C->getNameInfo()); - for (auto *VE : C->varlists()) - Record.AddStmt(VE); - for (auto *VE : C->privates()) - Record.AddStmt(VE); - for (auto *E : C->lhs_exprs()) - Record.AddStmt(E); - for (auto *E : C->rhs_exprs()) - Record.AddStmt(E); - for (auto *E : C->reduction_ops()) - Record.AddStmt(E); -} - -void OMPClauseWriter::VisitOMPInReductionClause(OMPInReductionClause *C) { - Record.push_back(C->varlist_size()); - VisitOMPClauseWithPostUpdate(C); - Record.AddSourceLocation(C->getLParenLoc()); - Record.AddSourceLocation(C->getColonLoc()); - Record.AddNestedNameSpecifierLoc(C->getQualifierLoc()); - Record.AddDeclarationNameInfo(C->getNameInfo()); - for (auto *VE : C->varlists()) - Record.AddStmt(VE); - for (auto *VE : C->privates()) - Record.AddStmt(VE); - for (auto *E : C->lhs_exprs()) - Record.AddStmt(E); - for (auto *E : C->rhs_exprs()) - Record.AddStmt(E); - for (auto *E : C->reduction_ops()) - Record.AddStmt(E); - for (auto *E : C->taskgroup_descriptors()) - Record.AddStmt(E); -} - -void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) { - Record.push_back(C->varlist_size()); - VisitOMPClauseWithPostUpdate(C); - Record.AddSourceLocation(C->getLParenLoc()); - Record.AddSourceLocation(C->getColonLoc()); - Record.push_back(C->getModifier()); - Record.AddSourceLocation(C->getModifierLoc()); - for (auto *VE : C->varlists()) { - Record.AddStmt(VE); - } - for (auto *VE : C->privates()) { - Record.AddStmt(VE); - } - for (auto *VE : C->inits()) { - Record.AddStmt(VE); - } - for (auto *VE : C->updates()) { - Record.AddStmt(VE); - } - for (auto *VE : C->finals()) { - Record.AddStmt(VE); - } - Record.AddStmt(C->getStep()); - Record.AddStmt(C->getCalcStep()); -} - -void OMPClauseWriter::VisitOMPAlignedClause(OMPAlignedClause *C) { - Record.push_back(C->varlist_size()); - Record.AddSourceLocation(C->getLParenLoc()); - Record.AddSourceLocation(C->getColonLoc()); - for (auto *VE : C->varlists()) - Record.AddStmt(VE); - Record.AddStmt(C->getAlignment()); -} - -void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) { - Record.push_back(C->varlist_size()); - Record.AddSourceLocation(C->getLParenLoc()); - for (auto *VE : C->varlists()) - Record.AddStmt(VE); - for (auto *E : C->source_exprs()) - Record.AddStmt(E); - for (auto *E : C->destination_exprs()) - Record.AddStmt(E); - for (auto *E : C->assignment_ops()) - Record.AddStmt(E); -} - -void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) { - Record.push_back(C->varlist_size()); - Record.AddSourceLocation(C->getLParenLoc()); - for (auto *VE : C->varlists()) - Record.AddStmt(VE); - for (auto *E : C->source_exprs()) - Record.AddStmt(E); - for (auto *E : C->destination_exprs()) - Record.AddStmt(E); - for (auto *E : C->assignment_ops()) - Record.AddStmt(E); -} - -void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) { - Record.push_back(C->varlist_size()); - Record.AddSourceLocation(C->getLParenLoc()); - for (auto *VE : C->varlists()) - Record.AddStmt(VE); -} - -void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) { - Record.push_back(C->varlist_size()); - Record.push_back(C->getNumLoops()); - Record.AddSourceLocation(C->getLParenLoc()); - Record.push_back(C->getDependencyKind()); - Record.AddSourceLocation(C->getDependencyLoc()); - Record.AddSourceLocation(C->getColonLoc()); - for (auto *VE : C->varlists()) - Record.AddStmt(VE); - for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) - Record.AddStmt(C->getLoopData(I)); -} - -void OMPClauseWriter::VisitOMPDeviceClause(OMPDeviceClause *C) { - VisitOMPClauseWithPreInit(C); - Record.AddStmt(C->getDevice()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPMapClause(OMPMapClause *C) { - Record.push_back(C->varlist_size()); - Record.push_back(C->getUniqueDeclarationsNum()); - Record.push_back(C->getTotalComponentListNum()); - Record.push_back(C->getTotalComponentsNum()); - Record.AddSourceLocation(C->getLParenLoc()); - for (unsigned I = 0; I < OMPMapClause::NumberOfModifiers; ++I) { - Record.push_back(C->getMapTypeModifier(I)); - Record.AddSourceLocation(C->getMapTypeModifierLoc(I)); - } - Record.push_back(C->getMapType()); - Record.AddSourceLocation(C->getMapLoc()); - Record.AddSourceLocation(C->getColonLoc()); - for (auto *E : C->varlists()) - Record.AddStmt(E); - for (auto *D : C->all_decls()) - Record.AddDeclRef(D); - for (auto N : C->all_num_lists()) - Record.push_back(N); - for (auto N : C->all_lists_sizes()) - Record.push_back(N); - for (auto &M : C->all_components()) { - Record.AddStmt(M.getAssociatedExpression()); - Record.AddDeclRef(M.getAssociatedDeclaration()); - } -} - -void OMPClauseWriter::VisitOMPNumTeamsClause(OMPNumTeamsClause *C) { - VisitOMPClauseWithPreInit(C); - Record.AddStmt(C->getNumTeams()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPThreadLimitClause(OMPThreadLimitClause *C) { - VisitOMPClauseWithPreInit(C); - Record.AddStmt(C->getThreadLimit()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPPriorityClause(OMPPriorityClause *C) { - Record.AddStmt(C->getPriority()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) { - Record.AddStmt(C->getGrainsize()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPNumTasksClause(OMPNumTasksClause *C) { - Record.AddStmt(C->getNumTasks()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPHintClause(OMPHintClause *C) { - Record.AddStmt(C->getHint()); - Record.AddSourceLocation(C->getLParenLoc()); -} - -void OMPClauseWriter::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) { - VisitOMPClauseWithPreInit(C); - Record.push_back(C->getDistScheduleKind()); - Record.AddStmt(C->getChunkSize()); - Record.AddSourceLocation(C->getLParenLoc()); - Record.AddSourceLocation(C->getDistScheduleKindLoc()); - Record.AddSourceLocation(C->getCommaLoc()); -} - -void OMPClauseWriter::VisitOMPDefaultmapClause(OMPDefaultmapClause *C) { - Record.push_back(C->getDefaultmapKind()); - Record.push_back(C->getDefaultmapModifier()); - Record.AddSourceLocation(C->getLParenLoc()); - Record.AddSourceLocation(C->getDefaultmapModifierLoc()); - Record.AddSourceLocation(C->getDefaultmapKindLoc()); -} - -void OMPClauseWriter::VisitOMPToClause(OMPToClause *C) { - Record.push_back(C->varlist_size()); - Record.push_back(C->getUniqueDeclarationsNum()); - Record.push_back(C->getTotalComponentListNum()); - Record.push_back(C->getTotalComponentsNum()); - Record.AddSourceLocation(C->getLParenLoc()); - for (auto *E : C->varlists()) - Record.AddStmt(E); - for (auto *D : C->all_decls()) - Record.AddDeclRef(D); - for (auto N : C->all_num_lists()) - Record.push_back(N); - for (auto N : C->all_lists_sizes()) - Record.push_back(N); - for (auto &M : C->all_components()) { - Record.AddStmt(M.getAssociatedExpression()); - Record.AddDeclRef(M.getAssociatedDeclaration()); - } -} - -void OMPClauseWriter::VisitOMPFromClause(OMPFromClause *C) { - Record.push_back(C->varlist_size()); - Record.push_back(C->getUniqueDeclarationsNum()); - Record.push_back(C->getTotalComponentListNum()); - Record.push_back(C->getTotalComponentsNum()); - Record.AddSourceLocation(C->getLParenLoc()); - for (auto *E : C->varlists()) - Record.AddStmt(E); - for (auto *D : C->all_decls()) - Record.AddDeclRef(D); - for (auto N : C->all_num_lists()) - Record.push_back(N); - for (auto N : C->all_lists_sizes()) - Record.push_back(N); - for (auto &M : C->all_components()) { - Record.AddStmt(M.getAssociatedExpression()); - Record.AddDeclRef(M.getAssociatedDeclaration()); - } -} - -void OMPClauseWriter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *C) { - Record.push_back(C->varlist_size()); - Record.push_back(C->getUniqueDeclarationsNum()); - Record.push_back(C->getTotalComponentListNum()); - Record.push_back(C->getTotalComponentsNum()); - Record.AddSourceLocation(C->getLParenLoc()); - for (auto *E : C->varlists()) - Record.AddStmt(E); - for (auto *VE : C->private_copies()) - Record.AddStmt(VE); - for (auto *VE : C->inits()) - Record.AddStmt(VE); - for (auto *D : C->all_decls()) - Record.AddDeclRef(D); - for (auto N : C->all_num_lists()) - Record.push_back(N); - for (auto N : C->all_lists_sizes()) - Record.push_back(N); - for (auto &M : C->all_components()) { - Record.AddStmt(M.getAssociatedExpression()); - Record.AddDeclRef(M.getAssociatedDeclaration()); - } -} - -void OMPClauseWriter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) { - Record.push_back(C->varlist_size()); - Record.push_back(C->getUniqueDeclarationsNum()); - Record.push_back(C->getTotalComponentListNum()); - Record.push_back(C->getTotalComponentsNum()); - Record.AddSourceLocation(C->getLParenLoc()); - for (auto *E : C->varlists()) - Record.AddStmt(E); - for (auto *D : C->all_decls()) - Record.AddDeclRef(D); - for (auto N : C->all_num_lists()) - Record.push_back(N); - for (auto N : C->all_lists_sizes()) - Record.push_back(N); - for (auto &M : C->all_components()) { - Record.AddStmt(M.getAssociatedExpression()); - Record.AddDeclRef(M.getAssociatedDeclaration()); - } -} - -void OMPClauseWriter::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) {} - -void OMPClauseWriter::VisitOMPUnifiedSharedMemoryClause( - OMPUnifiedSharedMemoryClause *) {} - -void OMPClauseWriter::VisitOMPReverseOffloadClause(OMPReverseOffloadClause *) {} - -void -OMPClauseWriter::VisitOMPDynamicAllocatorsClause(OMPDynamicAllocatorsClause *) { -} - -void OMPClauseWriter::VisitOMPAtomicDefaultMemOrderClause( - OMPAtomicDefaultMemOrderClause *C) { - Record.push_back(C->getAtomicDefaultMemOrderKind()); - Record.AddSourceLocation(C->getLParenLoc()); - Record.AddSourceLocation(C->getAtomicDefaultMemOrderKindKwLoc()); -} diff --git a/gnu/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/gnu/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp deleted file mode 100644 index 002b43f8112..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp +++ /dev/null @@ -1,2355 +0,0 @@ -//===--- ASTWriterDecl.cpp - Declaration Serialization --------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements serialization for Declarations. -// -//===----------------------------------------------------------------------===// - -#include "ASTCommon.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclContextInternals.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/DeclVisitor.h" -#include "clang/AST/Expr.h" -#include "clang/AST/OpenMPClause.h" -#include "clang/AST/PrettyDeclStackTrace.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Serialization/ASTReader.h" -#include "clang/Serialization/ASTWriter.h" -#include "llvm/Bitcode/BitstreamWriter.h" -#include "llvm/Support/ErrorHandling.h" -using namespace clang; -using namespace serialization; - -//===----------------------------------------------------------------------===// -// Declaration serialization -//===----------------------------------------------------------------------===// - -namespace clang { - class ASTDeclWriter : public DeclVisitor<ASTDeclWriter, void> { - ASTWriter &Writer; - ASTContext &Context; - ASTRecordWriter Record; - - serialization::DeclCode Code; - unsigned AbbrevToUse; - - public: - ASTDeclWriter(ASTWriter &Writer, ASTContext &Context, - ASTWriter::RecordDataImpl &Record) - : Writer(Writer), Context(Context), Record(Writer, Record), - Code((serialization::DeclCode)0), AbbrevToUse(0) {} - - uint64_t Emit(Decl *D) { - if (!Code) - llvm::report_fatal_error(StringRef("unexpected declaration kind '") + - D->getDeclKindName() + "'"); - return Record.Emit(Code, AbbrevToUse); - } - - void Visit(Decl *D); - - void VisitDecl(Decl *D); - void VisitPragmaCommentDecl(PragmaCommentDecl *D); - void VisitPragmaDetectMismatchDecl(PragmaDetectMismatchDecl *D); - void VisitTranslationUnitDecl(TranslationUnitDecl *D); - void VisitNamedDecl(NamedDecl *D); - void VisitLabelDecl(LabelDecl *LD); - void VisitNamespaceDecl(NamespaceDecl *D); - void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); - void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); - void VisitTypeDecl(TypeDecl *D); - void VisitTypedefNameDecl(TypedefNameDecl *D); - void VisitTypedefDecl(TypedefDecl *D); - void VisitTypeAliasDecl(TypeAliasDecl *D); - void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); - void VisitTagDecl(TagDecl *D); - void VisitEnumDecl(EnumDecl *D); - void VisitRecordDecl(RecordDecl *D); - void VisitCXXRecordDecl(CXXRecordDecl *D); - void VisitClassTemplateSpecializationDecl( - ClassTemplateSpecializationDecl *D); - void VisitClassTemplatePartialSpecializationDecl( - ClassTemplatePartialSpecializationDecl *D); - void VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D); - void VisitVarTemplatePartialSpecializationDecl( - VarTemplatePartialSpecializationDecl *D); - void VisitClassScopeFunctionSpecializationDecl( - ClassScopeFunctionSpecializationDecl *D); - void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); - void VisitValueDecl(ValueDecl *D); - void VisitEnumConstantDecl(EnumConstantDecl *D); - void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); - void VisitDeclaratorDecl(DeclaratorDecl *D); - void VisitFunctionDecl(FunctionDecl *D); - void VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D); - void VisitCXXMethodDecl(CXXMethodDecl *D); - void VisitCXXConstructorDecl(CXXConstructorDecl *D); - void VisitCXXDestructorDecl(CXXDestructorDecl *D); - void VisitCXXConversionDecl(CXXConversionDecl *D); - void VisitFieldDecl(FieldDecl *D); - void VisitMSPropertyDecl(MSPropertyDecl *D); - void VisitIndirectFieldDecl(IndirectFieldDecl *D); - void VisitVarDecl(VarDecl *D); - void VisitImplicitParamDecl(ImplicitParamDecl *D); - void VisitParmVarDecl(ParmVarDecl *D); - void VisitDecompositionDecl(DecompositionDecl *D); - void VisitBindingDecl(BindingDecl *D); - void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); - void VisitTemplateDecl(TemplateDecl *D); - void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); - void VisitClassTemplateDecl(ClassTemplateDecl *D); - void VisitVarTemplateDecl(VarTemplateDecl *D); - void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); - void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); - void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); - void VisitUsingDecl(UsingDecl *D); - void VisitUsingPackDecl(UsingPackDecl *D); - void VisitUsingShadowDecl(UsingShadowDecl *D); - void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D); - void VisitLinkageSpecDecl(LinkageSpecDecl *D); - void VisitExportDecl(ExportDecl *D); - void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); - void VisitImportDecl(ImportDecl *D); - void VisitAccessSpecDecl(AccessSpecDecl *D); - void VisitFriendDecl(FriendDecl *D); - void VisitFriendTemplateDecl(FriendTemplateDecl *D); - void VisitStaticAssertDecl(StaticAssertDecl *D); - void VisitBlockDecl(BlockDecl *D); - void VisitCapturedDecl(CapturedDecl *D); - void VisitEmptyDecl(EmptyDecl *D); - - void VisitDeclContext(DeclContext *DC); - template <typename T> void VisitRedeclarable(Redeclarable<T> *D); - - - // FIXME: Put in the same order is DeclNodes.td? - void VisitObjCMethodDecl(ObjCMethodDecl *D); - void VisitObjCTypeParamDecl(ObjCTypeParamDecl *D); - void VisitObjCContainerDecl(ObjCContainerDecl *D); - void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); - void VisitObjCIvarDecl(ObjCIvarDecl *D); - void VisitObjCProtocolDecl(ObjCProtocolDecl *D); - void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D); - void VisitObjCCategoryDecl(ObjCCategoryDecl *D); - void VisitObjCImplDecl(ObjCImplDecl *D); - void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); - void VisitObjCImplementationDecl(ObjCImplementationDecl *D); - void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); - void VisitObjCPropertyDecl(ObjCPropertyDecl *D); - void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); - void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); - void VisitOMPRequiresDecl(OMPRequiresDecl *D); - void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D); - void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D); - - /// Add an Objective-C type parameter list to the given record. - void AddObjCTypeParamList(ObjCTypeParamList *typeParams) { - // Empty type parameter list. - if (!typeParams) { - Record.push_back(0); - return; - } - - Record.push_back(typeParams->size()); - for (auto typeParam : *typeParams) { - Record.AddDeclRef(typeParam); - } - Record.AddSourceLocation(typeParams->getLAngleLoc()); - Record.AddSourceLocation(typeParams->getRAngleLoc()); - } - - /// Add to the record the first declaration from each module file that - /// provides a declaration of D. The intent is to provide a sufficient - /// set such that reloading this set will load all current redeclarations. - void AddFirstDeclFromEachModule(const Decl *D, bool IncludeLocal) { - llvm::MapVector<ModuleFile*, const Decl*> Firsts; - // FIXME: We can skip entries that we know are implied by others. - for (const Decl *R = D->getMostRecentDecl(); R; R = R->getPreviousDecl()) { - if (R->isFromASTFile()) - Firsts[Writer.Chain->getOwningModuleFile(R)] = R; - else if (IncludeLocal) - Firsts[nullptr] = R; - } - for (const auto &F : Firsts) - Record.AddDeclRef(F.second); - } - - /// Get the specialization decl from an entry in the specialization list. - template <typename EntryType> - typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType * - getSpecializationDecl(EntryType &T) { - return RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::getDecl(&T); - } - - /// Get the list of partial specializations from a template's common ptr. - template<typename T> - decltype(T::PartialSpecializations) &getPartialSpecializations(T *Common) { - return Common->PartialSpecializations; - } - ArrayRef<Decl> getPartialSpecializations(FunctionTemplateDecl::Common *) { - return None; - } - - template<typename DeclTy> - void AddTemplateSpecializations(DeclTy *D) { - auto *Common = D->getCommonPtr(); - - // If we have any lazy specializations, and the external AST source is - // our chained AST reader, we can just write out the DeclIDs. Otherwise, - // we need to resolve them to actual declarations. - if (Writer.Chain != Writer.Context->getExternalSource() && - Common->LazySpecializations) { - D->LoadLazySpecializations(); - assert(!Common->LazySpecializations); - } - - ArrayRef<DeclID> LazySpecializations; - if (auto *LS = Common->LazySpecializations) - LazySpecializations = llvm::makeArrayRef(LS + 1, LS[0]); - - // Add a slot to the record for the number of specializations. - unsigned I = Record.size(); - Record.push_back(0); - - // AddFirstDeclFromEachModule might trigger deserialization, invalidating - // *Specializations iterators. - llvm::SmallVector<const Decl*, 16> Specs; - for (auto &Entry : Common->Specializations) - Specs.push_back(getSpecializationDecl(Entry)); - for (auto &Entry : getPartialSpecializations(Common)) - Specs.push_back(getSpecializationDecl(Entry)); - - for (auto *D : Specs) { - assert(D->isCanonicalDecl() && "non-canonical decl in set"); - AddFirstDeclFromEachModule(D, /*IncludeLocal*/true); - } - Record.append(LazySpecializations.begin(), LazySpecializations.end()); - - // Update the size entry we added earlier. - Record[I] = Record.size() - I - 1; - } - - /// Ensure that this template specialization is associated with the specified - /// template on reload. - void RegisterTemplateSpecialization(const Decl *Template, - const Decl *Specialization) { - Template = Template->getCanonicalDecl(); - - // If the canonical template is local, we'll write out this specialization - // when we emit it. - // FIXME: We can do the same thing if there is any local declaration of - // the template, to avoid emitting an update record. - if (!Template->isFromASTFile()) - return; - - // We only need to associate the first local declaration of the - // specialization. The other declarations will get pulled in by it. - if (Writer.getFirstLocalDecl(Specialization) != Specialization) - return; - - Writer.DeclUpdates[Template].push_back(ASTWriter::DeclUpdate( - UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, Specialization)); - } - }; -} - -void ASTDeclWriter::Visit(Decl *D) { - DeclVisitor<ASTDeclWriter>::Visit(D); - - // Source locations require array (variable-length) abbreviations. The - // abbreviation infrastructure requires that arrays are encoded last, so - // we handle it here in the case of those classes derived from DeclaratorDecl - if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) { - if (auto *TInfo = DD->getTypeSourceInfo()) - Record.AddTypeLoc(TInfo->getTypeLoc()); - } - - // Handle FunctionDecl's body here and write it after all other Stmts/Exprs - // have been written. We want it last because we will not read it back when - // retrieving it from the AST, we'll just lazily set the offset. - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - Record.push_back(FD->doesThisDeclarationHaveABody()); - if (FD->doesThisDeclarationHaveABody()) - Record.AddFunctionDefinition(FD); - } - - // If this declaration is also a DeclContext, write blocks for the - // declarations that lexically stored inside its context and those - // declarations that are visible from its context. - if (DeclContext *DC = dyn_cast<DeclContext>(D)) - VisitDeclContext(DC); -} - -void ASTDeclWriter::VisitDecl(Decl *D) { - Record.AddDeclRef(cast_or_null<Decl>(D->getDeclContext())); - if (D->getDeclContext() != D->getLexicalDeclContext()) - Record.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext())); - else - Record.push_back(0); - Record.push_back(D->isInvalidDecl()); - Record.push_back(D->hasAttrs()); - if (D->hasAttrs()) - Record.AddAttributes(D->getAttrs()); - Record.push_back(D->isImplicit()); - Record.push_back(D->isUsed(false)); - Record.push_back(D->isReferenced()); - Record.push_back(D->isTopLevelDeclInObjCContainer()); - Record.push_back(D->getAccess()); - Record.push_back(D->isModulePrivate()); - Record.push_back(Writer.getSubmoduleID(D->getOwningModule())); - - // If this declaration injected a name into a context different from its - // lexical context, and that context is an imported namespace, we need to - // update its visible declarations to include this name. - // - // This happens when we instantiate a class with a friend declaration or a - // function with a local extern declaration, for instance. - // - // FIXME: Can we handle this in AddedVisibleDecl instead? - if (D->isOutOfLine()) { - auto *DC = D->getDeclContext(); - while (auto *NS = dyn_cast<NamespaceDecl>(DC->getRedeclContext())) { - if (!NS->isFromASTFile()) - break; - Writer.UpdatedDeclContexts.insert(NS->getPrimaryContext()); - if (!NS->isInlineNamespace()) - break; - DC = NS->getParent(); - } - } -} - -void ASTDeclWriter::VisitPragmaCommentDecl(PragmaCommentDecl *D) { - StringRef Arg = D->getArg(); - Record.push_back(Arg.size()); - VisitDecl(D); - Record.AddSourceLocation(D->getBeginLoc()); - Record.push_back(D->getCommentKind()); - Record.AddString(Arg); - Code = serialization::DECL_PRAGMA_COMMENT; -} - -void ASTDeclWriter::VisitPragmaDetectMismatchDecl( - PragmaDetectMismatchDecl *D) { - StringRef Name = D->getName(); - StringRef Value = D->getValue(); - Record.push_back(Name.size() + 1 + Value.size()); - VisitDecl(D); - Record.AddSourceLocation(D->getBeginLoc()); - Record.AddString(Name); - Record.AddString(Value); - Code = serialization::DECL_PRAGMA_DETECT_MISMATCH; -} - -void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { - llvm_unreachable("Translation units aren't directly serialized"); -} - -void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) { - VisitDecl(D); - Record.AddDeclarationName(D->getDeclName()); - Record.push_back(needsAnonymousDeclarationNumber(D) - ? Writer.getAnonymousDeclarationNumber(D) - : 0); -} - -void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) { - VisitNamedDecl(D); - Record.AddSourceLocation(D->getBeginLoc()); - Record.AddTypeRef(QualType(D->getTypeForDecl(), 0)); -} - -void ASTDeclWriter::VisitTypedefNameDecl(TypedefNameDecl *D) { - VisitRedeclarable(D); - VisitTypeDecl(D); - Record.AddTypeSourceInfo(D->getTypeSourceInfo()); - Record.push_back(D->isModed()); - if (D->isModed()) - Record.AddTypeRef(D->getUnderlyingType()); - Record.AddDeclRef(D->getAnonDeclWithTypedefName(false)); -} - -void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { - VisitTypedefNameDecl(D); - if (D->getDeclContext() == D->getLexicalDeclContext() && - !D->hasAttrs() && - !D->isImplicit() && - D->getFirstDecl() == D->getMostRecentDecl() && - !D->isInvalidDecl() && - !D->isTopLevelDeclInObjCContainer() && - !D->isModulePrivate() && - !needsAnonymousDeclarationNumber(D) && - D->getDeclName().getNameKind() == DeclarationName::Identifier) - AbbrevToUse = Writer.getDeclTypedefAbbrev(); - - Code = serialization::DECL_TYPEDEF; -} - -void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) { - VisitTypedefNameDecl(D); - Record.AddDeclRef(D->getDescribedAliasTemplate()); - Code = serialization::DECL_TYPEALIAS; -} - -void ASTDeclWriter::VisitTagDecl(TagDecl *D) { - VisitRedeclarable(D); - VisitTypeDecl(D); - Record.push_back(D->getIdentifierNamespace()); - Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding - if (!isa<CXXRecordDecl>(D)) - Record.push_back(D->isCompleteDefinition()); - Record.push_back(D->isEmbeddedInDeclarator()); - Record.push_back(D->isFreeStanding()); - Record.push_back(D->isCompleteDefinitionRequired()); - Record.AddSourceRange(D->getBraceRange()); - - if (D->hasExtInfo()) { - Record.push_back(1); - Record.AddQualifierInfo(*D->getExtInfo()); - } else if (auto *TD = D->getTypedefNameForAnonDecl()) { - Record.push_back(2); - Record.AddDeclRef(TD); - Record.AddIdentifierRef(TD->getDeclName().getAsIdentifierInfo()); - } else { - Record.push_back(0); - } -} - -void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { - VisitTagDecl(D); - Record.AddTypeSourceInfo(D->getIntegerTypeSourceInfo()); - if (!D->getIntegerTypeSourceInfo()) - Record.AddTypeRef(D->getIntegerType()); - Record.AddTypeRef(D->getPromotionType()); - Record.push_back(D->getNumPositiveBits()); - Record.push_back(D->getNumNegativeBits()); - Record.push_back(D->isScoped()); - Record.push_back(D->isScopedUsingClassTag()); - Record.push_back(D->isFixed()); - Record.push_back(D->getODRHash()); - - if (MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo()) { - Record.AddDeclRef(MemberInfo->getInstantiatedFrom()); - Record.push_back(MemberInfo->getTemplateSpecializationKind()); - Record.AddSourceLocation(MemberInfo->getPointOfInstantiation()); - } else { - Record.AddDeclRef(nullptr); - } - - if (D->getDeclContext() == D->getLexicalDeclContext() && - !D->hasAttrs() && - !D->isImplicit() && - !D->isUsed(false) && - !D->hasExtInfo() && - !D->getTypedefNameForAnonDecl() && - D->getFirstDecl() == D->getMostRecentDecl() && - !D->isInvalidDecl() && - !D->isReferenced() && - !D->isTopLevelDeclInObjCContainer() && - D->getAccess() == AS_none && - !D->isModulePrivate() && - !CXXRecordDecl::classofKind(D->getKind()) && - !D->getIntegerTypeSourceInfo() && - !D->getMemberSpecializationInfo() && - !needsAnonymousDeclarationNumber(D) && - D->getDeclName().getNameKind() == DeclarationName::Identifier) - AbbrevToUse = Writer.getDeclEnumAbbrev(); - - Code = serialization::DECL_ENUM; -} - -void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { - VisitTagDecl(D); - Record.push_back(D->hasFlexibleArrayMember()); - Record.push_back(D->isAnonymousStructOrUnion()); - Record.push_back(D->hasObjectMember()); - Record.push_back(D->hasVolatileMember()); - Record.push_back(D->isNonTrivialToPrimitiveDefaultInitialize()); - Record.push_back(D->isNonTrivialToPrimitiveCopy()); - Record.push_back(D->isNonTrivialToPrimitiveDestroy()); - Record.push_back(D->isParamDestroyedInCallee()); - Record.push_back(D->getArgPassingRestrictions()); - - if (D->getDeclContext() == D->getLexicalDeclContext() && - !D->hasAttrs() && - !D->isImplicit() && - !D->isUsed(false) && - !D->hasExtInfo() && - !D->getTypedefNameForAnonDecl() && - D->getFirstDecl() == D->getMostRecentDecl() && - !D->isInvalidDecl() && - !D->isReferenced() && - !D->isTopLevelDeclInObjCContainer() && - D->getAccess() == AS_none && - !D->isModulePrivate() && - !CXXRecordDecl::classofKind(D->getKind()) && - !needsAnonymousDeclarationNumber(D) && - D->getDeclName().getNameKind() == DeclarationName::Identifier) - AbbrevToUse = Writer.getDeclRecordAbbrev(); - - Code = serialization::DECL_RECORD; -} - -void ASTDeclWriter::VisitValueDecl(ValueDecl *D) { - VisitNamedDecl(D); - Record.AddTypeRef(D->getType()); -} - -void ASTDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) { - VisitValueDecl(D); - Record.push_back(D->getInitExpr()? 1 : 0); - if (D->getInitExpr()) - Record.AddStmt(D->getInitExpr()); - Record.AddAPSInt(D->getInitVal()); - - Code = serialization::DECL_ENUM_CONSTANT; -} - -void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { - VisitValueDecl(D); - Record.AddSourceLocation(D->getInnerLocStart()); - Record.push_back(D->hasExtInfo()); - if (D->hasExtInfo()) - Record.AddQualifierInfo(*D->getExtInfo()); - // The location information is deferred until the end of the record. - Record.AddTypeRef(D->getTypeSourceInfo() ? D->getTypeSourceInfo()->getType() - : QualType()); -} - -void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { - VisitRedeclarable(D); - VisitDeclaratorDecl(D); - Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName()); - Record.push_back(D->getIdentifierNamespace()); - - // FunctionDecl's body is handled last at ASTWriterDecl::Visit, - // after everything else is written. - Record.push_back(static_cast<int>(D->getStorageClass())); // FIXME: stable encoding - Record.push_back(D->isInlineSpecified()); - Record.push_back(D->isInlined()); - Record.push_back(D->isExplicitSpecified()); - Record.push_back(D->isVirtualAsWritten()); - Record.push_back(D->isPure()); - Record.push_back(D->hasInheritedPrototype()); - Record.push_back(D->hasWrittenPrototype()); - Record.push_back(D->isDeletedBit()); - Record.push_back(D->isTrivial()); - Record.push_back(D->isTrivialForCall()); - Record.push_back(D->isDefaulted()); - Record.push_back(D->isExplicitlyDefaulted()); - Record.push_back(D->hasImplicitReturnZero()); - Record.push_back(D->isConstexpr()); - Record.push_back(D->usesSEHTry()); - Record.push_back(D->hasSkippedBody()); - Record.push_back(D->isMultiVersion()); - Record.push_back(D->isLateTemplateParsed()); - Record.push_back(D->getLinkageInternal()); - Record.AddSourceLocation(D->getEndLoc()); - - Record.push_back(D->getODRHash()); - - Record.push_back(D->getTemplatedKind()); - switch (D->getTemplatedKind()) { - case FunctionDecl::TK_NonTemplate: - break; - case FunctionDecl::TK_FunctionTemplate: - Record.AddDeclRef(D->getDescribedFunctionTemplate()); - break; - case FunctionDecl::TK_MemberSpecialization: { - MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo(); - Record.AddDeclRef(MemberInfo->getInstantiatedFrom()); - Record.push_back(MemberInfo->getTemplateSpecializationKind()); - Record.AddSourceLocation(MemberInfo->getPointOfInstantiation()); - break; - } - case FunctionDecl::TK_FunctionTemplateSpecialization: { - FunctionTemplateSpecializationInfo * - FTSInfo = D->getTemplateSpecializationInfo(); - - RegisterTemplateSpecialization(FTSInfo->getTemplate(), D); - - Record.AddDeclRef(FTSInfo->getTemplate()); - Record.push_back(FTSInfo->getTemplateSpecializationKind()); - - // Template arguments. - Record.AddTemplateArgumentList(FTSInfo->TemplateArguments); - - // Template args as written. - Record.push_back(FTSInfo->TemplateArgumentsAsWritten != nullptr); - if (FTSInfo->TemplateArgumentsAsWritten) { - Record.push_back(FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs); - for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs; - i!=e; ++i) - Record.AddTemplateArgumentLoc( - (*FTSInfo->TemplateArgumentsAsWritten)[i]); - Record.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->LAngleLoc); - Record.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->RAngleLoc); - } - - Record.AddSourceLocation(FTSInfo->getPointOfInstantiation()); - - if (D->isCanonicalDecl()) { - // Write the template that contains the specializations set. We will - // add a FunctionTemplateSpecializationInfo to it when reading. - Record.AddDeclRef(FTSInfo->getTemplate()->getCanonicalDecl()); - } - break; - } - case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { - DependentFunctionTemplateSpecializationInfo * - DFTSInfo = D->getDependentSpecializationInfo(); - - // Templates. - Record.push_back(DFTSInfo->getNumTemplates()); - for (int i=0, e = DFTSInfo->getNumTemplates(); i != e; ++i) - Record.AddDeclRef(DFTSInfo->getTemplate(i)); - - // Templates args. - Record.push_back(DFTSInfo->getNumTemplateArgs()); - for (int i=0, e = DFTSInfo->getNumTemplateArgs(); i != e; ++i) - Record.AddTemplateArgumentLoc(DFTSInfo->getTemplateArg(i)); - Record.AddSourceLocation(DFTSInfo->getLAngleLoc()); - Record.AddSourceLocation(DFTSInfo->getRAngleLoc()); - break; - } - } - - Record.push_back(D->param_size()); - for (auto P : D->parameters()) - Record.AddDeclRef(P); - Code = serialization::DECL_FUNCTION; -} - -void ASTDeclWriter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { - VisitFunctionDecl(D); - Record.push_back(D->isCopyDeductionCandidate()); - Code = serialization::DECL_CXX_DEDUCTION_GUIDE; -} - -void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { - VisitNamedDecl(D); - // FIXME: convert to LazyStmtPtr? - // Unlike C/C++, method bodies will never be in header files. - bool HasBodyStuff = D->getBody() != nullptr || - D->getSelfDecl() != nullptr || D->getCmdDecl() != nullptr; - Record.push_back(HasBodyStuff); - if (HasBodyStuff) { - Record.AddStmt(D->getBody()); - Record.AddDeclRef(D->getSelfDecl()); - Record.AddDeclRef(D->getCmdDecl()); - } - Record.push_back(D->isInstanceMethod()); - Record.push_back(D->isVariadic()); - Record.push_back(D->isPropertyAccessor()); - Record.push_back(D->isDefined()); - Record.push_back(D->isOverriding()); - Record.push_back(D->hasSkippedBody()); - - Record.push_back(D->isRedeclaration()); - Record.push_back(D->hasRedeclaration()); - if (D->hasRedeclaration()) { - assert(Context.getObjCMethodRedeclaration(D)); - Record.AddDeclRef(Context.getObjCMethodRedeclaration(D)); - } - - // FIXME: stable encoding for @required/@optional - Record.push_back(D->getImplementationControl()); - // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway/nullability - Record.push_back(D->getObjCDeclQualifier()); - Record.push_back(D->hasRelatedResultType()); - Record.AddTypeRef(D->getReturnType()); - Record.AddTypeSourceInfo(D->getReturnTypeSourceInfo()); - Record.AddSourceLocation(D->getEndLoc()); - Record.push_back(D->param_size()); - for (const auto *P : D->parameters()) - Record.AddDeclRef(P); - - Record.push_back(D->getSelLocsKind()); - unsigned NumStoredSelLocs = D->getNumStoredSelLocs(); - SourceLocation *SelLocs = D->getStoredSelLocs(); - Record.push_back(NumStoredSelLocs); - for (unsigned i = 0; i != NumStoredSelLocs; ++i) - Record.AddSourceLocation(SelLocs[i]); - - Code = serialization::DECL_OBJC_METHOD; -} - -void ASTDeclWriter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) { - VisitTypedefNameDecl(D); - Record.push_back(D->Variance); - Record.push_back(D->Index); - Record.AddSourceLocation(D->VarianceLoc); - Record.AddSourceLocation(D->ColonLoc); - - Code = serialization::DECL_OBJC_TYPE_PARAM; -} - -void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) { - VisitNamedDecl(D); - Record.AddSourceLocation(D->getAtStartLoc()); - Record.AddSourceRange(D->getAtEndRange()); - // Abstract class (no need to define a stable serialization::DECL code). -} - -void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { - VisitRedeclarable(D); - VisitObjCContainerDecl(D); - Record.AddTypeRef(QualType(D->getTypeForDecl(), 0)); - AddObjCTypeParamList(D->TypeParamList); - - Record.push_back(D->isThisDeclarationADefinition()); - if (D->isThisDeclarationADefinition()) { - // Write the DefinitionData - ObjCInterfaceDecl::DefinitionData &Data = D->data(); - - Record.AddTypeSourceInfo(D->getSuperClassTInfo()); - Record.AddSourceLocation(D->getEndOfDefinitionLoc()); - Record.push_back(Data.HasDesignatedInitializers); - - // Write out the protocols that are directly referenced by the @interface. - Record.push_back(Data.ReferencedProtocols.size()); - for (const auto *P : D->protocols()) - Record.AddDeclRef(P); - for (const auto &PL : D->protocol_locs()) - Record.AddSourceLocation(PL); - - // Write out the protocols that are transitively referenced. - Record.push_back(Data.AllReferencedProtocols.size()); - for (ObjCList<ObjCProtocolDecl>::iterator - P = Data.AllReferencedProtocols.begin(), - PEnd = Data.AllReferencedProtocols.end(); - P != PEnd; ++P) - Record.AddDeclRef(*P); - - - if (ObjCCategoryDecl *Cat = D->getCategoryListRaw()) { - // Ensure that we write out the set of categories for this class. - Writer.ObjCClassesWithCategories.insert(D); - - // Make sure that the categories get serialized. - for (; Cat; Cat = Cat->getNextClassCategoryRaw()) - (void)Writer.GetDeclRef(Cat); - } - } - - Code = serialization::DECL_OBJC_INTERFACE; -} - -void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) { - VisitFieldDecl(D); - // FIXME: stable encoding for @public/@private/@protected/@package - Record.push_back(D->getAccessControl()); - Record.push_back(D->getSynthesize()); - - if (D->getDeclContext() == D->getLexicalDeclContext() && - !D->hasAttrs() && - !D->isImplicit() && - !D->isUsed(false) && - !D->isInvalidDecl() && - !D->isReferenced() && - !D->isModulePrivate() && - !D->getBitWidth() && - !D->hasExtInfo() && - D->getDeclName()) - AbbrevToUse = Writer.getDeclObjCIvarAbbrev(); - - Code = serialization::DECL_OBJC_IVAR; -} - -void ASTDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { - VisitRedeclarable(D); - VisitObjCContainerDecl(D); - - Record.push_back(D->isThisDeclarationADefinition()); - if (D->isThisDeclarationADefinition()) { - Record.push_back(D->protocol_size()); - for (const auto *I : D->protocols()) - Record.AddDeclRef(I); - for (const auto &PL : D->protocol_locs()) - Record.AddSourceLocation(PL); - } - - Code = serialization::DECL_OBJC_PROTOCOL; -} - -void ASTDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) { - VisitFieldDecl(D); - Code = serialization::DECL_OBJC_AT_DEFS_FIELD; -} - -void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { - VisitObjCContainerDecl(D); - Record.AddSourceLocation(D->getCategoryNameLoc()); - Record.AddSourceLocation(D->getIvarLBraceLoc()); - Record.AddSourceLocation(D->getIvarRBraceLoc()); - Record.AddDeclRef(D->getClassInterface()); - AddObjCTypeParamList(D->TypeParamList); - Record.push_back(D->protocol_size()); - for (const auto *I : D->protocols()) - Record.AddDeclRef(I); - for (const auto &PL : D->protocol_locs()) - Record.AddSourceLocation(PL); - Code = serialization::DECL_OBJC_CATEGORY; -} - -void ASTDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) { - VisitNamedDecl(D); - Record.AddDeclRef(D->getClassInterface()); - Code = serialization::DECL_OBJC_COMPATIBLE_ALIAS; -} - -void ASTDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { - VisitNamedDecl(D); - Record.AddSourceLocation(D->getAtLoc()); - Record.AddSourceLocation(D->getLParenLoc()); - Record.AddTypeRef(D->getType()); - Record.AddTypeSourceInfo(D->getTypeSourceInfo()); - // FIXME: stable encoding - Record.push_back((unsigned)D->getPropertyAttributes()); - Record.push_back((unsigned)D->getPropertyAttributesAsWritten()); - // FIXME: stable encoding - Record.push_back((unsigned)D->getPropertyImplementation()); - Record.AddDeclarationName(D->getGetterName()); - Record.AddSourceLocation(D->getGetterNameLoc()); - Record.AddDeclarationName(D->getSetterName()); - Record.AddSourceLocation(D->getSetterNameLoc()); - Record.AddDeclRef(D->getGetterMethodDecl()); - Record.AddDeclRef(D->getSetterMethodDecl()); - Record.AddDeclRef(D->getPropertyIvarDecl()); - Code = serialization::DECL_OBJC_PROPERTY; -} - -void ASTDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) { - VisitObjCContainerDecl(D); - Record.AddDeclRef(D->getClassInterface()); - // Abstract class (no need to define a stable serialization::DECL code). -} - -void ASTDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { - VisitObjCImplDecl(D); - Record.AddSourceLocation(D->getCategoryNameLoc()); - Code = serialization::DECL_OBJC_CATEGORY_IMPL; -} - -void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { - VisitObjCImplDecl(D); - Record.AddDeclRef(D->getSuperClass()); - Record.AddSourceLocation(D->getSuperClassLoc()); - Record.AddSourceLocation(D->getIvarLBraceLoc()); - Record.AddSourceLocation(D->getIvarRBraceLoc()); - Record.push_back(D->hasNonZeroConstructors()); - Record.push_back(D->hasDestructors()); - Record.push_back(D->NumIvarInitializers); - if (D->NumIvarInitializers) - Record.AddCXXCtorInitializers( - llvm::makeArrayRef(D->init_begin(), D->init_end())); - Code = serialization::DECL_OBJC_IMPLEMENTATION; -} - -void ASTDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { - VisitDecl(D); - Record.AddSourceLocation(D->getBeginLoc()); - Record.AddDeclRef(D->getPropertyDecl()); - Record.AddDeclRef(D->getPropertyIvarDecl()); - Record.AddSourceLocation(D->getPropertyIvarDeclLoc()); - Record.AddStmt(D->getGetterCXXConstructor()); - Record.AddStmt(D->getSetterCXXAssignment()); - Code = serialization::DECL_OBJC_PROPERTY_IMPL; -} - -void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) { - VisitDeclaratorDecl(D); - Record.push_back(D->isMutable()); - - FieldDecl::InitStorageKind ISK = D->InitStorage.getInt(); - Record.push_back(ISK); - if (ISK == FieldDecl::ISK_CapturedVLAType) - Record.AddTypeRef(QualType(D->getCapturedVLAType(), 0)); - else if (ISK) - Record.AddStmt(D->getInClassInitializer()); - - Record.AddStmt(D->getBitWidth()); - - if (!D->getDeclName()) - Record.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D)); - - if (D->getDeclContext() == D->getLexicalDeclContext() && - !D->hasAttrs() && - !D->isImplicit() && - !D->isUsed(false) && - !D->isInvalidDecl() && - !D->isReferenced() && - !D->isTopLevelDeclInObjCContainer() && - !D->isModulePrivate() && - !D->getBitWidth() && - !D->hasInClassInitializer() && - !D->hasCapturedVLAType() && - !D->hasExtInfo() && - !ObjCIvarDecl::classofKind(D->getKind()) && - !ObjCAtDefsFieldDecl::classofKind(D->getKind()) && - D->getDeclName()) - AbbrevToUse = Writer.getDeclFieldAbbrev(); - - Code = serialization::DECL_FIELD; -} - -void ASTDeclWriter::VisitMSPropertyDecl(MSPropertyDecl *D) { - VisitDeclaratorDecl(D); - Record.AddIdentifierRef(D->getGetterId()); - Record.AddIdentifierRef(D->getSetterId()); - Code = serialization::DECL_MS_PROPERTY; -} - -void ASTDeclWriter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { - VisitValueDecl(D); - Record.push_back(D->getChainingSize()); - - for (const auto *P : D->chain()) - Record.AddDeclRef(P); - Code = serialization::DECL_INDIRECTFIELD; -} - -void ASTDeclWriter::VisitVarDecl(VarDecl *D) { - VisitRedeclarable(D); - VisitDeclaratorDecl(D); - Record.push_back(D->getStorageClass()); - Record.push_back(D->getTSCSpec()); - Record.push_back(D->getInitStyle()); - Record.push_back(D->isARCPseudoStrong()); - if (!isa<ParmVarDecl>(D)) { - Record.push_back(D->isThisDeclarationADemotedDefinition()); - Record.push_back(D->isExceptionVariable()); - Record.push_back(D->isNRVOVariable()); - Record.push_back(D->isCXXForRangeDecl()); - Record.push_back(D->isObjCForDecl()); - Record.push_back(D->isInline()); - Record.push_back(D->isInlineSpecified()); - Record.push_back(D->isConstexpr()); - Record.push_back(D->isInitCapture()); - Record.push_back(D->isPreviousDeclInSameBlockScope()); - if (const auto *IPD = dyn_cast<ImplicitParamDecl>(D)) - Record.push_back(static_cast<unsigned>(IPD->getParameterKind())); - else - Record.push_back(0); - Record.push_back(D->isEscapingByref()); - } - Record.push_back(D->getLinkageInternal()); - - if (D->getInit()) { - Record.push_back(!D->isInitKnownICE() ? 1 : (D->isInitICE() ? 3 : 2)); - Record.AddStmt(D->getInit()); - } else { - Record.push_back(0); - } - - if (D->hasAttr<BlocksAttr>() && D->getType()->getAsCXXRecordDecl()) { - ASTContext::BlockVarCopyInit Init = Writer.Context->getBlockVarCopyInit(D); - Record.AddStmt(Init.getCopyExpr()); - if (Init.getCopyExpr()) - Record.push_back(Init.canThrow()); - } - - if (D->getStorageDuration() == SD_Static) { - bool ModulesCodegen = false; - if (Writer.WritingModule && - !D->getDescribedVarTemplate() && !D->getMemberSpecializationInfo() && - !isa<VarTemplateSpecializationDecl>(D)) { - // When building a C++ Modules TS module interface unit, a strong - // definition in the module interface is provided by the compilation of - // that module interface unit, not by its users. (Inline variables are - // still emitted in module users.) - ModulesCodegen = - (Writer.WritingModule->Kind == Module::ModuleInterfaceUnit && - Writer.Context->GetGVALinkageForVariable(D) == GVA_StrongExternal); - } - Record.push_back(ModulesCodegen); - if (ModulesCodegen) - Writer.ModularCodegenDecls.push_back(Writer.GetDeclRef(D)); - } - - enum { - VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization - }; - if (VarTemplateDecl *TemplD = D->getDescribedVarTemplate()) { - Record.push_back(VarTemplate); - Record.AddDeclRef(TemplD); - } else if (MemberSpecializationInfo *SpecInfo - = D->getMemberSpecializationInfo()) { - Record.push_back(StaticDataMemberSpecialization); - Record.AddDeclRef(SpecInfo->getInstantiatedFrom()); - Record.push_back(SpecInfo->getTemplateSpecializationKind()); - Record.AddSourceLocation(SpecInfo->getPointOfInstantiation()); - } else { - Record.push_back(VarNotTemplate); - } - - if (D->getDeclContext() == D->getLexicalDeclContext() && - !D->hasAttrs() && - !D->isImplicit() && - !D->isUsed(false) && - !D->isInvalidDecl() && - !D->isReferenced() && - !D->isTopLevelDeclInObjCContainer() && - D->getAccess() == AS_none && - !D->isModulePrivate() && - !needsAnonymousDeclarationNumber(D) && - D->getDeclName().getNameKind() == DeclarationName::Identifier && - !D->hasExtInfo() && - D->getFirstDecl() == D->getMostRecentDecl() && - D->getKind() == Decl::Var && - !D->isInline() && - !D->isConstexpr() && - !D->isInitCapture() && - !D->isPreviousDeclInSameBlockScope() && - !(D->hasAttr<BlocksAttr>() && D->getType()->getAsCXXRecordDecl()) && - !D->isEscapingByref() && - D->getStorageDuration() != SD_Static && - !D->getMemberSpecializationInfo()) - AbbrevToUse = Writer.getDeclVarAbbrev(); - - Code = serialization::DECL_VAR; -} - -void ASTDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) { - VisitVarDecl(D); - Code = serialization::DECL_IMPLICIT_PARAM; -} - -void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { - VisitVarDecl(D); - Record.push_back(D->isObjCMethodParameter()); - Record.push_back(D->getFunctionScopeDepth()); - Record.push_back(D->getFunctionScopeIndex()); - Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding - Record.push_back(D->isKNRPromoted()); - Record.push_back(D->hasInheritedDefaultArg()); - Record.push_back(D->hasUninstantiatedDefaultArg()); - if (D->hasUninstantiatedDefaultArg()) - Record.AddStmt(D->getUninstantiatedDefaultArg()); - Code = serialization::DECL_PARM_VAR; - - assert(!D->isARCPseudoStrong()); // can be true of ImplicitParamDecl - - // If the assumptions about the DECL_PARM_VAR abbrev are true, use it. Here - // we dynamically check for the properties that we optimize for, but don't - // know are true of all PARM_VAR_DECLs. - if (D->getDeclContext() == D->getLexicalDeclContext() && - !D->hasAttrs() && - !D->hasExtInfo() && - !D->isImplicit() && - !D->isUsed(false) && - !D->isInvalidDecl() && - !D->isReferenced() && - D->getAccess() == AS_none && - !D->isModulePrivate() && - D->getStorageClass() == 0 && - D->getInitStyle() == VarDecl::CInit && // Can params have anything else? - D->getFunctionScopeDepth() == 0 && - D->getObjCDeclQualifier() == 0 && - !D->isKNRPromoted() && - !D->hasInheritedDefaultArg() && - D->getInit() == nullptr && - !D->hasUninstantiatedDefaultArg()) // No default expr. - AbbrevToUse = Writer.getDeclParmVarAbbrev(); - - // Check things we know are true of *every* PARM_VAR_DECL, which is more than - // just us assuming it. - assert(!D->getTSCSpec() && "PARM_VAR_DECL can't use TLS"); - assert(!D->isThisDeclarationADemotedDefinition() - && "PARM_VAR_DECL can't be demoted definition."); - assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private"); - assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var"); - assert(D->getPreviousDecl() == nullptr && "PARM_VAR_DECL can't be redecl"); - assert(!D->isStaticDataMember() && - "PARM_VAR_DECL can't be static data member"); -} - -void ASTDeclWriter::VisitDecompositionDecl(DecompositionDecl *D) { - // Record the number of bindings first to simplify deserialization. - Record.push_back(D->bindings().size()); - - VisitVarDecl(D); - for (auto *B : D->bindings()) - Record.AddDeclRef(B); - Code = serialization::DECL_DECOMPOSITION; -} - -void ASTDeclWriter::VisitBindingDecl(BindingDecl *D) { - VisitValueDecl(D); - Record.AddStmt(D->getBinding()); - Code = serialization::DECL_BINDING; -} - -void ASTDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { - VisitDecl(D); - Record.AddStmt(D->getAsmString()); - Record.AddSourceLocation(D->getRParenLoc()); - Code = serialization::DECL_FILE_SCOPE_ASM; -} - -void ASTDeclWriter::VisitEmptyDecl(EmptyDecl *D) { - VisitDecl(D); - Code = serialization::DECL_EMPTY; -} - -void ASTDeclWriter::VisitBlockDecl(BlockDecl *D) { - VisitDecl(D); - Record.AddStmt(D->getBody()); - Record.AddTypeSourceInfo(D->getSignatureAsWritten()); - Record.push_back(D->param_size()); - for (ParmVarDecl *P : D->parameters()) - Record.AddDeclRef(P); - Record.push_back(D->isVariadic()); - Record.push_back(D->blockMissingReturnType()); - Record.push_back(D->isConversionFromLambda()); - Record.push_back(D->doesNotEscape()); - Record.push_back(D->capturesCXXThis()); - Record.push_back(D->getNumCaptures()); - for (const auto &capture : D->captures()) { - Record.AddDeclRef(capture.getVariable()); - - unsigned flags = 0; - if (capture.isByRef()) flags |= 1; - if (capture.isNested()) flags |= 2; - if (capture.hasCopyExpr()) flags |= 4; - Record.push_back(flags); - - if (capture.hasCopyExpr()) Record.AddStmt(capture.getCopyExpr()); - } - - Code = serialization::DECL_BLOCK; -} - -void ASTDeclWriter::VisitCapturedDecl(CapturedDecl *CD) { - Record.push_back(CD->getNumParams()); - VisitDecl(CD); - Record.push_back(CD->getContextParamPosition()); - Record.push_back(CD->isNothrow() ? 1 : 0); - // Body is stored by VisitCapturedStmt. - for (unsigned I = 0; I < CD->getNumParams(); ++I) - Record.AddDeclRef(CD->getParam(I)); - Code = serialization::DECL_CAPTURED; -} - -void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { - VisitDecl(D); - Record.push_back(D->getLanguage()); - Record.AddSourceLocation(D->getExternLoc()); - Record.AddSourceLocation(D->getRBraceLoc()); - Code = serialization::DECL_LINKAGE_SPEC; -} - -void ASTDeclWriter::VisitExportDecl(ExportDecl *D) { - VisitDecl(D); - Record.AddSourceLocation(D->getRBraceLoc()); - Code = serialization::DECL_EXPORT; -} - -void ASTDeclWriter::VisitLabelDecl(LabelDecl *D) { - VisitNamedDecl(D); - Record.AddSourceLocation(D->getBeginLoc()); - Code = serialization::DECL_LABEL; -} - - -void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { - VisitRedeclarable(D); - VisitNamedDecl(D); - Record.push_back(D->isInline()); - Record.AddSourceLocation(D->getBeginLoc()); - Record.AddSourceLocation(D->getRBraceLoc()); - - if (D->isOriginalNamespace()) - Record.AddDeclRef(D->getAnonymousNamespace()); - Code = serialization::DECL_NAMESPACE; - - if (Writer.hasChain() && D->isAnonymousNamespace() && - D == D->getMostRecentDecl()) { - // This is a most recent reopening of the anonymous namespace. If its parent - // is in a previous PCH (or is the TU), mark that parent for update, because - // the original namespace always points to the latest re-opening of its - // anonymous namespace. - Decl *Parent = cast<Decl>( - D->getParent()->getRedeclContext()->getPrimaryContext()); - if (Parent->isFromASTFile() || isa<TranslationUnitDecl>(Parent)) { - Writer.DeclUpdates[Parent].push_back( - ASTWriter::DeclUpdate(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, D)); - } - } -} - -void ASTDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { - VisitRedeclarable(D); - VisitNamedDecl(D); - Record.AddSourceLocation(D->getNamespaceLoc()); - Record.AddSourceLocation(D->getTargetNameLoc()); - Record.AddNestedNameSpecifierLoc(D->getQualifierLoc()); - Record.AddDeclRef(D->getNamespace()); - Code = serialization::DECL_NAMESPACE_ALIAS; -} - -void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) { - VisitNamedDecl(D); - Record.AddSourceLocation(D->getUsingLoc()); - Record.AddNestedNameSpecifierLoc(D->getQualifierLoc()); - Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName()); - Record.AddDeclRef(D->FirstUsingShadow.getPointer()); - Record.push_back(D->hasTypename()); - Record.AddDeclRef(Context.getInstantiatedFromUsingDecl(D)); - Code = serialization::DECL_USING; -} - -void ASTDeclWriter::VisitUsingPackDecl(UsingPackDecl *D) { - Record.push_back(D->NumExpansions); - VisitNamedDecl(D); - Record.AddDeclRef(D->getInstantiatedFromUsingDecl()); - for (auto *E : D->expansions()) - Record.AddDeclRef(E); - Code = serialization::DECL_USING_PACK; -} - -void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) { - VisitRedeclarable(D); - VisitNamedDecl(D); - Record.AddDeclRef(D->getTargetDecl()); - Record.push_back(D->getIdentifierNamespace()); - Record.AddDeclRef(D->UsingOrNextShadow); - Record.AddDeclRef(Context.getInstantiatedFromUsingShadowDecl(D)); - Code = serialization::DECL_USING_SHADOW; -} - -void ASTDeclWriter::VisitConstructorUsingShadowDecl( - ConstructorUsingShadowDecl *D) { - VisitUsingShadowDecl(D); - Record.AddDeclRef(D->NominatedBaseClassShadowDecl); - Record.AddDeclRef(D->ConstructedBaseClassShadowDecl); - Record.push_back(D->IsVirtual); - Code = serialization::DECL_CONSTRUCTOR_USING_SHADOW; -} - -void ASTDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { - VisitNamedDecl(D); - Record.AddSourceLocation(D->getUsingLoc()); - Record.AddSourceLocation(D->getNamespaceKeyLocation()); - Record.AddNestedNameSpecifierLoc(D->getQualifierLoc()); - Record.AddDeclRef(D->getNominatedNamespace()); - Record.AddDeclRef(dyn_cast<Decl>(D->getCommonAncestor())); - Code = serialization::DECL_USING_DIRECTIVE; -} - -void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { - VisitValueDecl(D); - Record.AddSourceLocation(D->getUsingLoc()); - Record.AddNestedNameSpecifierLoc(D->getQualifierLoc()); - Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName()); - Record.AddSourceLocation(D->getEllipsisLoc()); - Code = serialization::DECL_UNRESOLVED_USING_VALUE; -} - -void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl( - UnresolvedUsingTypenameDecl *D) { - VisitTypeDecl(D); - Record.AddSourceLocation(D->getTypenameLoc()); - Record.AddNestedNameSpecifierLoc(D->getQualifierLoc()); - Record.AddSourceLocation(D->getEllipsisLoc()); - Code = serialization::DECL_UNRESOLVED_USING_TYPENAME; -} - -void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { - VisitRecordDecl(D); - - enum { - CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization - }; - if (ClassTemplateDecl *TemplD = D->getDescribedClassTemplate()) { - Record.push_back(CXXRecTemplate); - Record.AddDeclRef(TemplD); - } else if (MemberSpecializationInfo *MSInfo - = D->getMemberSpecializationInfo()) { - Record.push_back(CXXRecMemberSpecialization); - Record.AddDeclRef(MSInfo->getInstantiatedFrom()); - Record.push_back(MSInfo->getTemplateSpecializationKind()); - Record.AddSourceLocation(MSInfo->getPointOfInstantiation()); - } else { - Record.push_back(CXXRecNotTemplate); - } - - Record.push_back(D->isThisDeclarationADefinition()); - if (D->isThisDeclarationADefinition()) - Record.AddCXXDefinitionData(D); - - // Store (what we currently believe to be) the key function to avoid - // deserializing every method so we can compute it. - if (D->isCompleteDefinition()) - Record.AddDeclRef(Context.getCurrentKeyFunction(D)); - - Code = serialization::DECL_CXX_RECORD; -} - -void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) { - VisitFunctionDecl(D); - if (D->isCanonicalDecl()) { - Record.push_back(D->size_overridden_methods()); - for (const CXXMethodDecl *MD : D->overridden_methods()) - Record.AddDeclRef(MD); - } else { - // We only need to record overridden methods once for the canonical decl. - Record.push_back(0); - } - - if (D->getDeclContext() == D->getLexicalDeclContext() && - D->getFirstDecl() == D->getMostRecentDecl() && - !D->isInvalidDecl() && - !D->hasAttrs() && - !D->isTopLevelDeclInObjCContainer() && - D->getDeclName().getNameKind() == DeclarationName::Identifier && - !D->hasExtInfo() && - !D->hasInheritedPrototype() && - D->hasWrittenPrototype()) - AbbrevToUse = Writer.getDeclCXXMethodAbbrev(); - - Code = serialization::DECL_CXX_METHOD; -} - -void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { - if (auto Inherited = D->getInheritedConstructor()) { - Record.AddDeclRef(Inherited.getShadowDecl()); - Record.AddDeclRef(Inherited.getConstructor()); - Code = serialization::DECL_CXX_INHERITED_CONSTRUCTOR; - } else { - Code = serialization::DECL_CXX_CONSTRUCTOR; - } - - VisitCXXMethodDecl(D); - - Code = D->isInheritingConstructor() - ? serialization::DECL_CXX_INHERITED_CONSTRUCTOR - : serialization::DECL_CXX_CONSTRUCTOR; -} - -void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) { - VisitCXXMethodDecl(D); - - Record.AddDeclRef(D->getOperatorDelete()); - if (D->getOperatorDelete()) - Record.AddStmt(D->getOperatorDeleteThisArg()); - - Code = serialization::DECL_CXX_DESTRUCTOR; -} - -void ASTDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) { - VisitCXXMethodDecl(D); - Code = serialization::DECL_CXX_CONVERSION; -} - -void ASTDeclWriter::VisitImportDecl(ImportDecl *D) { - VisitDecl(D); - Record.push_back(Writer.getSubmoduleID(D->getImportedModule())); - ArrayRef<SourceLocation> IdentifierLocs = D->getIdentifierLocs(); - Record.push_back(!IdentifierLocs.empty()); - if (IdentifierLocs.empty()) { - Record.AddSourceLocation(D->getEndLoc()); - Record.push_back(1); - } else { - for (unsigned I = 0, N = IdentifierLocs.size(); I != N; ++I) - Record.AddSourceLocation(IdentifierLocs[I]); - Record.push_back(IdentifierLocs.size()); - } - // Note: the number of source locations must always be the last element in - // the record. - Code = serialization::DECL_IMPORT; -} - -void ASTDeclWriter::VisitAccessSpecDecl(AccessSpecDecl *D) { - VisitDecl(D); - Record.AddSourceLocation(D->getColonLoc()); - Code = serialization::DECL_ACCESS_SPEC; -} - -void ASTDeclWriter::VisitFriendDecl(FriendDecl *D) { - // Record the number of friend type template parameter lists here - // so as to simplify memory allocation during deserialization. - Record.push_back(D->NumTPLists); - VisitDecl(D); - bool hasFriendDecl = D->Friend.is<NamedDecl*>(); - Record.push_back(hasFriendDecl); - if (hasFriendDecl) - Record.AddDeclRef(D->getFriendDecl()); - else - Record.AddTypeSourceInfo(D->getFriendType()); - for (unsigned i = 0; i < D->NumTPLists; ++i) - Record.AddTemplateParameterList(D->getFriendTypeTemplateParameterList(i)); - Record.AddDeclRef(D->getNextFriend()); - Record.push_back(D->UnsupportedFriend); - Record.AddSourceLocation(D->FriendLoc); - Code = serialization::DECL_FRIEND; -} - -void ASTDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) { - VisitDecl(D); - Record.push_back(D->getNumTemplateParameters()); - for (unsigned i = 0, e = D->getNumTemplateParameters(); i != e; ++i) - Record.AddTemplateParameterList(D->getTemplateParameterList(i)); - Record.push_back(D->getFriendDecl() != nullptr); - if (D->getFriendDecl()) - Record.AddDeclRef(D->getFriendDecl()); - else - Record.AddTypeSourceInfo(D->getFriendType()); - Record.AddSourceLocation(D->getFriendLoc()); - Code = serialization::DECL_FRIEND_TEMPLATE; -} - -void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) { - VisitNamedDecl(D); - - Record.AddDeclRef(D->getTemplatedDecl()); - Record.AddTemplateParameterList(D->getTemplateParameters()); -} - -void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { - VisitRedeclarable(D); - - // Emit data to initialize CommonOrPrev before VisitTemplateDecl so that - // getCommonPtr() can be used while this is still initializing. - if (D->isFirstDecl()) { - // This declaration owns the 'common' pointer, so serialize that data now. - Record.AddDeclRef(D->getInstantiatedFromMemberTemplate()); - if (D->getInstantiatedFromMemberTemplate()) - Record.push_back(D->isMemberSpecialization()); - } - - VisitTemplateDecl(D); - Record.push_back(D->getIdentifierNamespace()); -} - -void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { - VisitRedeclarableTemplateDecl(D); - - if (D->isFirstDecl()) - AddTemplateSpecializations(D); - Code = serialization::DECL_CLASS_TEMPLATE; -} - -void ASTDeclWriter::VisitClassTemplateSpecializationDecl( - ClassTemplateSpecializationDecl *D) { - RegisterTemplateSpecialization(D->getSpecializedTemplate(), D); - - VisitCXXRecordDecl(D); - - llvm::PointerUnion<ClassTemplateDecl *, - ClassTemplatePartialSpecializationDecl *> InstFrom - = D->getSpecializedTemplateOrPartial(); - if (Decl *InstFromD = InstFrom.dyn_cast<ClassTemplateDecl *>()) { - Record.AddDeclRef(InstFromD); - } else { - Record.AddDeclRef(InstFrom.get<ClassTemplatePartialSpecializationDecl *>()); - Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs()); - } - - Record.AddTemplateArgumentList(&D->getTemplateArgs()); - Record.AddSourceLocation(D->getPointOfInstantiation()); - Record.push_back(D->getSpecializationKind()); - Record.push_back(D->isCanonicalDecl()); - - if (D->isCanonicalDecl()) { - // When reading, we'll add it to the folding set of the following template. - Record.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl()); - } - - // Explicit info. - Record.AddTypeSourceInfo(D->getTypeAsWritten()); - if (D->getTypeAsWritten()) { - Record.AddSourceLocation(D->getExternLoc()); - Record.AddSourceLocation(D->getTemplateKeywordLoc()); - } - - Code = serialization::DECL_CLASS_TEMPLATE_SPECIALIZATION; -} - -void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl( - ClassTemplatePartialSpecializationDecl *D) { - VisitClassTemplateSpecializationDecl(D); - - Record.AddTemplateParameterList(D->getTemplateParameters()); - Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); - - // These are read/set from/to the first declaration. - if (D->getPreviousDecl() == nullptr) { - Record.AddDeclRef(D->getInstantiatedFromMember()); - Record.push_back(D->isMemberSpecialization()); - } - - Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION; -} - -void ASTDeclWriter::VisitVarTemplateDecl(VarTemplateDecl *D) { - VisitRedeclarableTemplateDecl(D); - - if (D->isFirstDecl()) - AddTemplateSpecializations(D); - Code = serialization::DECL_VAR_TEMPLATE; -} - -void ASTDeclWriter::VisitVarTemplateSpecializationDecl( - VarTemplateSpecializationDecl *D) { - RegisterTemplateSpecialization(D->getSpecializedTemplate(), D); - - VisitVarDecl(D); - - llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> - InstFrom = D->getSpecializedTemplateOrPartial(); - if (Decl *InstFromD = InstFrom.dyn_cast<VarTemplateDecl *>()) { - Record.AddDeclRef(InstFromD); - } else { - Record.AddDeclRef(InstFrom.get<VarTemplatePartialSpecializationDecl *>()); - Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs()); - } - - // Explicit info. - Record.AddTypeSourceInfo(D->getTypeAsWritten()); - if (D->getTypeAsWritten()) { - Record.AddSourceLocation(D->getExternLoc()); - Record.AddSourceLocation(D->getTemplateKeywordLoc()); - } - - Record.AddTemplateArgumentList(&D->getTemplateArgs()); - Record.AddSourceLocation(D->getPointOfInstantiation()); - Record.push_back(D->getSpecializationKind()); - Record.push_back(D->IsCompleteDefinition); - Record.push_back(D->isCanonicalDecl()); - - if (D->isCanonicalDecl()) { - // When reading, we'll add it to the folding set of the following template. - Record.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl()); - } - - Code = serialization::DECL_VAR_TEMPLATE_SPECIALIZATION; -} - -void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl( - VarTemplatePartialSpecializationDecl *D) { - VisitVarTemplateSpecializationDecl(D); - - Record.AddTemplateParameterList(D->getTemplateParameters()); - Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); - - // These are read/set from/to the first declaration. - if (D->getPreviousDecl() == nullptr) { - Record.AddDeclRef(D->getInstantiatedFromMember()); - Record.push_back(D->isMemberSpecialization()); - } - - Code = serialization::DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION; -} - -void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl( - ClassScopeFunctionSpecializationDecl *D) { - VisitDecl(D); - Record.AddDeclRef(D->getSpecialization()); - Code = serialization::DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION; -} - - -void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { - VisitRedeclarableTemplateDecl(D); - - if (D->isFirstDecl()) - AddTemplateSpecializations(D); - Code = serialization::DECL_FUNCTION_TEMPLATE; -} - -void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { - VisitTypeDecl(D); - - Record.push_back(D->wasDeclaredWithTypename()); - - bool OwnsDefaultArg = D->hasDefaultArgument() && - !D->defaultArgumentWasInherited(); - Record.push_back(OwnsDefaultArg); - if (OwnsDefaultArg) - Record.AddTypeSourceInfo(D->getDefaultArgumentInfo()); - - Code = serialization::DECL_TEMPLATE_TYPE_PARM; -} - -void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { - // For an expanded parameter pack, record the number of expansion types here - // so that it's easier for deserialization to allocate the right amount of - // memory. - if (D->isExpandedParameterPack()) - Record.push_back(D->getNumExpansionTypes()); - - VisitDeclaratorDecl(D); - // TemplateParmPosition. - Record.push_back(D->getDepth()); - Record.push_back(D->getPosition()); - - if (D->isExpandedParameterPack()) { - for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) { - Record.AddTypeRef(D->getExpansionType(I)); - Record.AddTypeSourceInfo(D->getExpansionTypeSourceInfo(I)); - } - - Code = serialization::DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK; - } else { - // Rest of NonTypeTemplateParmDecl. - Record.push_back(D->isParameterPack()); - bool OwnsDefaultArg = D->hasDefaultArgument() && - !D->defaultArgumentWasInherited(); - Record.push_back(OwnsDefaultArg); - if (OwnsDefaultArg) - Record.AddStmt(D->getDefaultArgument()); - Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM; - } -} - -void ASTDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { - // For an expanded parameter pack, record the number of expansion types here - // so that it's easier for deserialization to allocate the right amount of - // memory. - if (D->isExpandedParameterPack()) - Record.push_back(D->getNumExpansionTemplateParameters()); - - VisitTemplateDecl(D); - // TemplateParmPosition. - Record.push_back(D->getDepth()); - Record.push_back(D->getPosition()); - - if (D->isExpandedParameterPack()) { - for (unsigned I = 0, N = D->getNumExpansionTemplateParameters(); - I != N; ++I) - Record.AddTemplateParameterList(D->getExpansionTemplateParameters(I)); - Code = serialization::DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK; - } else { - // Rest of TemplateTemplateParmDecl. - Record.push_back(D->isParameterPack()); - bool OwnsDefaultArg = D->hasDefaultArgument() && - !D->defaultArgumentWasInherited(); - Record.push_back(OwnsDefaultArg); - if (OwnsDefaultArg) - Record.AddTemplateArgumentLoc(D->getDefaultArgument()); - Code = serialization::DECL_TEMPLATE_TEMPLATE_PARM; - } -} - -void ASTDeclWriter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { - VisitRedeclarableTemplateDecl(D); - Code = serialization::DECL_TYPE_ALIAS_TEMPLATE; -} - -void ASTDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) { - VisitDecl(D); - Record.AddStmt(D->getAssertExpr()); - Record.push_back(D->isFailed()); - Record.AddStmt(D->getMessage()); - Record.AddSourceLocation(D->getRParenLoc()); - Code = serialization::DECL_STATIC_ASSERT; -} - -/// Emit the DeclContext part of a declaration context decl. -void ASTDeclWriter::VisitDeclContext(DeclContext *DC) { - Record.AddOffset(Writer.WriteDeclContextLexicalBlock(Context, DC)); - Record.AddOffset(Writer.WriteDeclContextVisibleBlock(Context, DC)); -} - -const Decl *ASTWriter::getFirstLocalDecl(const Decl *D) { - assert(IsLocalDecl(D) && "expected a local declaration"); - - const Decl *Canon = D->getCanonicalDecl(); - if (IsLocalDecl(Canon)) - return Canon; - - const Decl *&CacheEntry = FirstLocalDeclCache[Canon]; - if (CacheEntry) - return CacheEntry; - - for (const Decl *Redecl = D; Redecl; Redecl = Redecl->getPreviousDecl()) - if (IsLocalDecl(Redecl)) - D = Redecl; - return CacheEntry = D; -} - -template <typename T> -void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) { - T *First = D->getFirstDecl(); - T *MostRecent = First->getMostRecentDecl(); - T *DAsT = static_cast<T *>(D); - if (MostRecent != First) { - assert(isRedeclarableDeclKind(DAsT->getKind()) && - "Not considered redeclarable?"); - - Record.AddDeclRef(First); - - // Write out a list of local redeclarations of this declaration if it's the - // first local declaration in the chain. - const Decl *FirstLocal = Writer.getFirstLocalDecl(DAsT); - if (DAsT == FirstLocal) { - // Emit a list of all imported first declarations so that we can be sure - // that all redeclarations visible to this module are before D in the - // redecl chain. - unsigned I = Record.size(); - Record.push_back(0); - if (Writer.Chain) - AddFirstDeclFromEachModule(DAsT, /*IncludeLocal*/false); - // This is the number of imported first declarations + 1. - Record[I] = Record.size() - I; - - // Collect the set of local redeclarations of this declaration, from - // newest to oldest. - ASTWriter::RecordData LocalRedecls; - ASTRecordWriter LocalRedeclWriter(Record, LocalRedecls); - for (const Decl *Prev = FirstLocal->getMostRecentDecl(); - Prev != FirstLocal; Prev = Prev->getPreviousDecl()) - if (!Prev->isFromASTFile()) - LocalRedeclWriter.AddDeclRef(Prev); - - // If we have any redecls, write them now as a separate record preceding - // the declaration itself. - if (LocalRedecls.empty()) - Record.push_back(0); - else - Record.AddOffset(LocalRedeclWriter.Emit(LOCAL_REDECLARATIONS)); - } else { - Record.push_back(0); - Record.AddDeclRef(FirstLocal); - } - - // Make sure that we serialize both the previous and the most-recent - // declarations, which (transitively) ensures that all declarations in the - // chain get serialized. - // - // FIXME: This is not correct; when we reach an imported declaration we - // won't emit its previous declaration. - (void)Writer.GetDeclRef(D->getPreviousDecl()); - (void)Writer.GetDeclRef(MostRecent); - } else { - // We use the sentinel value 0 to indicate an only declaration. - Record.push_back(0); - } -} - -void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { - Record.push_back(D->varlist_size()); - VisitDecl(D); - for (auto *I : D->varlists()) - Record.AddStmt(I); - Code = serialization::DECL_OMP_THREADPRIVATE; -} - -void ASTDeclWriter::VisitOMPRequiresDecl(OMPRequiresDecl *D) { - Record.push_back(D->clauselist_size()); - VisitDecl(D); - OMPClauseWriter ClauseWriter(Record); - for (OMPClause *C : D->clauselists()) - ClauseWriter.writeClause(C); - Code = serialization::DECL_OMP_REQUIRES; -} - -void ASTDeclWriter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { - VisitValueDecl(D); - Record.AddSourceLocation(D->getBeginLoc()); - Record.AddStmt(D->getCombinerIn()); - Record.AddStmt(D->getCombinerOut()); - Record.AddStmt(D->getCombiner()); - Record.AddStmt(D->getInitOrig()); - Record.AddStmt(D->getInitPriv()); - Record.AddStmt(D->getInitializer()); - Record.push_back(D->getInitializerKind()); - Record.AddDeclRef(D->getPrevDeclInScope()); - Code = serialization::DECL_OMP_DECLARE_REDUCTION; -} - -void ASTDeclWriter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) { - VisitVarDecl(D); - Code = serialization::DECL_OMP_CAPTUREDEXPR; -} - -//===----------------------------------------------------------------------===// -// ASTWriter Implementation -//===----------------------------------------------------------------------===// - -void ASTWriter::WriteDeclAbbrevs() { - using namespace llvm; - - std::shared_ptr<BitCodeAbbrev> Abv; - - // Abbreviation for DECL_FIELD - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::DECL_FIELD)); - // Decl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl - Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs - Abv->Add(BitCodeAbbrevOp(0)); // isImplicit - Abv->Add(BitCodeAbbrevOp(0)); // isUsed - Abv->Add(BitCodeAbbrevOp(0)); // isReferenced - Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID - // NamedDecl - Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name - Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber - // ValueDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - // DeclaratorDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc - Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType - // FieldDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable - Abv->Add(BitCodeAbbrevOp(0)); // InitStyle - // Type Source Info - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc - DeclFieldAbbrev = Stream.EmitAbbrev(std::move(Abv)); - - // Abbreviation for DECL_OBJC_IVAR - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::DECL_OBJC_IVAR)); - // Decl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl - Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs - Abv->Add(BitCodeAbbrevOp(0)); // isImplicit - Abv->Add(BitCodeAbbrevOp(0)); // isUsed - Abv->Add(BitCodeAbbrevOp(0)); // isReferenced - Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID - // NamedDecl - Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name - Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber - // ValueDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - // DeclaratorDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc - Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType - // FieldDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable - Abv->Add(BitCodeAbbrevOp(0)); // InitStyle - // ObjC Ivar - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getAccessControl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getSynthesize - // Type Source Info - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc - DeclObjCIvarAbbrev = Stream.EmitAbbrev(std::move(Abv)); - - // Abbreviation for DECL_ENUM - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::DECL_ENUM)); - // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration - // Decl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl - Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs - Abv->Add(BitCodeAbbrevOp(0)); // isImplicit - Abv->Add(BitCodeAbbrevOp(0)); // isUsed - Abv->Add(BitCodeAbbrevOp(0)); // isReferenced - Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer - Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID - // NamedDecl - Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name - Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber - // TypeDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref - // TagDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getTagKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCompleteDefinition - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // EmbeddedInDeclarator - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsCompleteDefinitionRequired - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation - Abv->Add(BitCodeAbbrevOp(0)); // ExtInfoKind - // EnumDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // AddTypeRef - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IntegerType - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getPromotionType - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getNumPositiveBits - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getNumNegativeBits - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isScoped - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isScopedUsingClassTag - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isFixed - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));// ODRHash - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InstantiatedMembEnum - // DC - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalOffset - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // VisibleOffset - DeclEnumAbbrev = Stream.EmitAbbrev(std::move(Abv)); - - // Abbreviation for DECL_RECORD - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::DECL_RECORD)); - // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration - // Decl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl - Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs - Abv->Add(BitCodeAbbrevOp(0)); // isImplicit - Abv->Add(BitCodeAbbrevOp(0)); // isUsed - Abv->Add(BitCodeAbbrevOp(0)); // isReferenced - Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer - Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID - // NamedDecl - Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name - Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber - // TypeDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref - // TagDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getTagKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCompleteDefinition - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // EmbeddedInDeclarator - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsCompleteDefinitionRequired - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation - Abv->Add(BitCodeAbbrevOp(0)); // ExtInfoKind - // RecordDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // FlexibleArrayMember - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // AnonymousStructUnion - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // hasObjectMember - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // hasVolatileMember - - // isNonTrivialToPrimitiveDefaultInitialize - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); - // isNonTrivialToPrimitiveCopy - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); - // isNonTrivialToPrimitiveDestroy - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); - // isParamDestroyedInCallee - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); - // getArgPassingRestrictions - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); - - // DC - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalOffset - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // VisibleOffset - DeclRecordAbbrev = Stream.EmitAbbrev(std::move(Abv)); - - // Abbreviation for DECL_PARM_VAR - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARM_VAR)); - // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration - // Decl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl - Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs - Abv->Add(BitCodeAbbrevOp(0)); // isImplicit - Abv->Add(BitCodeAbbrevOp(0)); // isUsed - Abv->Add(BitCodeAbbrevOp(0)); // isReferenced - Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer - Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID - // NamedDecl - Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name - Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber - // ValueDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - // DeclaratorDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc - Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType - // VarDecl - Abv->Add(BitCodeAbbrevOp(0)); // SClass - Abv->Add(BitCodeAbbrevOp(0)); // TSCSpec - Abv->Add(BitCodeAbbrevOp(0)); // InitStyle - Abv->Add(BitCodeAbbrevOp(0)); // ARCPseudoStrong - Abv->Add(BitCodeAbbrevOp(0)); // Linkage - Abv->Add(BitCodeAbbrevOp(0)); // HasInit - Abv->Add(BitCodeAbbrevOp(0)); // HasMemberSpecializationInfo - // ParmVarDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsObjCMethodParameter - Abv->Add(BitCodeAbbrevOp(0)); // ScopeDepth - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ScopeIndex - Abv->Add(BitCodeAbbrevOp(0)); // ObjCDeclQualifier - Abv->Add(BitCodeAbbrevOp(0)); // KNRPromoted - Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedDefaultArg - Abv->Add(BitCodeAbbrevOp(0)); // HasUninstantiatedDefaultArg - // Type Source Info - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc - DeclParmVarAbbrev = Stream.EmitAbbrev(std::move(Abv)); - - // Abbreviation for DECL_TYPEDEF - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::DECL_TYPEDEF)); - // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration - // Decl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl - Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs - Abv->Add(BitCodeAbbrevOp(0)); // isImplicit - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isUsed - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isReferenced - Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID - // NamedDecl - Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name - Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber - // TypeDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref - // TypedefDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc - DeclTypedefAbbrev = Stream.EmitAbbrev(std::move(Abv)); - - // Abbreviation for DECL_VAR - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::DECL_VAR)); - // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration - // Decl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl - Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs - Abv->Add(BitCodeAbbrevOp(0)); // isImplicit - Abv->Add(BitCodeAbbrevOp(0)); // isUsed - Abv->Add(BitCodeAbbrevOp(0)); // isReferenced - Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer - Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID - // NamedDecl - Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name - Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber - // ValueDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - // DeclaratorDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc - Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType - // VarDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // SClass - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // TSCSpec - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // InitStyle - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsThisDeclarationADemotedDefinition - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isExceptionVariable - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isObjCForDecl - Abv->Add(BitCodeAbbrevOp(0)); // isInline - Abv->Add(BitCodeAbbrevOp(0)); // isInlineSpecified - Abv->Add(BitCodeAbbrevOp(0)); // isConstexpr - Abv->Add(BitCodeAbbrevOp(0)); // isInitCapture - Abv->Add(BitCodeAbbrevOp(0)); // isPrevDeclInSameScope - Abv->Add(BitCodeAbbrevOp(0)); // ImplicitParamKind - Abv->Add(BitCodeAbbrevOp(0)); // EscapingByref - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // IsInitICE (local) - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // VarKind (local enum) - // Type Source Info - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc - DeclVarAbbrev = Stream.EmitAbbrev(std::move(Abv)); - - // Abbreviation for DECL_CXX_METHOD - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::DECL_CXX_METHOD)); - // RedeclarableDecl - Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl - // Decl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(0)); // Invalid - Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Implicit - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Used - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Referenced - Abv->Add(BitCodeAbbrevOp(0)); // InObjCContainer - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Access - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ModulePrivate - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID - // NamedDecl - Abv->Add(BitCodeAbbrevOp(DeclarationName::Identifier)); // NameKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Identifier - Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber - // ValueDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - // DeclaratorDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerLocStart - Abv->Add(BitCodeAbbrevOp(0)); // HasExtInfo - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType - // FunctionDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 11)); // IDNS - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // StorageClass - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Inline - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InlineSpecified - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ExplicitSpecified - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // VirtualAsWritten - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Pure - Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedProto - Abv->Add(BitCodeAbbrevOp(1)); // HasWrittenProto - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Deleted - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Trivial - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // TrivialForCall - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Defaulted - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ExplicitlyDefaulted - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ImplicitReturnZero - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constexpr - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // UsesSEHTry - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // SkippedBody - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // MultiVersion - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // LateParsed - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // ODRHash - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // TemplateKind - // This Array slurps the rest of the record. Fortunately we want to encode - // (nearly) all the remaining (variable number of) fields in the same way. - // - // This is the function template information if any, then - // NumParams and Params[] from FunctionDecl, and - // NumOverriddenMethods, OverriddenMethods[] from CXXMethodDecl. - // - // Add an AbbrevOp for 'size then elements' and use it here. - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); - DeclCXXMethodAbbrev = Stream.EmitAbbrev(std::move(Abv)); - - // Abbreviation for EXPR_DECL_REF - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::EXPR_DECL_REF)); - //Stmt - //Expr - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind - //DeclRefExpr - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HasQualifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //GetDeclFound - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ExplicitTemplateArgs - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HadMultipleCandidates - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, - 1)); // RefersToEnclosingVariableOrCapture - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location - DeclRefExprAbbrev = Stream.EmitAbbrev(std::move(Abv)); - - // Abbreviation for EXPR_INTEGER_LITERAL - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::EXPR_INTEGER_LITERAL)); - //Stmt - //Expr - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind - //Integer Literal - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location - Abv->Add(BitCodeAbbrevOp(32)); // Bit Width - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Value - IntegerLiteralAbbrev = Stream.EmitAbbrev(std::move(Abv)); - - // Abbreviation for EXPR_CHARACTER_LITERAL - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::EXPR_CHARACTER_LITERAL)); - //Stmt - //Expr - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind - //Character Literal - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getValue - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // getKind - CharacterLiteralAbbrev = Stream.EmitAbbrev(std::move(Abv)); - - // Abbreviation for EXPR_IMPLICIT_CAST - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::EXPR_IMPLICIT_CAST)); - // Stmt - // Expr - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind - // CastExpr - Abv->Add(BitCodeAbbrevOp(0)); // PathSize - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 6)); // CastKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // PartOfExplicitCast - // ImplicitCastExpr - ExprImplicitCastAbbrev = Stream.EmitAbbrev(std::move(Abv)); - - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_LEXICAL)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - DeclContextLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv)); - - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_VISIBLE)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - DeclContextVisibleLookupAbbrev = Stream.EmitAbbrev(std::move(Abv)); -} - -/// isRequiredDecl - Check if this is a "required" Decl, which must be seen by -/// consumers of the AST. -/// -/// Such decls will always be deserialized from the AST file, so we would like -/// this to be as restrictive as possible. Currently the predicate is driven by -/// code generation requirements, if other clients have a different notion of -/// what is "required" then we may have to consider an alternate scheme where -/// clients can iterate over the top-level decls and get information on them, -/// without necessary deserializing them. We could explicitly require such -/// clients to use a separate API call to "realize" the decl. This should be -/// relatively painless since they would presumably only do it for top-level -/// decls. -static bool isRequiredDecl(const Decl *D, ASTContext &Context, - bool WritingModule) { - // An ObjCMethodDecl is never considered as "required" because its - // implementation container always is. - - // File scoped assembly or obj-c or OMP declare target implementation must be - // seen. - if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplDecl>(D)) - return true; - - if (WritingModule && (isa<VarDecl>(D) || isa<ImportDecl>(D))) { - // These declarations are part of the module initializer, and are emitted - // if and when the module is imported, rather than being emitted eagerly. - return false; - } - - return Context.DeclMustBeEmitted(D); -} - -void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { - PrettyDeclStackTraceEntry CrashInfo(Context, D, SourceLocation(), - "serializing"); - - // Determine the ID for this declaration. - serialization::DeclID ID; - assert(!D->isFromASTFile() && "should not be emitting imported decl"); - serialization::DeclID &IDR = DeclIDs[D]; - if (IDR == 0) - IDR = NextDeclID++; - - ID = IDR; - - assert(ID >= FirstDeclID && "invalid decl ID"); - - RecordData Record; - ASTDeclWriter W(*this, Context, Record); - - // Build a record for this declaration - W.Visit(D); - - // Emit this declaration to the bitstream. - uint64_t Offset = W.Emit(D); - - // Record the offset for this declaration - SourceLocation Loc = D->getLocation(); - unsigned Index = ID - FirstDeclID; - if (DeclOffsets.size() == Index) - DeclOffsets.push_back(DeclOffset(Loc, Offset)); - else if (DeclOffsets.size() < Index) { - // FIXME: Can/should this happen? - DeclOffsets.resize(Index+1); - DeclOffsets[Index].setLocation(Loc); - DeclOffsets[Index].BitOffset = Offset; - } else { - llvm_unreachable("declarations should be emitted in ID order"); - } - - SourceManager &SM = Context.getSourceManager(); - if (Loc.isValid() && SM.isLocalSourceLocation(Loc)) - associateDeclWithFile(D, ID); - - // Note declarations that should be deserialized eagerly so that we can add - // them to a record in the AST file later. - if (isRequiredDecl(D, Context, WritingModule)) - EagerlyDeserializedDecls.push_back(ID); -} - -void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) { - // Switch case IDs are per function body. - Writer->ClearSwitchCaseIDs(); - - assert(FD->doesThisDeclarationHaveABody()); - bool ModulesCodegen = false; - if (Writer->WritingModule && !FD->isDependentContext()) { - Optional<GVALinkage> Linkage; - if (Writer->WritingModule->Kind == Module::ModuleInterfaceUnit) { - // When building a C++ Modules TS module interface unit, a strong - // definition in the module interface is provided by the compilation of - // that module interface unit, not by its users. (Inline functions are - // still emitted in module users.) - Linkage = Writer->Context->GetGVALinkageForFunction(FD); - ModulesCodegen = *Linkage == GVA_StrongExternal; - } - if (Writer->Context->getLangOpts().ModulesCodegen) { - // Under -fmodules-codegen, codegen is performed for all non-internal, - // non-always_inline functions. - if (!FD->hasAttr<AlwaysInlineAttr>()) { - if (!Linkage) - Linkage = Writer->Context->GetGVALinkageForFunction(FD); - ModulesCodegen = *Linkage != GVA_Internal; - } - } - } - Record->push_back(ModulesCodegen); - if (ModulesCodegen) - Writer->ModularCodegenDecls.push_back(Writer->GetDeclRef(FD)); - if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) { - Record->push_back(CD->getNumCtorInitializers()); - if (CD->getNumCtorInitializers()) - AddCXXCtorInitializers( - llvm::makeArrayRef(CD->init_begin(), CD->init_end())); - } - AddStmt(FD->getBody()); -} diff --git a/gnu/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp b/gnu/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp deleted file mode 100644 index 6f8b86edcdf..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp +++ /dev/null @@ -1,2368 +0,0 @@ -//===--- ASTWriterStmt.cpp - Statement and Expression Serialization -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// Implements serialization for Statements and Expressions. -/// -//===----------------------------------------------------------------------===// - -#include "clang/Serialization/ASTWriter.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/Lex/Token.h" -#include "llvm/Bitcode/BitstreamWriter.h" -using namespace clang; - -//===----------------------------------------------------------------------===// -// Statement/expression serialization -//===----------------------------------------------------------------------===// - -namespace clang { - - class ASTStmtWriter : public StmtVisitor<ASTStmtWriter, void> { - ASTWriter &Writer; - ASTRecordWriter Record; - - serialization::StmtCode Code; - unsigned AbbrevToUse; - - public: - ASTStmtWriter(ASTWriter &Writer, ASTWriter::RecordData &Record) - : Writer(Writer), Record(Writer, Record), - Code(serialization::STMT_NULL_PTR), AbbrevToUse(0) {} - - ASTStmtWriter(const ASTStmtWriter&) = delete; - - uint64_t Emit() { - assert(Code != serialization::STMT_NULL_PTR && - "unhandled sub-statement writing AST file"); - return Record.EmitStmt(Code, AbbrevToUse); - } - - void AddTemplateKWAndArgsInfo(const ASTTemplateKWAndArgsInfo &ArgInfo, - const TemplateArgumentLoc *Args); - - void VisitStmt(Stmt *S); -#define STMT(Type, Base) \ - void Visit##Type(Type *); -#include "clang/AST/StmtNodes.inc" - }; -} - -void ASTStmtWriter::AddTemplateKWAndArgsInfo( - const ASTTemplateKWAndArgsInfo &ArgInfo, const TemplateArgumentLoc *Args) { - Record.AddSourceLocation(ArgInfo.TemplateKWLoc); - Record.AddSourceLocation(ArgInfo.LAngleLoc); - Record.AddSourceLocation(ArgInfo.RAngleLoc); - for (unsigned i = 0; i != ArgInfo.NumTemplateArgs; ++i) - Record.AddTemplateArgumentLoc(Args[i]); -} - -void ASTStmtWriter::VisitStmt(Stmt *S) { -} - -void ASTStmtWriter::VisitNullStmt(NullStmt *S) { - VisitStmt(S); - Record.AddSourceLocation(S->getSemiLoc()); - Record.push_back(S->NullStmtBits.HasLeadingEmptyMacro); - Code = serialization::STMT_NULL; -} - -void ASTStmtWriter::VisitCompoundStmt(CompoundStmt *S) { - VisitStmt(S); - Record.push_back(S->size()); - for (auto *CS : S->body()) - Record.AddStmt(CS); - Record.AddSourceLocation(S->getLBracLoc()); - Record.AddSourceLocation(S->getRBracLoc()); - Code = serialization::STMT_COMPOUND; -} - -void ASTStmtWriter::VisitSwitchCase(SwitchCase *S) { - VisitStmt(S); - Record.push_back(Writer.getSwitchCaseID(S)); - Record.AddSourceLocation(S->getKeywordLoc()); - Record.AddSourceLocation(S->getColonLoc()); -} - -void ASTStmtWriter::VisitCaseStmt(CaseStmt *S) { - VisitSwitchCase(S); - Record.push_back(S->caseStmtIsGNURange()); - Record.AddStmt(S->getLHS()); - Record.AddStmt(S->getSubStmt()); - if (S->caseStmtIsGNURange()) { - Record.AddStmt(S->getRHS()); - Record.AddSourceLocation(S->getEllipsisLoc()); - } - Code = serialization::STMT_CASE; -} - -void ASTStmtWriter::VisitDefaultStmt(DefaultStmt *S) { - VisitSwitchCase(S); - Record.AddStmt(S->getSubStmt()); - Code = serialization::STMT_DEFAULT; -} - -void ASTStmtWriter::VisitLabelStmt(LabelStmt *S) { - VisitStmt(S); - Record.AddDeclRef(S->getDecl()); - Record.AddStmt(S->getSubStmt()); - Record.AddSourceLocation(S->getIdentLoc()); - Code = serialization::STMT_LABEL; -} - -void ASTStmtWriter::VisitAttributedStmt(AttributedStmt *S) { - VisitStmt(S); - Record.push_back(S->getAttrs().size()); - Record.AddAttributes(S->getAttrs()); - Record.AddStmt(S->getSubStmt()); - Record.AddSourceLocation(S->getAttrLoc()); - Code = serialization::STMT_ATTRIBUTED; -} - -void ASTStmtWriter::VisitIfStmt(IfStmt *S) { - VisitStmt(S); - - bool HasElse = S->getElse() != nullptr; - bool HasVar = S->getConditionVariableDeclStmt() != nullptr; - bool HasInit = S->getInit() != nullptr; - - Record.push_back(S->isConstexpr()); - Record.push_back(HasElse); - Record.push_back(HasVar); - Record.push_back(HasInit); - - Record.AddStmt(S->getCond()); - Record.AddStmt(S->getThen()); - if (HasElse) - Record.AddStmt(S->getElse()); - if (HasVar) - Record.AddDeclRef(S->getConditionVariable()); - if (HasInit) - Record.AddStmt(S->getInit()); - - Record.AddSourceLocation(S->getIfLoc()); - if (HasElse) - Record.AddSourceLocation(S->getElseLoc()); - - Code = serialization::STMT_IF; -} - -void ASTStmtWriter::VisitSwitchStmt(SwitchStmt *S) { - VisitStmt(S); - - bool HasInit = S->getInit() != nullptr; - bool HasVar = S->getConditionVariableDeclStmt() != nullptr; - Record.push_back(HasInit); - Record.push_back(HasVar); - Record.push_back(S->isAllEnumCasesCovered()); - - Record.AddStmt(S->getCond()); - Record.AddStmt(S->getBody()); - if (HasInit) - Record.AddStmt(S->getInit()); - if (HasVar) - Record.AddDeclRef(S->getConditionVariable()); - - Record.AddSourceLocation(S->getSwitchLoc()); - - for (SwitchCase *SC = S->getSwitchCaseList(); SC; - SC = SC->getNextSwitchCase()) - Record.push_back(Writer.RecordSwitchCaseID(SC)); - Code = serialization::STMT_SWITCH; -} - -void ASTStmtWriter::VisitWhileStmt(WhileStmt *S) { - VisitStmt(S); - - bool HasVar = S->getConditionVariableDeclStmt() != nullptr; - Record.push_back(HasVar); - - Record.AddStmt(S->getCond()); - Record.AddStmt(S->getBody()); - if (HasVar) - Record.AddDeclRef(S->getConditionVariable()); - - Record.AddSourceLocation(S->getWhileLoc()); - Code = serialization::STMT_WHILE; -} - -void ASTStmtWriter::VisitDoStmt(DoStmt *S) { - VisitStmt(S); - Record.AddStmt(S->getCond()); - Record.AddStmt(S->getBody()); - Record.AddSourceLocation(S->getDoLoc()); - Record.AddSourceLocation(S->getWhileLoc()); - Record.AddSourceLocation(S->getRParenLoc()); - Code = serialization::STMT_DO; -} - -void ASTStmtWriter::VisitForStmt(ForStmt *S) { - VisitStmt(S); - Record.AddStmt(S->getInit()); - Record.AddStmt(S->getCond()); - Record.AddDeclRef(S->getConditionVariable()); - Record.AddStmt(S->getInc()); - Record.AddStmt(S->getBody()); - Record.AddSourceLocation(S->getForLoc()); - Record.AddSourceLocation(S->getLParenLoc()); - Record.AddSourceLocation(S->getRParenLoc()); - Code = serialization::STMT_FOR; -} - -void ASTStmtWriter::VisitGotoStmt(GotoStmt *S) { - VisitStmt(S); - Record.AddDeclRef(S->getLabel()); - Record.AddSourceLocation(S->getGotoLoc()); - Record.AddSourceLocation(S->getLabelLoc()); - Code = serialization::STMT_GOTO; -} - -void ASTStmtWriter::VisitIndirectGotoStmt(IndirectGotoStmt *S) { - VisitStmt(S); - Record.AddSourceLocation(S->getGotoLoc()); - Record.AddSourceLocation(S->getStarLoc()); - Record.AddStmt(S->getTarget()); - Code = serialization::STMT_INDIRECT_GOTO; -} - -void ASTStmtWriter::VisitContinueStmt(ContinueStmt *S) { - VisitStmt(S); - Record.AddSourceLocation(S->getContinueLoc()); - Code = serialization::STMT_CONTINUE; -} - -void ASTStmtWriter::VisitBreakStmt(BreakStmt *S) { - VisitStmt(S); - Record.AddSourceLocation(S->getBreakLoc()); - Code = serialization::STMT_BREAK; -} - -void ASTStmtWriter::VisitReturnStmt(ReturnStmt *S) { - VisitStmt(S); - - bool HasNRVOCandidate = S->getNRVOCandidate() != nullptr; - Record.push_back(HasNRVOCandidate); - - Record.AddStmt(S->getRetValue()); - if (HasNRVOCandidate) - Record.AddDeclRef(S->getNRVOCandidate()); - - Record.AddSourceLocation(S->getReturnLoc()); - Code = serialization::STMT_RETURN; -} - -void ASTStmtWriter::VisitDeclStmt(DeclStmt *S) { - VisitStmt(S); - Record.AddSourceLocation(S->getBeginLoc()); - Record.AddSourceLocation(S->getEndLoc()); - DeclGroupRef DG = S->getDeclGroup(); - for (DeclGroupRef::iterator D = DG.begin(), DEnd = DG.end(); D != DEnd; ++D) - Record.AddDeclRef(*D); - Code = serialization::STMT_DECL; -} - -void ASTStmtWriter::VisitAsmStmt(AsmStmt *S) { - VisitStmt(S); - Record.push_back(S->getNumOutputs()); - Record.push_back(S->getNumInputs()); - Record.push_back(S->getNumClobbers()); - Record.AddSourceLocation(S->getAsmLoc()); - Record.push_back(S->isVolatile()); - Record.push_back(S->isSimple()); -} - -void ASTStmtWriter::VisitGCCAsmStmt(GCCAsmStmt *S) { - VisitAsmStmt(S); - Record.AddSourceLocation(S->getRParenLoc()); - Record.AddStmt(S->getAsmString()); - - // Outputs - for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) { - Record.AddIdentifierRef(S->getOutputIdentifier(I)); - Record.AddStmt(S->getOutputConstraintLiteral(I)); - Record.AddStmt(S->getOutputExpr(I)); - } - - // Inputs - for (unsigned I = 0, N = S->getNumInputs(); I != N; ++I) { - Record.AddIdentifierRef(S->getInputIdentifier(I)); - Record.AddStmt(S->getInputConstraintLiteral(I)); - Record.AddStmt(S->getInputExpr(I)); - } - - // Clobbers - for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I) - Record.AddStmt(S->getClobberStringLiteral(I)); - - Code = serialization::STMT_GCCASM; -} - -void ASTStmtWriter::VisitMSAsmStmt(MSAsmStmt *S) { - VisitAsmStmt(S); - Record.AddSourceLocation(S->getLBraceLoc()); - Record.AddSourceLocation(S->getEndLoc()); - Record.push_back(S->getNumAsmToks()); - Record.AddString(S->getAsmString()); - - // Tokens - for (unsigned I = 0, N = S->getNumAsmToks(); I != N; ++I) { - // FIXME: Move this to ASTRecordWriter? - Writer.AddToken(S->getAsmToks()[I], Record.getRecordData()); - } - - // Clobbers - for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I) { - Record.AddString(S->getClobber(I)); - } - - // Outputs - for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) { - Record.AddStmt(S->getOutputExpr(I)); - Record.AddString(S->getOutputConstraint(I)); - } - - // Inputs - for (unsigned I = 0, N = S->getNumInputs(); I != N; ++I) { - Record.AddStmt(S->getInputExpr(I)); - Record.AddString(S->getInputConstraint(I)); - } - - Code = serialization::STMT_MSASM; -} - -void ASTStmtWriter::VisitCoroutineBodyStmt(CoroutineBodyStmt *CoroStmt) { - VisitStmt(CoroStmt); - Record.push_back(CoroStmt->getParamMoves().size()); - for (Stmt *S : CoroStmt->children()) - Record.AddStmt(S); - Code = serialization::STMT_COROUTINE_BODY; -} - -void ASTStmtWriter::VisitCoreturnStmt(CoreturnStmt *S) { - VisitStmt(S); - Record.AddSourceLocation(S->getKeywordLoc()); - Record.AddStmt(S->getOperand()); - Record.AddStmt(S->getPromiseCall()); - Record.push_back(S->isImplicit()); - Code = serialization::STMT_CORETURN; -} - -void ASTStmtWriter::VisitCoroutineSuspendExpr(CoroutineSuspendExpr *E) { - VisitExpr(E); - Record.AddSourceLocation(E->getKeywordLoc()); - for (Stmt *S : E->children()) - Record.AddStmt(S); - Record.AddStmt(E->getOpaqueValue()); -} - -void ASTStmtWriter::VisitCoawaitExpr(CoawaitExpr *E) { - VisitCoroutineSuspendExpr(E); - Record.push_back(E->isImplicit()); - Code = serialization::EXPR_COAWAIT; -} - -void ASTStmtWriter::VisitCoyieldExpr(CoyieldExpr *E) { - VisitCoroutineSuspendExpr(E); - Code = serialization::EXPR_COYIELD; -} - -void ASTStmtWriter::VisitDependentCoawaitExpr(DependentCoawaitExpr *E) { - VisitExpr(E); - Record.AddSourceLocation(E->getKeywordLoc()); - for (Stmt *S : E->children()) - Record.AddStmt(S); - Code = serialization::EXPR_DEPENDENT_COAWAIT; -} - -void ASTStmtWriter::VisitCapturedStmt(CapturedStmt *S) { - VisitStmt(S); - // NumCaptures - Record.push_back(std::distance(S->capture_begin(), S->capture_end())); - - // CapturedDecl and captured region kind - Record.AddDeclRef(S->getCapturedDecl()); - Record.push_back(S->getCapturedRegionKind()); - - Record.AddDeclRef(S->getCapturedRecordDecl()); - - // Capture inits - for (auto *I : S->capture_inits()) - Record.AddStmt(I); - - // Body - Record.AddStmt(S->getCapturedStmt()); - - // Captures - for (const auto &I : S->captures()) { - if (I.capturesThis() || I.capturesVariableArrayType()) - Record.AddDeclRef(nullptr); - else - Record.AddDeclRef(I.getCapturedVar()); - Record.push_back(I.getCaptureKind()); - Record.AddSourceLocation(I.getLocation()); - } - - Code = serialization::STMT_CAPTURED; -} - -void ASTStmtWriter::VisitExpr(Expr *E) { - VisitStmt(E); - Record.AddTypeRef(E->getType()); - Record.push_back(E->isTypeDependent()); - Record.push_back(E->isValueDependent()); - Record.push_back(E->isInstantiationDependent()); - Record.push_back(E->containsUnexpandedParameterPack()); - Record.push_back(E->getValueKind()); - Record.push_back(E->getObjectKind()); -} - -void ASTStmtWriter::VisitConstantExpr(ConstantExpr *E) { - VisitExpr(E); - Record.AddStmt(E->getSubExpr()); - Code = serialization::EXPR_CONSTANT; -} - -void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) { - VisitExpr(E); - - bool HasFunctionName = E->getFunctionName() != nullptr; - Record.push_back(HasFunctionName); - Record.push_back(E->getIdentKind()); // FIXME: stable encoding - Record.AddSourceLocation(E->getLocation()); - if (HasFunctionName) - Record.AddStmt(E->getFunctionName()); - Code = serialization::EXPR_PREDEFINED; -} - -void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { - VisitExpr(E); - - Record.push_back(E->hasQualifier()); - Record.push_back(E->getDecl() != E->getFoundDecl()); - Record.push_back(E->hasTemplateKWAndArgsInfo()); - Record.push_back(E->hadMultipleCandidates()); - Record.push_back(E->refersToEnclosingVariableOrCapture()); - - if (E->hasTemplateKWAndArgsInfo()) { - unsigned NumTemplateArgs = E->getNumTemplateArgs(); - Record.push_back(NumTemplateArgs); - } - - DeclarationName::NameKind nk = (E->getDecl()->getDeclName().getNameKind()); - - if ((!E->hasTemplateKWAndArgsInfo()) && (!E->hasQualifier()) && - (E->getDecl() == E->getFoundDecl()) && - nk == DeclarationName::Identifier) { - AbbrevToUse = Writer.getDeclRefExprAbbrev(); - } - - if (E->hasQualifier()) - Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); - - if (E->getDecl() != E->getFoundDecl()) - Record.AddDeclRef(E->getFoundDecl()); - - if (E->hasTemplateKWAndArgsInfo()) - AddTemplateKWAndArgsInfo(*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(), - E->getTrailingObjects<TemplateArgumentLoc>()); - - Record.AddDeclRef(E->getDecl()); - Record.AddSourceLocation(E->getLocation()); - Record.AddDeclarationNameLoc(E->DNLoc, E->getDecl()->getDeclName()); - Code = serialization::EXPR_DECL_REF; -} - -void ASTStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) { - VisitExpr(E); - Record.AddSourceLocation(E->getLocation()); - Record.AddAPInt(E->getValue()); - - if (E->getValue().getBitWidth() == 32) { - AbbrevToUse = Writer.getIntegerLiteralAbbrev(); - } - - Code = serialization::EXPR_INTEGER_LITERAL; -} - -void ASTStmtWriter::VisitFixedPointLiteral(FixedPointLiteral *E) { - VisitExpr(E); - Record.AddSourceLocation(E->getLocation()); - Record.AddAPInt(E->getValue()); - Code = serialization::EXPR_INTEGER_LITERAL; -} - -void ASTStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) { - VisitExpr(E); - Record.push_back(E->getRawSemantics()); - Record.push_back(E->isExact()); - Record.AddAPFloat(E->getValue()); - Record.AddSourceLocation(E->getLocation()); - Code = serialization::EXPR_FLOATING_LITERAL; -} - -void ASTStmtWriter::VisitImaginaryLiteral(ImaginaryLiteral *E) { - VisitExpr(E); - Record.AddStmt(E->getSubExpr()); - Code = serialization::EXPR_IMAGINARY_LITERAL; -} - -void ASTStmtWriter::VisitStringLiteral(StringLiteral *E) { - VisitExpr(E); - - // Store the various bits of data of StringLiteral. - Record.push_back(E->getNumConcatenated()); - Record.push_back(E->getLength()); - Record.push_back(E->getCharByteWidth()); - Record.push_back(E->getKind()); - Record.push_back(E->isPascal()); - - // Store the trailing array of SourceLocation. - for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I) - Record.AddSourceLocation(E->getStrTokenLoc(I)); - - // Store the trailing array of char holding the string data. - StringRef StrData = E->getBytes(); - for (unsigned I = 0, N = E->getByteLength(); I != N; ++I) - Record.push_back(StrData[I]); - - Code = serialization::EXPR_STRING_LITERAL; -} - -void ASTStmtWriter::VisitCharacterLiteral(CharacterLiteral *E) { - VisitExpr(E); - Record.push_back(E->getValue()); - Record.AddSourceLocation(E->getLocation()); - Record.push_back(E->getKind()); - - AbbrevToUse = Writer.getCharacterLiteralAbbrev(); - - Code = serialization::EXPR_CHARACTER_LITERAL; -} - -void ASTStmtWriter::VisitParenExpr(ParenExpr *E) { - VisitExpr(E); - Record.AddSourceLocation(E->getLParen()); - Record.AddSourceLocation(E->getRParen()); - Record.AddStmt(E->getSubExpr()); - Code = serialization::EXPR_PAREN; -} - -void ASTStmtWriter::VisitParenListExpr(ParenListExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumExprs()); - for (auto *SubStmt : E->exprs()) - Record.AddStmt(SubStmt); - Record.AddSourceLocation(E->getLParenLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Code = serialization::EXPR_PAREN_LIST; -} - -void ASTStmtWriter::VisitUnaryOperator(UnaryOperator *E) { - VisitExpr(E); - Record.AddStmt(E->getSubExpr()); - Record.push_back(E->getOpcode()); // FIXME: stable encoding - Record.AddSourceLocation(E->getOperatorLoc()); - Record.push_back(E->canOverflow()); - Code = serialization::EXPR_UNARY_OPERATOR; -} - -void ASTStmtWriter::VisitOffsetOfExpr(OffsetOfExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumComponents()); - Record.push_back(E->getNumExpressions()); - Record.AddSourceLocation(E->getOperatorLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Record.AddTypeSourceInfo(E->getTypeSourceInfo()); - for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) { - const OffsetOfNode &ON = E->getComponent(I); - Record.push_back(ON.getKind()); // FIXME: Stable encoding - Record.AddSourceLocation(ON.getSourceRange().getBegin()); - Record.AddSourceLocation(ON.getSourceRange().getEnd()); - switch (ON.getKind()) { - case OffsetOfNode::Array: - Record.push_back(ON.getArrayExprIndex()); - break; - - case OffsetOfNode::Field: - Record.AddDeclRef(ON.getField()); - break; - - case OffsetOfNode::Identifier: - Record.AddIdentifierRef(ON.getFieldName()); - break; - - case OffsetOfNode::Base: - Record.AddCXXBaseSpecifier(*ON.getBase()); - break; - } - } - for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I) - Record.AddStmt(E->getIndexExpr(I)); - Code = serialization::EXPR_OFFSETOF; -} - -void ASTStmtWriter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { - VisitExpr(E); - Record.push_back(E->getKind()); - if (E->isArgumentType()) - Record.AddTypeSourceInfo(E->getArgumentTypeInfo()); - else { - Record.push_back(0); - Record.AddStmt(E->getArgumentExpr()); - } - Record.AddSourceLocation(E->getOperatorLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Code = serialization::EXPR_SIZEOF_ALIGN_OF; -} - -void ASTStmtWriter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { - VisitExpr(E); - Record.AddStmt(E->getLHS()); - Record.AddStmt(E->getRHS()); - Record.AddSourceLocation(E->getRBracketLoc()); - Code = serialization::EXPR_ARRAY_SUBSCRIPT; -} - -void ASTStmtWriter::VisitOMPArraySectionExpr(OMPArraySectionExpr *E) { - VisitExpr(E); - Record.AddStmt(E->getBase()); - Record.AddStmt(E->getLowerBound()); - Record.AddStmt(E->getLength()); - Record.AddSourceLocation(E->getColonLoc()); - Record.AddSourceLocation(E->getRBracketLoc()); - Code = serialization::EXPR_OMP_ARRAY_SECTION; -} - -void ASTStmtWriter::VisitCallExpr(CallExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumArgs()); - Record.AddSourceLocation(E->getRParenLoc()); - Record.AddStmt(E->getCallee()); - for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end(); - Arg != ArgEnd; ++Arg) - Record.AddStmt(*Arg); - Record.push_back(static_cast<unsigned>(E->getADLCallKind())); - Code = serialization::EXPR_CALL; -} - -void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { - // Don't call VisitExpr, we'll write everything here. - - Record.push_back(E->hasQualifier()); - if (E->hasQualifier()) - Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); - - Record.push_back(E->hasTemplateKWAndArgsInfo()); - if (E->hasTemplateKWAndArgsInfo()) { - Record.AddSourceLocation(E->getTemplateKeywordLoc()); - unsigned NumTemplateArgs = E->getNumTemplateArgs(); - Record.push_back(NumTemplateArgs); - Record.AddSourceLocation(E->getLAngleLoc()); - Record.AddSourceLocation(E->getRAngleLoc()); - for (unsigned i=0; i != NumTemplateArgs; ++i) - Record.AddTemplateArgumentLoc(E->getTemplateArgs()[i]); - } - - Record.push_back(E->hadMultipleCandidates()); - - DeclAccessPair FoundDecl = E->getFoundDecl(); - Record.AddDeclRef(FoundDecl.getDecl()); - Record.push_back(FoundDecl.getAccess()); - - Record.AddTypeRef(E->getType()); - Record.push_back(E->getValueKind()); - Record.push_back(E->getObjectKind()); - Record.AddStmt(E->getBase()); - Record.AddDeclRef(E->getMemberDecl()); - Record.AddSourceLocation(E->getMemberLoc()); - Record.push_back(E->isArrow()); - Record.AddSourceLocation(E->getOperatorLoc()); - Record.AddDeclarationNameLoc(E->MemberDNLoc, - E->getMemberDecl()->getDeclName()); - Code = serialization::EXPR_MEMBER; -} - -void ASTStmtWriter::VisitObjCIsaExpr(ObjCIsaExpr *E) { - VisitExpr(E); - Record.AddStmt(E->getBase()); - Record.AddSourceLocation(E->getIsaMemberLoc()); - Record.AddSourceLocation(E->getOpLoc()); - Record.push_back(E->isArrow()); - Code = serialization::EXPR_OBJC_ISA; -} - -void ASTStmtWriter:: -VisitObjCIndirectCopyRestoreExpr(ObjCIndirectCopyRestoreExpr *E) { - VisitExpr(E); - Record.AddStmt(E->getSubExpr()); - Record.push_back(E->shouldCopy()); - Code = serialization::EXPR_OBJC_INDIRECT_COPY_RESTORE; -} - -void ASTStmtWriter::VisitObjCBridgedCastExpr(ObjCBridgedCastExpr *E) { - VisitExplicitCastExpr(E); - Record.AddSourceLocation(E->getLParenLoc()); - Record.AddSourceLocation(E->getBridgeKeywordLoc()); - Record.push_back(E->getBridgeKind()); // FIXME: Stable encoding - Code = serialization::EXPR_OBJC_BRIDGED_CAST; -} - -void ASTStmtWriter::VisitCastExpr(CastExpr *E) { - VisitExpr(E); - Record.push_back(E->path_size()); - Record.AddStmt(E->getSubExpr()); - Record.push_back(E->getCastKind()); // FIXME: stable encoding - - for (CastExpr::path_iterator - PI = E->path_begin(), PE = E->path_end(); PI != PE; ++PI) - Record.AddCXXBaseSpecifier(**PI); -} - -void ASTStmtWriter::VisitBinaryOperator(BinaryOperator *E) { - VisitExpr(E); - Record.AddStmt(E->getLHS()); - Record.AddStmt(E->getRHS()); - Record.push_back(E->getOpcode()); // FIXME: stable encoding - Record.AddSourceLocation(E->getOperatorLoc()); - Record.push_back(E->getFPFeatures().getInt()); - Code = serialization::EXPR_BINARY_OPERATOR; -} - -void ASTStmtWriter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { - VisitBinaryOperator(E); - Record.AddTypeRef(E->getComputationLHSType()); - Record.AddTypeRef(E->getComputationResultType()); - Code = serialization::EXPR_COMPOUND_ASSIGN_OPERATOR; -} - -void ASTStmtWriter::VisitConditionalOperator(ConditionalOperator *E) { - VisitExpr(E); - Record.AddStmt(E->getCond()); - Record.AddStmt(E->getLHS()); - Record.AddStmt(E->getRHS()); - Record.AddSourceLocation(E->getQuestionLoc()); - Record.AddSourceLocation(E->getColonLoc()); - Code = serialization::EXPR_CONDITIONAL_OPERATOR; -} - -void -ASTStmtWriter::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { - VisitExpr(E); - Record.AddStmt(E->getOpaqueValue()); - Record.AddStmt(E->getCommon()); - Record.AddStmt(E->getCond()); - Record.AddStmt(E->getTrueExpr()); - Record.AddStmt(E->getFalseExpr()); - Record.AddSourceLocation(E->getQuestionLoc()); - Record.AddSourceLocation(E->getColonLoc()); - Code = serialization::EXPR_BINARY_CONDITIONAL_OPERATOR; -} - -void ASTStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) { - VisitCastExpr(E); - Record.push_back(E->isPartOfExplicitCast()); - - if (E->path_size() == 0) - AbbrevToUse = Writer.getExprImplicitCastAbbrev(); - - Code = serialization::EXPR_IMPLICIT_CAST; -} - -void ASTStmtWriter::VisitExplicitCastExpr(ExplicitCastExpr *E) { - VisitCastExpr(E); - Record.AddTypeSourceInfo(E->getTypeInfoAsWritten()); -} - -void ASTStmtWriter::VisitCStyleCastExpr(CStyleCastExpr *E) { - VisitExplicitCastExpr(E); - Record.AddSourceLocation(E->getLParenLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Code = serialization::EXPR_CSTYLE_CAST; -} - -void ASTStmtWriter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { - VisitExpr(E); - Record.AddSourceLocation(E->getLParenLoc()); - Record.AddTypeSourceInfo(E->getTypeSourceInfo()); - Record.AddStmt(E->getInitializer()); - Record.push_back(E->isFileScope()); - Code = serialization::EXPR_COMPOUND_LITERAL; -} - -void ASTStmtWriter::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { - VisitExpr(E); - Record.AddStmt(E->getBase()); - Record.AddIdentifierRef(&E->getAccessor()); - Record.AddSourceLocation(E->getAccessorLoc()); - Code = serialization::EXPR_EXT_VECTOR_ELEMENT; -} - -void ASTStmtWriter::VisitInitListExpr(InitListExpr *E) { - VisitExpr(E); - // NOTE: only add the (possibly null) syntactic form. - // No need to serialize the isSemanticForm flag and the semantic form. - Record.AddStmt(E->getSyntacticForm()); - Record.AddSourceLocation(E->getLBraceLoc()); - Record.AddSourceLocation(E->getRBraceLoc()); - bool isArrayFiller = E->ArrayFillerOrUnionFieldInit.is<Expr*>(); - Record.push_back(isArrayFiller); - if (isArrayFiller) - Record.AddStmt(E->getArrayFiller()); - else - Record.AddDeclRef(E->getInitializedFieldInUnion()); - Record.push_back(E->hadArrayRangeDesignator()); - Record.push_back(E->getNumInits()); - if (isArrayFiller) { - // ArrayFiller may have filled "holes" due to designated initializer. - // Replace them by 0 to indicate that the filler goes in that place. - Expr *filler = E->getArrayFiller(); - for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) - Record.AddStmt(E->getInit(I) != filler ? E->getInit(I) : nullptr); - } else { - for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) - Record.AddStmt(E->getInit(I)); - } - Code = serialization::EXPR_INIT_LIST; -} - -void ASTStmtWriter::VisitDesignatedInitExpr(DesignatedInitExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumSubExprs()); - for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) - Record.AddStmt(E->getSubExpr(I)); - Record.AddSourceLocation(E->getEqualOrColonLoc()); - Record.push_back(E->usesGNUSyntax()); - for (const DesignatedInitExpr::Designator &D : E->designators()) { - if (D.isFieldDesignator()) { - if (FieldDecl *Field = D.getField()) { - Record.push_back(serialization::DESIG_FIELD_DECL); - Record.AddDeclRef(Field); - } else { - Record.push_back(serialization::DESIG_FIELD_NAME); - Record.AddIdentifierRef(D.getFieldName()); - } - Record.AddSourceLocation(D.getDotLoc()); - Record.AddSourceLocation(D.getFieldLoc()); - } else if (D.isArrayDesignator()) { - Record.push_back(serialization::DESIG_ARRAY); - Record.push_back(D.getFirstExprIndex()); - Record.AddSourceLocation(D.getLBracketLoc()); - Record.AddSourceLocation(D.getRBracketLoc()); - } else { - assert(D.isArrayRangeDesignator() && "Unknown designator"); - Record.push_back(serialization::DESIG_ARRAY_RANGE); - Record.push_back(D.getFirstExprIndex()); - Record.AddSourceLocation(D.getLBracketLoc()); - Record.AddSourceLocation(D.getEllipsisLoc()); - Record.AddSourceLocation(D.getRBracketLoc()); - } - } - Code = serialization::EXPR_DESIGNATED_INIT; -} - -void ASTStmtWriter::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) { - VisitExpr(E); - Record.AddStmt(E->getBase()); - Record.AddStmt(E->getUpdater()); - Code = serialization::EXPR_DESIGNATED_INIT_UPDATE; -} - -void ASTStmtWriter::VisitNoInitExpr(NoInitExpr *E) { - VisitExpr(E); - Code = serialization::EXPR_NO_INIT; -} - -void ASTStmtWriter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) { - VisitExpr(E); - Record.AddStmt(E->SubExprs[0]); - Record.AddStmt(E->SubExprs[1]); - Code = serialization::EXPR_ARRAY_INIT_LOOP; -} - -void ASTStmtWriter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) { - VisitExpr(E); - Code = serialization::EXPR_ARRAY_INIT_INDEX; -} - -void ASTStmtWriter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { - VisitExpr(E); - Code = serialization::EXPR_IMPLICIT_VALUE_INIT; -} - -void ASTStmtWriter::VisitVAArgExpr(VAArgExpr *E) { - VisitExpr(E); - Record.AddStmt(E->getSubExpr()); - Record.AddTypeSourceInfo(E->getWrittenTypeInfo()); - Record.AddSourceLocation(E->getBuiltinLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Record.push_back(E->isMicrosoftABI()); - Code = serialization::EXPR_VA_ARG; -} - -void ASTStmtWriter::VisitAddrLabelExpr(AddrLabelExpr *E) { - VisitExpr(E); - Record.AddSourceLocation(E->getAmpAmpLoc()); - Record.AddSourceLocation(E->getLabelLoc()); - Record.AddDeclRef(E->getLabel()); - Code = serialization::EXPR_ADDR_LABEL; -} - -void ASTStmtWriter::VisitStmtExpr(StmtExpr *E) { - VisitExpr(E); - Record.AddStmt(E->getSubStmt()); - Record.AddSourceLocation(E->getLParenLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Code = serialization::EXPR_STMT; -} - -void ASTStmtWriter::VisitChooseExpr(ChooseExpr *E) { - VisitExpr(E); - Record.AddStmt(E->getCond()); - Record.AddStmt(E->getLHS()); - Record.AddStmt(E->getRHS()); - Record.AddSourceLocation(E->getBuiltinLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Record.push_back(E->isConditionDependent() ? false : E->isConditionTrue()); - Code = serialization::EXPR_CHOOSE; -} - -void ASTStmtWriter::VisitGNUNullExpr(GNUNullExpr *E) { - VisitExpr(E); - Record.AddSourceLocation(E->getTokenLocation()); - Code = serialization::EXPR_GNU_NULL; -} - -void ASTStmtWriter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumSubExprs()); - for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) - Record.AddStmt(E->getExpr(I)); - Record.AddSourceLocation(E->getBuiltinLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Code = serialization::EXPR_SHUFFLE_VECTOR; -} - -void ASTStmtWriter::VisitConvertVectorExpr(ConvertVectorExpr *E) { - VisitExpr(E); - Record.AddSourceLocation(E->getBuiltinLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Record.AddTypeSourceInfo(E->getTypeSourceInfo()); - Record.AddStmt(E->getSrcExpr()); - Code = serialization::EXPR_CONVERT_VECTOR; -} - -void ASTStmtWriter::VisitBlockExpr(BlockExpr *E) { - VisitExpr(E); - Record.AddDeclRef(E->getBlockDecl()); - Code = serialization::EXPR_BLOCK; -} - -void ASTStmtWriter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumAssocs()); - - Record.AddStmt(E->getControllingExpr()); - for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) { - Record.AddTypeSourceInfo(E->getAssocTypeSourceInfo(I)); - Record.AddStmt(E->getAssocExpr(I)); - } - Record.push_back(E->isResultDependent() ? -1U : E->getResultIndex()); - - Record.AddSourceLocation(E->getGenericLoc()); - Record.AddSourceLocation(E->getDefaultLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Code = serialization::EXPR_GENERIC_SELECTION; -} - -void ASTStmtWriter::VisitPseudoObjectExpr(PseudoObjectExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumSemanticExprs()); - - // Push the result index. Currently, this needs to exactly match - // the encoding used internally for ResultIndex. - unsigned result = E->getResultExprIndex(); - result = (result == PseudoObjectExpr::NoResult ? 0 : result + 1); - Record.push_back(result); - - Record.AddStmt(E->getSyntacticForm()); - for (PseudoObjectExpr::semantics_iterator - i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) { - Record.AddStmt(*i); - } - Code = serialization::EXPR_PSEUDO_OBJECT; -} - -void ASTStmtWriter::VisitAtomicExpr(AtomicExpr *E) { - VisitExpr(E); - Record.push_back(E->getOp()); - for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) - Record.AddStmt(E->getSubExprs()[I]); - Record.AddSourceLocation(E->getBuiltinLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Code = serialization::EXPR_ATOMIC; -} - -//===----------------------------------------------------------------------===// -// Objective-C Expressions and Statements. -//===----------------------------------------------------------------------===// - -void ASTStmtWriter::VisitObjCStringLiteral(ObjCStringLiteral *E) { - VisitExpr(E); - Record.AddStmt(E->getString()); - Record.AddSourceLocation(E->getAtLoc()); - Code = serialization::EXPR_OBJC_STRING_LITERAL; -} - -void ASTStmtWriter::VisitObjCBoxedExpr(ObjCBoxedExpr *E) { - VisitExpr(E); - Record.AddStmt(E->getSubExpr()); - Record.AddDeclRef(E->getBoxingMethod()); - Record.AddSourceRange(E->getSourceRange()); - Code = serialization::EXPR_OBJC_BOXED_EXPRESSION; -} - -void ASTStmtWriter::VisitObjCArrayLiteral(ObjCArrayLiteral *E) { - VisitExpr(E); - Record.push_back(E->getNumElements()); - for (unsigned i = 0; i < E->getNumElements(); i++) - Record.AddStmt(E->getElement(i)); - Record.AddDeclRef(E->getArrayWithObjectsMethod()); - Record.AddSourceRange(E->getSourceRange()); - Code = serialization::EXPR_OBJC_ARRAY_LITERAL; -} - -void ASTStmtWriter::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { - VisitExpr(E); - Record.push_back(E->getNumElements()); - Record.push_back(E->HasPackExpansions); - for (unsigned i = 0; i < E->getNumElements(); i++) { - ObjCDictionaryElement Element = E->getKeyValueElement(i); - Record.AddStmt(Element.Key); - Record.AddStmt(Element.Value); - if (E->HasPackExpansions) { - Record.AddSourceLocation(Element.EllipsisLoc); - unsigned NumExpansions = 0; - if (Element.NumExpansions) - NumExpansions = *Element.NumExpansions + 1; - Record.push_back(NumExpansions); - } - } - - Record.AddDeclRef(E->getDictWithObjectsMethod()); - Record.AddSourceRange(E->getSourceRange()); - Code = serialization::EXPR_OBJC_DICTIONARY_LITERAL; -} - -void ASTStmtWriter::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { - VisitExpr(E); - Record.AddTypeSourceInfo(E->getEncodedTypeSourceInfo()); - Record.AddSourceLocation(E->getAtLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Code = serialization::EXPR_OBJC_ENCODE; -} - -void ASTStmtWriter::VisitObjCSelectorExpr(ObjCSelectorExpr *E) { - VisitExpr(E); - Record.AddSelectorRef(E->getSelector()); - Record.AddSourceLocation(E->getAtLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Code = serialization::EXPR_OBJC_SELECTOR_EXPR; -} - -void ASTStmtWriter::VisitObjCProtocolExpr(ObjCProtocolExpr *E) { - VisitExpr(E); - Record.AddDeclRef(E->getProtocol()); - Record.AddSourceLocation(E->getAtLoc()); - Record.AddSourceLocation(E->ProtoLoc); - Record.AddSourceLocation(E->getRParenLoc()); - Code = serialization::EXPR_OBJC_PROTOCOL_EXPR; -} - -void ASTStmtWriter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { - VisitExpr(E); - Record.AddDeclRef(E->getDecl()); - Record.AddSourceLocation(E->getLocation()); - Record.AddSourceLocation(E->getOpLoc()); - Record.AddStmt(E->getBase()); - Record.push_back(E->isArrow()); - Record.push_back(E->isFreeIvar()); - Code = serialization::EXPR_OBJC_IVAR_REF_EXPR; -} - -void ASTStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { - VisitExpr(E); - Record.push_back(E->SetterAndMethodRefFlags.getInt()); - Record.push_back(E->isImplicitProperty()); - if (E->isImplicitProperty()) { - Record.AddDeclRef(E->getImplicitPropertyGetter()); - Record.AddDeclRef(E->getImplicitPropertySetter()); - } else { - Record.AddDeclRef(E->getExplicitProperty()); - } - Record.AddSourceLocation(E->getLocation()); - Record.AddSourceLocation(E->getReceiverLocation()); - if (E->isObjectReceiver()) { - Record.push_back(0); - Record.AddStmt(E->getBase()); - } else if (E->isSuperReceiver()) { - Record.push_back(1); - Record.AddTypeRef(E->getSuperReceiverType()); - } else { - Record.push_back(2); - Record.AddDeclRef(E->getClassReceiver()); - } - - Code = serialization::EXPR_OBJC_PROPERTY_REF_EXPR; -} - -void ASTStmtWriter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *E) { - VisitExpr(E); - Record.AddSourceLocation(E->getRBracket()); - Record.AddStmt(E->getBaseExpr()); - Record.AddStmt(E->getKeyExpr()); - Record.AddDeclRef(E->getAtIndexMethodDecl()); - Record.AddDeclRef(E->setAtIndexMethodDecl()); - - Code = serialization::EXPR_OBJC_SUBSCRIPT_REF_EXPR; -} - -void ASTStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumArgs()); - Record.push_back(E->getNumStoredSelLocs()); - Record.push_back(E->SelLocsKind); - Record.push_back(E->isDelegateInitCall()); - Record.push_back(E->IsImplicit); - Record.push_back((unsigned)E->getReceiverKind()); // FIXME: stable encoding - switch (E->getReceiverKind()) { - case ObjCMessageExpr::Instance: - Record.AddStmt(E->getInstanceReceiver()); - break; - - case ObjCMessageExpr::Class: - Record.AddTypeSourceInfo(E->getClassReceiverTypeInfo()); - break; - - case ObjCMessageExpr::SuperClass: - case ObjCMessageExpr::SuperInstance: - Record.AddTypeRef(E->getSuperType()); - Record.AddSourceLocation(E->getSuperLoc()); - break; - } - - if (E->getMethodDecl()) { - Record.push_back(1); - Record.AddDeclRef(E->getMethodDecl()); - } else { - Record.push_back(0); - Record.AddSelectorRef(E->getSelector()); - } - - Record.AddSourceLocation(E->getLeftLoc()); - Record.AddSourceLocation(E->getRightLoc()); - - for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end(); - Arg != ArgEnd; ++Arg) - Record.AddStmt(*Arg); - - SourceLocation *Locs = E->getStoredSelLocs(); - for (unsigned i = 0, e = E->getNumStoredSelLocs(); i != e; ++i) - Record.AddSourceLocation(Locs[i]); - - Code = serialization::EXPR_OBJC_MESSAGE_EXPR; -} - -void ASTStmtWriter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { - VisitStmt(S); - Record.AddStmt(S->getElement()); - Record.AddStmt(S->getCollection()); - Record.AddStmt(S->getBody()); - Record.AddSourceLocation(S->getForLoc()); - Record.AddSourceLocation(S->getRParenLoc()); - Code = serialization::STMT_OBJC_FOR_COLLECTION; -} - -void ASTStmtWriter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { - Record.AddStmt(S->getCatchBody()); - Record.AddDeclRef(S->getCatchParamDecl()); - Record.AddSourceLocation(S->getAtCatchLoc()); - Record.AddSourceLocation(S->getRParenLoc()); - Code = serialization::STMT_OBJC_CATCH; -} - -void ASTStmtWriter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { - Record.AddStmt(S->getFinallyBody()); - Record.AddSourceLocation(S->getAtFinallyLoc()); - Code = serialization::STMT_OBJC_FINALLY; -} - -void ASTStmtWriter::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) { - Record.AddStmt(S->getSubStmt()); - Record.AddSourceLocation(S->getAtLoc()); - Code = serialization::STMT_OBJC_AUTORELEASE_POOL; -} - -void ASTStmtWriter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { - Record.push_back(S->getNumCatchStmts()); - Record.push_back(S->getFinallyStmt() != nullptr); - Record.AddStmt(S->getTryBody()); - for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) - Record.AddStmt(S->getCatchStmt(I)); - if (S->getFinallyStmt()) - Record.AddStmt(S->getFinallyStmt()); - Record.AddSourceLocation(S->getAtTryLoc()); - Code = serialization::STMT_OBJC_AT_TRY; -} - -void ASTStmtWriter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { - Record.AddStmt(S->getSynchExpr()); - Record.AddStmt(S->getSynchBody()); - Record.AddSourceLocation(S->getAtSynchronizedLoc()); - Code = serialization::STMT_OBJC_AT_SYNCHRONIZED; -} - -void ASTStmtWriter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { - Record.AddStmt(S->getThrowExpr()); - Record.AddSourceLocation(S->getThrowLoc()); - Code = serialization::STMT_OBJC_AT_THROW; -} - -void ASTStmtWriter::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *E) { - VisitExpr(E); - Record.push_back(E->getValue()); - Record.AddSourceLocation(E->getLocation()); - Code = serialization::EXPR_OBJC_BOOL_LITERAL; -} - -void ASTStmtWriter::VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) { - VisitExpr(E); - Record.AddSourceRange(E->getSourceRange()); - Record.AddVersionTuple(E->getVersion()); - Code = serialization::EXPR_OBJC_AVAILABILITY_CHECK; -} - -//===----------------------------------------------------------------------===// -// C++ Expressions and Statements. -//===----------------------------------------------------------------------===// - -void ASTStmtWriter::VisitCXXCatchStmt(CXXCatchStmt *S) { - VisitStmt(S); - Record.AddSourceLocation(S->getCatchLoc()); - Record.AddDeclRef(S->getExceptionDecl()); - Record.AddStmt(S->getHandlerBlock()); - Code = serialization::STMT_CXX_CATCH; -} - -void ASTStmtWriter::VisitCXXTryStmt(CXXTryStmt *S) { - VisitStmt(S); - Record.push_back(S->getNumHandlers()); - Record.AddSourceLocation(S->getTryLoc()); - Record.AddStmt(S->getTryBlock()); - for (unsigned i = 0, e = S->getNumHandlers(); i != e; ++i) - Record.AddStmt(S->getHandler(i)); - Code = serialization::STMT_CXX_TRY; -} - -void ASTStmtWriter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { - VisitStmt(S); - Record.AddSourceLocation(S->getForLoc()); - Record.AddSourceLocation(S->getCoawaitLoc()); - Record.AddSourceLocation(S->getColonLoc()); - Record.AddSourceLocation(S->getRParenLoc()); - Record.AddStmt(S->getInit()); - Record.AddStmt(S->getRangeStmt()); - Record.AddStmt(S->getBeginStmt()); - Record.AddStmt(S->getEndStmt()); - Record.AddStmt(S->getCond()); - Record.AddStmt(S->getInc()); - Record.AddStmt(S->getLoopVarStmt()); - Record.AddStmt(S->getBody()); - Code = serialization::STMT_CXX_FOR_RANGE; -} - -void ASTStmtWriter::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) { - VisitStmt(S); - Record.AddSourceLocation(S->getKeywordLoc()); - Record.push_back(S->isIfExists()); - Record.AddNestedNameSpecifierLoc(S->getQualifierLoc()); - Record.AddDeclarationNameInfo(S->getNameInfo()); - Record.AddStmt(S->getSubStmt()); - Code = serialization::STMT_MS_DEPENDENT_EXISTS; -} - -void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { - VisitCallExpr(E); - Record.push_back(E->getOperator()); - Record.push_back(E->getFPFeatures().getInt()); - Record.AddSourceRange(E->Range); - Code = serialization::EXPR_CXX_OPERATOR_CALL; -} - -void ASTStmtWriter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { - VisitCallExpr(E); - Code = serialization::EXPR_CXX_MEMBER_CALL; -} - -void ASTStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) { - VisitExpr(E); - - Record.push_back(E->getNumArgs()); - Record.push_back(E->isElidable()); - Record.push_back(E->hadMultipleCandidates()); - Record.push_back(E->isListInitialization()); - Record.push_back(E->isStdInitListInitialization()); - Record.push_back(E->requiresZeroInitialization()); - Record.push_back(E->getConstructionKind()); // FIXME: stable encoding - Record.AddSourceLocation(E->getLocation()); - Record.AddDeclRef(E->getConstructor()); - Record.AddSourceRange(E->getParenOrBraceRange()); - - for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) - Record.AddStmt(E->getArg(I)); - - Code = serialization::EXPR_CXX_CONSTRUCT; -} - -void ASTStmtWriter::VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E) { - VisitExpr(E); - Record.AddDeclRef(E->getConstructor()); - Record.AddSourceLocation(E->getLocation()); - Record.push_back(E->constructsVBase()); - Record.push_back(E->inheritedFromVBase()); - Code = serialization::EXPR_CXX_INHERITED_CTOR_INIT; -} - -void ASTStmtWriter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { - VisitCXXConstructExpr(E); - Record.AddTypeSourceInfo(E->getTypeSourceInfo()); - Code = serialization::EXPR_CXX_TEMPORARY_OBJECT; -} - -void ASTStmtWriter::VisitLambdaExpr(LambdaExpr *E) { - VisitExpr(E); - Record.push_back(E->NumCaptures); - Record.AddSourceRange(E->IntroducerRange); - Record.push_back(E->CaptureDefault); // FIXME: stable encoding - Record.AddSourceLocation(E->CaptureDefaultLoc); - Record.push_back(E->ExplicitParams); - Record.push_back(E->ExplicitResultType); - Record.AddSourceLocation(E->ClosingBrace); - - // Add capture initializers. - for (LambdaExpr::capture_init_iterator C = E->capture_init_begin(), - CEnd = E->capture_init_end(); - C != CEnd; ++C) { - Record.AddStmt(*C); - } - - Code = serialization::EXPR_LAMBDA; -} - -void ASTStmtWriter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { - VisitExpr(E); - Record.AddStmt(E->getSubExpr()); - Code = serialization::EXPR_CXX_STD_INITIALIZER_LIST; -} - -void ASTStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { - VisitExplicitCastExpr(E); - Record.AddSourceRange(SourceRange(E->getOperatorLoc(), E->getRParenLoc())); - Record.AddSourceRange(E->getAngleBrackets()); -} - -void ASTStmtWriter::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) { - VisitCXXNamedCastExpr(E); - Code = serialization::EXPR_CXX_STATIC_CAST; -} - -void ASTStmtWriter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) { - VisitCXXNamedCastExpr(E); - Code = serialization::EXPR_CXX_DYNAMIC_CAST; -} - -void ASTStmtWriter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) { - VisitCXXNamedCastExpr(E); - Code = serialization::EXPR_CXX_REINTERPRET_CAST; -} - -void ASTStmtWriter::VisitCXXConstCastExpr(CXXConstCastExpr *E) { - VisitCXXNamedCastExpr(E); - Code = serialization::EXPR_CXX_CONST_CAST; -} - -void ASTStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { - VisitExplicitCastExpr(E); - Record.AddSourceLocation(E->getLParenLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Code = serialization::EXPR_CXX_FUNCTIONAL_CAST; -} - -void ASTStmtWriter::VisitUserDefinedLiteral(UserDefinedLiteral *E) { - VisitCallExpr(E); - Record.AddSourceLocation(E->UDSuffixLoc); - Code = serialization::EXPR_USER_DEFINED_LITERAL; -} - -void ASTStmtWriter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { - VisitExpr(E); - Record.push_back(E->getValue()); - Record.AddSourceLocation(E->getLocation()); - Code = serialization::EXPR_CXX_BOOL_LITERAL; -} - -void ASTStmtWriter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { - VisitExpr(E); - Record.AddSourceLocation(E->getLocation()); - Code = serialization::EXPR_CXX_NULL_PTR_LITERAL; -} - -void ASTStmtWriter::VisitCXXTypeidExpr(CXXTypeidExpr *E) { - VisitExpr(E); - Record.AddSourceRange(E->getSourceRange()); - if (E->isTypeOperand()) { - Record.AddTypeSourceInfo(E->getTypeOperandSourceInfo()); - Code = serialization::EXPR_CXX_TYPEID_TYPE; - } else { - Record.AddStmt(E->getExprOperand()); - Code = serialization::EXPR_CXX_TYPEID_EXPR; - } -} - -void ASTStmtWriter::VisitCXXThisExpr(CXXThisExpr *E) { - VisitExpr(E); - Record.AddSourceLocation(E->getLocation()); - Record.push_back(E->isImplicit()); - Code = serialization::EXPR_CXX_THIS; -} - -void ASTStmtWriter::VisitCXXThrowExpr(CXXThrowExpr *E) { - VisitExpr(E); - Record.AddSourceLocation(E->getThrowLoc()); - Record.AddStmt(E->getSubExpr()); - Record.push_back(E->isThrownVariableInScope()); - Code = serialization::EXPR_CXX_THROW; -} - -void ASTStmtWriter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { - VisitExpr(E); - Record.AddDeclRef(E->getParam()); - Record.AddSourceLocation(E->getUsedLocation()); - Code = serialization::EXPR_CXX_DEFAULT_ARG; -} - -void ASTStmtWriter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { - VisitExpr(E); - Record.AddDeclRef(E->getField()); - Record.AddSourceLocation(E->getExprLoc()); - Code = serialization::EXPR_CXX_DEFAULT_INIT; -} - -void ASTStmtWriter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { - VisitExpr(E); - Record.AddCXXTemporary(E->getTemporary()); - Record.AddStmt(E->getSubExpr()); - Code = serialization::EXPR_CXX_BIND_TEMPORARY; -} - -void ASTStmtWriter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { - VisitExpr(E); - Record.AddTypeSourceInfo(E->getTypeSourceInfo()); - Record.AddSourceLocation(E->getRParenLoc()); - Code = serialization::EXPR_CXX_SCALAR_VALUE_INIT; -} - -void ASTStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) { - VisitExpr(E); - - Record.push_back(E->isArray()); - Record.push_back(E->hasInitializer()); - Record.push_back(E->getNumPlacementArgs()); - Record.push_back(E->isParenTypeId()); - - Record.push_back(E->isGlobalNew()); - Record.push_back(E->passAlignment()); - Record.push_back(E->doesUsualArrayDeleteWantSize()); - Record.push_back(E->CXXNewExprBits.StoredInitializationStyle); - - Record.AddDeclRef(E->getOperatorNew()); - Record.AddDeclRef(E->getOperatorDelete()); - Record.AddTypeSourceInfo(E->getAllocatedTypeSourceInfo()); - if (E->isParenTypeId()) - Record.AddSourceRange(E->getTypeIdParens()); - Record.AddSourceRange(E->getSourceRange()); - Record.AddSourceRange(E->getDirectInitRange()); - - for (CXXNewExpr::arg_iterator I = E->raw_arg_begin(), N = E->raw_arg_end(); - I != N; ++I) - Record.AddStmt(*I); - - Code = serialization::EXPR_CXX_NEW; -} - -void ASTStmtWriter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { - VisitExpr(E); - Record.push_back(E->isGlobalDelete()); - Record.push_back(E->isArrayForm()); - Record.push_back(E->isArrayFormAsWritten()); - Record.push_back(E->doesUsualArrayDeleteWantSize()); - Record.AddDeclRef(E->getOperatorDelete()); - Record.AddStmt(E->getArgument()); - Record.AddSourceLocation(E->getBeginLoc()); - - Code = serialization::EXPR_CXX_DELETE; -} - -void ASTStmtWriter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { - VisitExpr(E); - - Record.AddStmt(E->getBase()); - Record.push_back(E->isArrow()); - Record.AddSourceLocation(E->getOperatorLoc()); - Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); - Record.AddTypeSourceInfo(E->getScopeTypeInfo()); - Record.AddSourceLocation(E->getColonColonLoc()); - Record.AddSourceLocation(E->getTildeLoc()); - - // PseudoDestructorTypeStorage. - Record.AddIdentifierRef(E->getDestroyedTypeIdentifier()); - if (E->getDestroyedTypeIdentifier()) - Record.AddSourceLocation(E->getDestroyedTypeLoc()); - else - Record.AddTypeSourceInfo(E->getDestroyedTypeInfo()); - - Code = serialization::EXPR_CXX_PSEUDO_DESTRUCTOR; -} - -void ASTStmtWriter::VisitExprWithCleanups(ExprWithCleanups *E) { - VisitExpr(E); - Record.push_back(E->getNumObjects()); - for (unsigned i = 0, e = E->getNumObjects(); i != e; ++i) - Record.AddDeclRef(E->getObject(i)); - - Record.push_back(E->cleanupsHaveSideEffects()); - Record.AddStmt(E->getSubExpr()); - Code = serialization::EXPR_EXPR_WITH_CLEANUPS; -} - -void ASTStmtWriter::VisitCXXDependentScopeMemberExpr( - CXXDependentScopeMemberExpr *E) { - VisitExpr(E); - - // Don't emit anything here (or if you do you will have to update - // the corresponding deserialization function). - - Record.push_back(E->hasTemplateKWAndArgsInfo()); - Record.push_back(E->getNumTemplateArgs()); - Record.push_back(E->hasFirstQualifierFoundInScope()); - - if (E->hasTemplateKWAndArgsInfo()) { - const ASTTemplateKWAndArgsInfo &ArgInfo = - *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); - AddTemplateKWAndArgsInfo(ArgInfo, - E->getTrailingObjects<TemplateArgumentLoc>()); - } - - Record.push_back(E->isArrow()); - Record.AddSourceLocation(E->getOperatorLoc()); - Record.AddTypeRef(E->getBaseType()); - Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); - if (!E->isImplicitAccess()) - Record.AddStmt(E->getBase()); - else - Record.AddStmt(nullptr); - - if (E->hasFirstQualifierFoundInScope()) - Record.AddDeclRef(E->getFirstQualifierFoundInScope()); - - Record.AddDeclarationNameInfo(E->MemberNameInfo); - Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_MEMBER; -} - -void -ASTStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { - VisitExpr(E); - - // Don't emit anything here, HasTemplateKWAndArgsInfo must be - // emitted first. - - Record.push_back(E->DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo); - if (E->DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo) { - const ASTTemplateKWAndArgsInfo &ArgInfo = - *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); - Record.push_back(ArgInfo.NumTemplateArgs); - AddTemplateKWAndArgsInfo(ArgInfo, - E->getTrailingObjects<TemplateArgumentLoc>()); - } - - Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); - Record.AddDeclarationNameInfo(E->NameInfo); - Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_DECL_REF; -} - -void -ASTStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { - VisitExpr(E); - Record.push_back(E->arg_size()); - for (CXXUnresolvedConstructExpr::arg_iterator - ArgI = E->arg_begin(), ArgE = E->arg_end(); ArgI != ArgE; ++ArgI) - Record.AddStmt(*ArgI); - Record.AddTypeSourceInfo(E->getTypeSourceInfo()); - Record.AddSourceLocation(E->getLParenLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Code = serialization::EXPR_CXX_UNRESOLVED_CONSTRUCT; -} - -void ASTStmtWriter::VisitOverloadExpr(OverloadExpr *E) { - VisitExpr(E); - - Record.push_back(E->getNumDecls()); - Record.push_back(E->hasTemplateKWAndArgsInfo()); - if (E->hasTemplateKWAndArgsInfo()) { - const ASTTemplateKWAndArgsInfo &ArgInfo = - *E->getTrailingASTTemplateKWAndArgsInfo(); - Record.push_back(ArgInfo.NumTemplateArgs); - AddTemplateKWAndArgsInfo(ArgInfo, E->getTrailingTemplateArgumentLoc()); - } - - for (OverloadExpr::decls_iterator OvI = E->decls_begin(), - OvE = E->decls_end(); - OvI != OvE; ++OvI) { - Record.AddDeclRef(OvI.getDecl()); - Record.push_back(OvI.getAccess()); - } - - Record.AddDeclarationNameInfo(E->getNameInfo()); - Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); -} - -void ASTStmtWriter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { - VisitOverloadExpr(E); - Record.push_back(E->isArrow()); - Record.push_back(E->hasUnresolvedUsing()); - Record.AddStmt(!E->isImplicitAccess() ? E->getBase() : nullptr); - Record.AddTypeRef(E->getBaseType()); - Record.AddSourceLocation(E->getOperatorLoc()); - Code = serialization::EXPR_CXX_UNRESOLVED_MEMBER; -} - -void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { - VisitOverloadExpr(E); - Record.push_back(E->requiresADL()); - Record.push_back(E->isOverloaded()); - Record.AddDeclRef(E->getNamingClass()); - Code = serialization::EXPR_CXX_UNRESOLVED_LOOKUP; -} - -void ASTStmtWriter::VisitTypeTraitExpr(TypeTraitExpr *E) { - VisitExpr(E); - Record.push_back(E->TypeTraitExprBits.NumArgs); - Record.push_back(E->TypeTraitExprBits.Kind); // FIXME: Stable encoding - Record.push_back(E->TypeTraitExprBits.Value); - Record.AddSourceRange(E->getSourceRange()); - for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) - Record.AddTypeSourceInfo(E->getArg(I)); - Code = serialization::EXPR_TYPE_TRAIT; -} - -void ASTStmtWriter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { - VisitExpr(E); - Record.push_back(E->getTrait()); - Record.push_back(E->getValue()); - Record.AddSourceRange(E->getSourceRange()); - Record.AddTypeSourceInfo(E->getQueriedTypeSourceInfo()); - Record.AddStmt(E->getDimensionExpression()); - Code = serialization::EXPR_ARRAY_TYPE_TRAIT; -} - -void ASTStmtWriter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { - VisitExpr(E); - Record.push_back(E->getTrait()); - Record.push_back(E->getValue()); - Record.AddSourceRange(E->getSourceRange()); - Record.AddStmt(E->getQueriedExpression()); - Code = serialization::EXPR_CXX_EXPRESSION_TRAIT; -} - -void ASTStmtWriter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { - VisitExpr(E); - Record.push_back(E->getValue()); - Record.AddSourceRange(E->getSourceRange()); - Record.AddStmt(E->getOperand()); - Code = serialization::EXPR_CXX_NOEXCEPT; -} - -void ASTStmtWriter::VisitPackExpansionExpr(PackExpansionExpr *E) { - VisitExpr(E); - Record.AddSourceLocation(E->getEllipsisLoc()); - Record.push_back(E->NumExpansions); - Record.AddStmt(E->getPattern()); - Code = serialization::EXPR_PACK_EXPANSION; -} - -void ASTStmtWriter::VisitSizeOfPackExpr(SizeOfPackExpr *E) { - VisitExpr(E); - Record.push_back(E->isPartiallySubstituted() ? E->getPartialArguments().size() - : 0); - Record.AddSourceLocation(E->OperatorLoc); - Record.AddSourceLocation(E->PackLoc); - Record.AddSourceLocation(E->RParenLoc); - Record.AddDeclRef(E->Pack); - if (E->isPartiallySubstituted()) { - for (const auto &TA : E->getPartialArguments()) - Record.AddTemplateArgument(TA); - } else if (!E->isValueDependent()) { - Record.push_back(E->getPackLength()); - } - Code = serialization::EXPR_SIZEOF_PACK; -} - -void ASTStmtWriter::VisitSubstNonTypeTemplateParmExpr( - SubstNonTypeTemplateParmExpr *E) { - VisitExpr(E); - Record.AddDeclRef(E->getParameter()); - Record.AddSourceLocation(E->getNameLoc()); - Record.AddStmt(E->getReplacement()); - Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM; -} - -void ASTStmtWriter::VisitSubstNonTypeTemplateParmPackExpr( - SubstNonTypeTemplateParmPackExpr *E) { - VisitExpr(E); - Record.AddDeclRef(E->getParameterPack()); - Record.AddTemplateArgument(E->getArgumentPack()); - Record.AddSourceLocation(E->getParameterPackLocation()); - Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK; -} - -void ASTStmtWriter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumExpansions()); - Record.AddDeclRef(E->getParameterPack()); - Record.AddSourceLocation(E->getParameterPackLocation()); - for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end(); - I != End; ++I) - Record.AddDeclRef(*I); - Code = serialization::EXPR_FUNCTION_PARM_PACK; -} - -void ASTStmtWriter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { - VisitExpr(E); - Record.AddStmt(E->getTemporary()); - Record.AddDeclRef(E->getExtendingDecl()); - Record.push_back(E->getManglingNumber()); - Code = serialization::EXPR_MATERIALIZE_TEMPORARY; -} - -void ASTStmtWriter::VisitCXXFoldExpr(CXXFoldExpr *E) { - VisitExpr(E); - Record.AddSourceLocation(E->LParenLoc); - Record.AddSourceLocation(E->EllipsisLoc); - Record.AddSourceLocation(E->RParenLoc); - Record.AddStmt(E->SubExprs[0]); - Record.AddStmt(E->SubExprs[1]); - Record.push_back(E->Opcode); - Code = serialization::EXPR_CXX_FOLD; -} - -void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { - VisitExpr(E); - Record.AddStmt(E->getSourceExpr()); - Record.AddSourceLocation(E->getLocation()); - Record.push_back(E->isUnique()); - Code = serialization::EXPR_OPAQUE_VALUE; -} - -void ASTStmtWriter::VisitTypoExpr(TypoExpr *E) { - VisitExpr(E); - // TODO: Figure out sane writer behavior for a TypoExpr, if necessary - llvm_unreachable("Cannot write TypoExpr nodes"); -} - -//===----------------------------------------------------------------------===// -// CUDA Expressions and Statements. -//===----------------------------------------------------------------------===// - -void ASTStmtWriter::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E) { - VisitCallExpr(E); - Record.AddStmt(E->getConfig()); - Code = serialization::EXPR_CUDA_KERNEL_CALL; -} - -//===----------------------------------------------------------------------===// -// OpenCL Expressions and Statements. -//===----------------------------------------------------------------------===// -void ASTStmtWriter::VisitAsTypeExpr(AsTypeExpr *E) { - VisitExpr(E); - Record.AddSourceLocation(E->getBuiltinLoc()); - Record.AddSourceLocation(E->getRParenLoc()); - Record.AddStmt(E->getSrcExpr()); - Code = serialization::EXPR_ASTYPE; -} - -//===----------------------------------------------------------------------===// -// Microsoft Expressions and Statements. -//===----------------------------------------------------------------------===// -void ASTStmtWriter::VisitMSPropertyRefExpr(MSPropertyRefExpr *E) { - VisitExpr(E); - Record.push_back(E->isArrow()); - Record.AddStmt(E->getBaseExpr()); - Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); - Record.AddSourceLocation(E->getMemberLoc()); - Record.AddDeclRef(E->getPropertyDecl()); - Code = serialization::EXPR_CXX_PROPERTY_REF_EXPR; -} - -void ASTStmtWriter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *E) { - VisitExpr(E); - Record.AddStmt(E->getBase()); - Record.AddStmt(E->getIdx()); - Record.AddSourceLocation(E->getRBracketLoc()); - Code = serialization::EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR; -} - -void ASTStmtWriter::VisitCXXUuidofExpr(CXXUuidofExpr *E) { - VisitExpr(E); - Record.AddSourceRange(E->getSourceRange()); - Record.AddString(E->getUuidStr()); - if (E->isTypeOperand()) { - Record.AddTypeSourceInfo(E->getTypeOperandSourceInfo()); - Code = serialization::EXPR_CXX_UUIDOF_TYPE; - } else { - Record.AddStmt(E->getExprOperand()); - Code = serialization::EXPR_CXX_UUIDOF_EXPR; - } -} - -void ASTStmtWriter::VisitSEHExceptStmt(SEHExceptStmt *S) { - VisitStmt(S); - Record.AddSourceLocation(S->getExceptLoc()); - Record.AddStmt(S->getFilterExpr()); - Record.AddStmt(S->getBlock()); - Code = serialization::STMT_SEH_EXCEPT; -} - -void ASTStmtWriter::VisitSEHFinallyStmt(SEHFinallyStmt *S) { - VisitStmt(S); - Record.AddSourceLocation(S->getFinallyLoc()); - Record.AddStmt(S->getBlock()); - Code = serialization::STMT_SEH_FINALLY; -} - -void ASTStmtWriter::VisitSEHTryStmt(SEHTryStmt *S) { - VisitStmt(S); - Record.push_back(S->getIsCXXTry()); - Record.AddSourceLocation(S->getTryLoc()); - Record.AddStmt(S->getTryBlock()); - Record.AddStmt(S->getHandler()); - Code = serialization::STMT_SEH_TRY; -} - -void ASTStmtWriter::VisitSEHLeaveStmt(SEHLeaveStmt *S) { - VisitStmt(S); - Record.AddSourceLocation(S->getLeaveLoc()); - Code = serialization::STMT_SEH_LEAVE; -} - -//===----------------------------------------------------------------------===// -// OpenMP Directives. -//===----------------------------------------------------------------------===// -void ASTStmtWriter::VisitOMPExecutableDirective(OMPExecutableDirective *E) { - Record.AddSourceLocation(E->getBeginLoc()); - Record.AddSourceLocation(E->getEndLoc()); - OMPClauseWriter ClauseWriter(Record); - for (unsigned i = 0; i < E->getNumClauses(); ++i) { - ClauseWriter.writeClause(E->getClause(i)); - } - if (E->hasAssociatedStmt()) - Record.AddStmt(E->getAssociatedStmt()); -} - -void ASTStmtWriter::VisitOMPLoopDirective(OMPLoopDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - Record.push_back(D->getCollapsedNumber()); - VisitOMPExecutableDirective(D); - Record.AddStmt(D->getIterationVariable()); - Record.AddStmt(D->getLastIteration()); - Record.AddStmt(D->getCalcLastIteration()); - Record.AddStmt(D->getPreCond()); - Record.AddStmt(D->getCond()); - Record.AddStmt(D->getInit()); - Record.AddStmt(D->getInc()); - Record.AddStmt(D->getPreInits()); - if (isOpenMPWorksharingDirective(D->getDirectiveKind()) || - isOpenMPTaskLoopDirective(D->getDirectiveKind()) || - isOpenMPDistributeDirective(D->getDirectiveKind())) { - Record.AddStmt(D->getIsLastIterVariable()); - Record.AddStmt(D->getLowerBoundVariable()); - Record.AddStmt(D->getUpperBoundVariable()); - Record.AddStmt(D->getStrideVariable()); - Record.AddStmt(D->getEnsureUpperBound()); - Record.AddStmt(D->getNextLowerBound()); - Record.AddStmt(D->getNextUpperBound()); - Record.AddStmt(D->getNumIterations()); - } - if (isOpenMPLoopBoundSharingDirective(D->getDirectiveKind())) { - Record.AddStmt(D->getPrevLowerBoundVariable()); - Record.AddStmt(D->getPrevUpperBoundVariable()); - Record.AddStmt(D->getDistInc()); - Record.AddStmt(D->getPrevEnsureUpperBound()); - Record.AddStmt(D->getCombinedLowerBoundVariable()); - Record.AddStmt(D->getCombinedUpperBoundVariable()); - Record.AddStmt(D->getCombinedEnsureUpperBound()); - Record.AddStmt(D->getCombinedInit()); - Record.AddStmt(D->getCombinedCond()); - Record.AddStmt(D->getCombinedNextLowerBound()); - Record.AddStmt(D->getCombinedNextUpperBound()); - Record.AddStmt(D->getCombinedDistCond()); - Record.AddStmt(D->getCombinedParForInDistCond()); - } - for (auto I : D->counters()) { - Record.AddStmt(I); - } - for (auto I : D->private_counters()) { - Record.AddStmt(I); - } - for (auto I : D->inits()) { - Record.AddStmt(I); - } - for (auto I : D->updates()) { - Record.AddStmt(I); - } - for (auto I : D->finals()) { - Record.AddStmt(I); - } -} - -void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Record.push_back(D->hasCancel() ? 1 : 0); - Code = serialization::STMT_OMP_PARALLEL_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPSimdDirective(OMPSimdDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization::STMT_OMP_SIMD_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPForDirective(OMPForDirective *D) { - VisitOMPLoopDirective(D); - Record.push_back(D->hasCancel() ? 1 : 0); - Code = serialization::STMT_OMP_FOR_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPForSimdDirective(OMPForSimdDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization::STMT_OMP_FOR_SIMD_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPSectionsDirective(OMPSectionsDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Record.push_back(D->hasCancel() ? 1 : 0); - Code = serialization::STMT_OMP_SECTIONS_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPSectionDirective(OMPSectionDirective *D) { - VisitStmt(D); - VisitOMPExecutableDirective(D); - Record.push_back(D->hasCancel() ? 1 : 0); - Code = serialization::STMT_OMP_SECTION_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPSingleDirective(OMPSingleDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_SINGLE_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPMasterDirective(OMPMasterDirective *D) { - VisitStmt(D); - VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_MASTER_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPCriticalDirective(OMPCriticalDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Record.AddDeclarationNameInfo(D->getDirectiveName()); - Code = serialization::STMT_OMP_CRITICAL_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPParallelForDirective(OMPParallelForDirective *D) { - VisitOMPLoopDirective(D); - Record.push_back(D->hasCancel() ? 1 : 0); - Code = serialization::STMT_OMP_PARALLEL_FOR_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPParallelForSimdDirective( - OMPParallelForSimdDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization::STMT_OMP_PARALLEL_FOR_SIMD_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPParallelSectionsDirective( - OMPParallelSectionsDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Record.push_back(D->hasCancel() ? 1 : 0); - Code = serialization::STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTaskDirective(OMPTaskDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Record.push_back(D->hasCancel() ? 1 : 0); - Code = serialization::STMT_OMP_TASK_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPAtomicDirective(OMPAtomicDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Record.AddStmt(D->getX()); - Record.AddStmt(D->getV()); - Record.AddStmt(D->getExpr()); - Record.AddStmt(D->getUpdateExpr()); - Record.push_back(D->isXLHSInRHSPart() ? 1 : 0); - Record.push_back(D->isPostfixUpdate() ? 1 : 0); - Code = serialization::STMT_OMP_ATOMIC_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTargetDirective(OMPTargetDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_TARGET_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTargetDataDirective(OMPTargetDataDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_TARGET_DATA_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTargetEnterDataDirective( - OMPTargetEnterDataDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_TARGET_ENTER_DATA_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTargetExitDataDirective( - OMPTargetExitDataDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_TARGET_EXIT_DATA_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTargetParallelDirective( - OMPTargetParallelDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_TARGET_PARALLEL_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTargetParallelForDirective( - OMPTargetParallelForDirective *D) { - VisitOMPLoopDirective(D); - Record.push_back(D->hasCancel() ? 1 : 0); - Code = serialization::STMT_OMP_TARGET_PARALLEL_FOR_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) { - VisitStmt(D); - VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_TASKYIELD_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPBarrierDirective(OMPBarrierDirective *D) { - VisitStmt(D); - VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_BARRIER_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) { - VisitStmt(D); - VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_TASKWAIT_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Record.AddStmt(D->getReductionRef()); - Code = serialization::STMT_OMP_TASKGROUP_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPFlushDirective(OMPFlushDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_FLUSH_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPOrderedDirective(OMPOrderedDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_ORDERED_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTeamsDirective(OMPTeamsDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_TEAMS_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPCancellationPointDirective( - OMPCancellationPointDirective *D) { - VisitStmt(D); - VisitOMPExecutableDirective(D); - Record.push_back(D->getCancelRegion()); - Code = serialization::STMT_OMP_CANCELLATION_POINT_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPCancelDirective(OMPCancelDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Record.push_back(D->getCancelRegion()); - Code = serialization::STMT_OMP_CANCEL_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTaskLoopDirective(OMPTaskLoopDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization::STMT_OMP_TASKLOOP_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTaskLoopSimdDirective(OMPTaskLoopSimdDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization::STMT_OMP_TASKLOOP_SIMD_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPDistributeDirective(OMPDistributeDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization::STMT_OMP_DISTRIBUTE_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTargetUpdateDirective(OMPTargetUpdateDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_TARGET_UPDATE_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPDistributeParallelForDirective( - OMPDistributeParallelForDirective *D) { - VisitOMPLoopDirective(D); - Record.push_back(D->hasCancel() ? 1 : 0); - Code = serialization::STMT_OMP_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPDistributeParallelForSimdDirective( - OMPDistributeParallelForSimdDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization::STMT_OMP_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPDistributeSimdDirective( - OMPDistributeSimdDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization::STMT_OMP_DISTRIBUTE_SIMD_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTargetParallelForSimdDirective( - OMPTargetParallelForSimdDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization::STMT_OMP_TARGET_PARALLEL_FOR_SIMD_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTargetSimdDirective(OMPTargetSimdDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization::STMT_OMP_TARGET_SIMD_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTeamsDistributeDirective( - OMPTeamsDistributeDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization::STMT_OMP_TEAMS_DISTRIBUTE_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTeamsDistributeSimdDirective( - OMPTeamsDistributeSimdDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization::STMT_OMP_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTeamsDistributeParallelForSimdDirective( - OMPTeamsDistributeParallelForSimdDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization::STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTeamsDistributeParallelForDirective( - OMPTeamsDistributeParallelForDirective *D) { - VisitOMPLoopDirective(D); - Record.push_back(D->hasCancel() ? 1 : 0); - Code = serialization::STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTargetTeamsDirective(OMPTargetTeamsDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_TARGET_TEAMS_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTargetTeamsDistributeDirective( - OMPTargetTeamsDistributeDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization::STMT_OMP_TARGET_TEAMS_DISTRIBUTE_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTargetTeamsDistributeParallelForDirective( - OMPTargetTeamsDistributeParallelForDirective *D) { - VisitOMPLoopDirective(D); - Record.push_back(D->hasCancel() ? 1 : 0); - Code = serialization::STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTargetTeamsDistributeParallelForSimdDirective( - OMPTargetTeamsDistributeParallelForSimdDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization:: - STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE; -} - -void ASTStmtWriter::VisitOMPTargetTeamsDistributeSimdDirective( - OMPTargetTeamsDistributeSimdDirective *D) { - VisitOMPLoopDirective(D); - Code = serialization::STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE; -} - -//===----------------------------------------------------------------------===// -// ASTWriter Implementation -//===----------------------------------------------------------------------===// - -unsigned ASTWriter::RecordSwitchCaseID(SwitchCase *S) { - assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() && - "SwitchCase recorded twice"); - unsigned NextID = SwitchCaseIDs.size(); - SwitchCaseIDs[S] = NextID; - return NextID; -} - -unsigned ASTWriter::getSwitchCaseID(SwitchCase *S) { - assert(SwitchCaseIDs.find(S) != SwitchCaseIDs.end() && - "SwitchCase hasn't been seen yet"); - return SwitchCaseIDs[S]; -} - -void ASTWriter::ClearSwitchCaseIDs() { - SwitchCaseIDs.clear(); -} - -/// Write the given substatement or subexpression to the -/// bitstream. -void ASTWriter::WriteSubStmt(Stmt *S) { - RecordData Record; - ASTStmtWriter Writer(*this, Record); - ++NumStatements; - - if (!S) { - Stream.EmitRecord(serialization::STMT_NULL_PTR, Record); - return; - } - - llvm::DenseMap<Stmt *, uint64_t>::iterator I = SubStmtEntries.find(S); - if (I != SubStmtEntries.end()) { - Record.push_back(I->second); - Stream.EmitRecord(serialization::STMT_REF_PTR, Record); - return; - } - -#ifndef NDEBUG - assert(!ParentStmts.count(S) && "There is a Stmt cycle!"); - - struct ParentStmtInserterRAII { - Stmt *S; - llvm::DenseSet<Stmt *> &ParentStmts; - - ParentStmtInserterRAII(Stmt *S, llvm::DenseSet<Stmt *> &ParentStmts) - : S(S), ParentStmts(ParentStmts) { - ParentStmts.insert(S); - } - ~ParentStmtInserterRAII() { - ParentStmts.erase(S); - } - }; - - ParentStmtInserterRAII ParentStmtInserter(S, ParentStmts); -#endif - - Writer.Visit(S); - - uint64_t Offset = Writer.Emit(); - SubStmtEntries[S] = Offset; -} - -/// Flush all of the statements that have been added to the -/// queue via AddStmt(). -void ASTRecordWriter::FlushStmts() { - // We expect to be the only consumer of the two temporary statement maps, - // assert that they are empty. - assert(Writer->SubStmtEntries.empty() && "unexpected entries in sub-stmt map"); - assert(Writer->ParentStmts.empty() && "unexpected entries in parent stmt map"); - - for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) { - Writer->WriteSubStmt(StmtsToEmit[I]); - - assert(N == StmtsToEmit.size() && "record modified while being written!"); - - // Note that we are at the end of a full expression. Any - // expression records that follow this one are part of a different - // expression. - Writer->Stream.EmitRecord(serialization::STMT_STOP, ArrayRef<uint32_t>()); - - Writer->SubStmtEntries.clear(); - Writer->ParentStmts.clear(); - } - - StmtsToEmit.clear(); -} - -void ASTRecordWriter::FlushSubStmts() { - // For a nested statement, write out the substatements in reverse order (so - // that a simple stack machine can be used when loading), and don't emit a - // STMT_STOP after each one. - for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) { - Writer->WriteSubStmt(StmtsToEmit[N - I - 1]); - assert(N == StmtsToEmit.size() && "record modified while being written!"); - } - - StmtsToEmit.clear(); -} diff --git a/gnu/llvm/tools/clang/lib/Serialization/CMakeLists.txt b/gnu/llvm/tools/clang/lib/Serialization/CMakeLists.txt deleted file mode 100644 index a312cb91eb0..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -set(LLVM_LINK_COMPONENTS - BitReader - Support - ) - - -add_clang_library(clangSerialization - ASTCommon.cpp - ASTReader.cpp - ASTReaderDecl.cpp - ASTReaderStmt.cpp - ASTWriter.cpp - ASTWriterDecl.cpp - ASTWriterStmt.cpp - GeneratePCH.cpp - GlobalModuleIndex.cpp - Module.cpp - ModuleFileExtension.cpp - ModuleManager.cpp - PCHContainerOperations.cpp - - ADDITIONAL_HEADERS - ASTCommon.h - ASTReaderInternals.h - - LINK_LIBS - clangAST - clangBasic - clangLex - clangSema - ) diff --git a/gnu/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp b/gnu/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp deleted file mode 100644 index 2e0076521f9..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp +++ /dev/null @@ -1,76 +0,0 @@ -//===--- GeneratePCH.cpp - Sema Consumer for PCH Generation -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the PCHGenerator, which as a SemaConsumer that generates -// a PCH file. -// -//===----------------------------------------------------------------------===// - -#include "clang/AST/ASTContext.h" -#include "clang/Lex/HeaderSearch.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Sema/SemaConsumer.h" -#include "clang/Serialization/ASTWriter.h" -#include "llvm/Bitcode/BitstreamWriter.h" - -using namespace clang; - -PCHGenerator::PCHGenerator( - const Preprocessor &PP, StringRef OutputFile, StringRef isysroot, - std::shared_ptr<PCHBuffer> Buffer, - ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, - bool AllowASTWithErrors, bool IncludeTimestamps) - : PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()), - SemaPtr(nullptr), Buffer(std::move(Buffer)), Stream(this->Buffer->Data), - Writer(Stream, this->Buffer->Data, PP.getPCMCache(), Extensions, - IncludeTimestamps), - AllowASTWithErrors(AllowASTWithErrors) { - this->Buffer->IsComplete = false; -} - -PCHGenerator::~PCHGenerator() { -} - -void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { - // Don't create a PCH if there were fatal failures during module loading. - if (PP.getModuleLoader().HadFatalFailure) - return; - - bool hasErrors = PP.getDiagnostics().hasErrorOccurred(); - if (hasErrors && !AllowASTWithErrors) - return; - - Module *Module = nullptr; - if (PP.getLangOpts().isCompilingModule()) { - Module = PP.getHeaderSearchInfo().lookupModule( - PP.getLangOpts().CurrentModule, /*AllowSearch*/ false); - if (!Module) { - assert(hasErrors && "emitting module but current module doesn't exist"); - return; - } - } - - // Emit the PCH file to the Buffer. - assert(SemaPtr && "No Sema?"); - Buffer->Signature = - Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot, - // For serialization we are lenient if the errors were - // only warn-as-error kind. - PP.getDiagnostics().hasUncompilableErrorOccurred()); - - Buffer->IsComplete = true; -} - -ASTMutationListener *PCHGenerator::GetASTMutationListener() { - return &Writer; -} - -ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() { - return &Writer; -} diff --git a/gnu/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp b/gnu/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp deleted file mode 100644 index e7642a38924..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp +++ /dev/null @@ -1,943 +0,0 @@ -//===--- GlobalModuleIndex.cpp - Global Module Index ------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the GlobalModuleIndex class. -// -//===----------------------------------------------------------------------===// - -#include "ASTReaderInternals.h" -#include "clang/Basic/FileManager.h" -#include "clang/Lex/HeaderSearch.h" -#include "clang/Serialization/ASTBitCodes.h" -#include "clang/Serialization/GlobalModuleIndex.h" -#include "clang/Serialization/Module.h" -#include "clang/Serialization/PCHContainerOperations.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/Bitcode/BitstreamReader.h" -#include "llvm/Bitcode/BitstreamWriter.h" -#include "llvm/Support/DJB.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/LockFileManager.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/OnDiskHashTable.h" -#include "llvm/Support/Path.h" -#include <cstdio> -using namespace clang; -using namespace serialization; - -//----------------------------------------------------------------------------// -// Shared constants -//----------------------------------------------------------------------------// -namespace { - enum { - /// The block containing the index. - GLOBAL_INDEX_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID - }; - - /// Describes the record types in the index. - enum IndexRecordTypes { - /// Contains version information and potentially other metadata, - /// used to determine if we can read this global index file. - INDEX_METADATA, - /// Describes a module, including its file name and dependencies. - MODULE, - /// The index for identifiers. - IDENTIFIER_INDEX - }; -} - -/// The name of the global index file. -static const char * const IndexFileName = "modules.idx"; - -/// The global index file version. -static const unsigned CurrentVersion = 1; - -//----------------------------------------------------------------------------// -// Global module index reader. -//----------------------------------------------------------------------------// - -namespace { - -/// Trait used to read the identifier index from the on-disk hash -/// table. -class IdentifierIndexReaderTrait { -public: - typedef StringRef external_key_type; - typedef StringRef internal_key_type; - typedef SmallVector<unsigned, 2> data_type; - typedef unsigned hash_value_type; - typedef unsigned offset_type; - - static bool EqualKey(const internal_key_type& a, const internal_key_type& b) { - return a == b; - } - - static hash_value_type ComputeHash(const internal_key_type& a) { - return llvm::djbHash(a); - } - - static std::pair<unsigned, unsigned> - ReadKeyDataLength(const unsigned char*& d) { - using namespace llvm::support; - unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d); - unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d); - return std::make_pair(KeyLen, DataLen); - } - - static const internal_key_type& - GetInternalKey(const external_key_type& x) { return x; } - - static const external_key_type& - GetExternalKey(const internal_key_type& x) { return x; } - - static internal_key_type ReadKey(const unsigned char* d, unsigned n) { - return StringRef((const char *)d, n); - } - - static data_type ReadData(const internal_key_type& k, - const unsigned char* d, - unsigned DataLen) { - using namespace llvm::support; - - data_type Result; - while (DataLen > 0) { - unsigned ID = endian::readNext<uint32_t, little, unaligned>(d); - Result.push_back(ID); - DataLen -= 4; - } - - return Result; - } -}; - -typedef llvm::OnDiskIterableChainedHashTable<IdentifierIndexReaderTrait> - IdentifierIndexTable; - -} - -GlobalModuleIndex::GlobalModuleIndex(std::unique_ptr<llvm::MemoryBuffer> Buffer, - llvm::BitstreamCursor Cursor) - : Buffer(std::move(Buffer)), IdentifierIndex(), NumIdentifierLookups(), - NumIdentifierLookupHits() { - // Read the global index. - bool InGlobalIndexBlock = false; - bool Done = false; - while (!Done) { - llvm::BitstreamEntry Entry = Cursor.advance(); - - switch (Entry.Kind) { - case llvm::BitstreamEntry::Error: - return; - - case llvm::BitstreamEntry::EndBlock: - if (InGlobalIndexBlock) { - InGlobalIndexBlock = false; - Done = true; - continue; - } - return; - - - case llvm::BitstreamEntry::Record: - // Entries in the global index block are handled below. - if (InGlobalIndexBlock) - break; - - return; - - case llvm::BitstreamEntry::SubBlock: - if (!InGlobalIndexBlock && Entry.ID == GLOBAL_INDEX_BLOCK_ID) { - if (Cursor.EnterSubBlock(GLOBAL_INDEX_BLOCK_ID)) - return; - - InGlobalIndexBlock = true; - } else if (Cursor.SkipBlock()) { - return; - } - continue; - } - - SmallVector<uint64_t, 64> Record; - StringRef Blob; - switch ((IndexRecordTypes)Cursor.readRecord(Entry.ID, Record, &Blob)) { - case INDEX_METADATA: - // Make sure that the version matches. - if (Record.size() < 1 || Record[0] != CurrentVersion) - return; - break; - - case MODULE: { - unsigned Idx = 0; - unsigned ID = Record[Idx++]; - - // Make room for this module's information. - if (ID == Modules.size()) - Modules.push_back(ModuleInfo()); - else - Modules.resize(ID + 1); - - // Size/modification time for this module file at the time the - // global index was built. - Modules[ID].Size = Record[Idx++]; - Modules[ID].ModTime = Record[Idx++]; - - // File name. - unsigned NameLen = Record[Idx++]; - Modules[ID].FileName.assign(Record.begin() + Idx, - Record.begin() + Idx + NameLen); - Idx += NameLen; - - // Dependencies - unsigned NumDeps = Record[Idx++]; - Modules[ID].Dependencies.insert(Modules[ID].Dependencies.end(), - Record.begin() + Idx, - Record.begin() + Idx + NumDeps); - Idx += NumDeps; - - // Make sure we're at the end of the record. - assert(Idx == Record.size() && "More module info?"); - - // Record this module as an unresolved module. - // FIXME: this doesn't work correctly for module names containing path - // separators. - StringRef ModuleName = llvm::sys::path::stem(Modules[ID].FileName); - // Remove the -<hash of ModuleMapPath> - ModuleName = ModuleName.rsplit('-').first; - UnresolvedModules[ModuleName] = ID; - break; - } - - case IDENTIFIER_INDEX: - // Wire up the identifier index. - if (Record[0]) { - IdentifierIndex = IdentifierIndexTable::Create( - (const unsigned char *)Blob.data() + Record[0], - (const unsigned char *)Blob.data() + sizeof(uint32_t), - (const unsigned char *)Blob.data(), IdentifierIndexReaderTrait()); - } - break; - } - } -} - -GlobalModuleIndex::~GlobalModuleIndex() { - delete static_cast<IdentifierIndexTable *>(IdentifierIndex); -} - -std::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode> -GlobalModuleIndex::readIndex(StringRef Path) { - // Load the index file, if it's there. - llvm::SmallString<128> IndexPath; - IndexPath += Path; - llvm::sys::path::append(IndexPath, IndexFileName); - - llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> BufferOrErr = - llvm::MemoryBuffer::getFile(IndexPath.c_str()); - if (!BufferOrErr) - return std::make_pair(nullptr, EC_NotFound); - std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(BufferOrErr.get()); - - /// The main bitstream cursor for the main block. - llvm::BitstreamCursor Cursor(*Buffer); - - // Sniff for the signature. - if (Cursor.Read(8) != 'B' || - Cursor.Read(8) != 'C' || - Cursor.Read(8) != 'G' || - Cursor.Read(8) != 'I') { - return std::make_pair(nullptr, EC_IOError); - } - - return std::make_pair(new GlobalModuleIndex(std::move(Buffer), Cursor), - EC_None); -} - -void -GlobalModuleIndex::getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles) { - ModuleFiles.clear(); - for (unsigned I = 0, N = Modules.size(); I != N; ++I) { - if (ModuleFile *MF = Modules[I].File) - ModuleFiles.push_back(MF); - } -} - -void GlobalModuleIndex::getModuleDependencies( - ModuleFile *File, - SmallVectorImpl<ModuleFile *> &Dependencies) { - // Look for information about this module file. - llvm::DenseMap<ModuleFile *, unsigned>::iterator Known - = ModulesByFile.find(File); - if (Known == ModulesByFile.end()) - return; - - // Record dependencies. - Dependencies.clear(); - ArrayRef<unsigned> StoredDependencies = Modules[Known->second].Dependencies; - for (unsigned I = 0, N = StoredDependencies.size(); I != N; ++I) { - if (ModuleFile *MF = Modules[I].File) - Dependencies.push_back(MF); - } -} - -bool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) { - Hits.clear(); - - // If there's no identifier index, there is nothing we can do. - if (!IdentifierIndex) - return false; - - // Look into the identifier index. - ++NumIdentifierLookups; - IdentifierIndexTable &Table - = *static_cast<IdentifierIndexTable *>(IdentifierIndex); - IdentifierIndexTable::iterator Known = Table.find(Name); - if (Known == Table.end()) { - return true; - } - - SmallVector<unsigned, 2> ModuleIDs = *Known; - for (unsigned I = 0, N = ModuleIDs.size(); I != N; ++I) { - if (ModuleFile *MF = Modules[ModuleIDs[I]].File) - Hits.insert(MF); - } - - ++NumIdentifierLookupHits; - return true; -} - -bool GlobalModuleIndex::loadedModuleFile(ModuleFile *File) { - // Look for the module in the global module index based on the module name. - StringRef Name = File->ModuleName; - llvm::StringMap<unsigned>::iterator Known = UnresolvedModules.find(Name); - if (Known == UnresolvedModules.end()) { - return true; - } - - // Rectify this module with the global module index. - ModuleInfo &Info = Modules[Known->second]; - - // If the size and modification time match what we expected, record this - // module file. - bool Failed = true; - if (File->File->getSize() == Info.Size && - File->File->getModificationTime() == Info.ModTime) { - Info.File = File; - ModulesByFile[File] = Known->second; - - Failed = false; - } - - // One way or another, we have resolved this module file. - UnresolvedModules.erase(Known); - return Failed; -} - -void GlobalModuleIndex::printStats() { - std::fprintf(stderr, "*** Global Module Index Statistics:\n"); - if (NumIdentifierLookups) { - fprintf(stderr, " %u / %u identifier lookups succeeded (%f%%)\n", - NumIdentifierLookupHits, NumIdentifierLookups, - (double)NumIdentifierLookupHits*100.0/NumIdentifierLookups); - } - std::fprintf(stderr, "\n"); -} - -LLVM_DUMP_METHOD void GlobalModuleIndex::dump() { - llvm::errs() << "*** Global Module Index Dump:\n"; - llvm::errs() << "Module files:\n"; - for (auto &MI : Modules) { - llvm::errs() << "** " << MI.FileName << "\n"; - if (MI.File) - MI.File->dump(); - else - llvm::errs() << "\n"; - } - llvm::errs() << "\n"; -} - -//----------------------------------------------------------------------------// -// Global module index writer. -//----------------------------------------------------------------------------// - -namespace { - /// Provides information about a specific module file. - struct ModuleFileInfo { - /// The numberic ID for this module file. - unsigned ID; - - /// The set of modules on which this module depends. Each entry is - /// a module ID. - SmallVector<unsigned, 4> Dependencies; - ASTFileSignature Signature; - }; - - struct ImportedModuleFileInfo { - off_t StoredSize; - time_t StoredModTime; - ASTFileSignature StoredSignature; - ImportedModuleFileInfo(off_t Size, time_t ModTime, ASTFileSignature Sig) - : StoredSize(Size), StoredModTime(ModTime), StoredSignature(Sig) {} - }; - - /// Builder that generates the global module index file. - class GlobalModuleIndexBuilder { - FileManager &FileMgr; - const PCHContainerReader &PCHContainerRdr; - - /// Mapping from files to module file information. - typedef llvm::MapVector<const FileEntry *, ModuleFileInfo> ModuleFilesMap; - - /// Information about each of the known module files. - ModuleFilesMap ModuleFiles; - - /// Mapping from the imported module file to the imported - /// information. - typedef std::multimap<const FileEntry *, ImportedModuleFileInfo> - ImportedModuleFilesMap; - - /// Information about each importing of a module file. - ImportedModuleFilesMap ImportedModuleFiles; - - /// Mapping from identifiers to the list of module file IDs that - /// consider this identifier to be interesting. - typedef llvm::StringMap<SmallVector<unsigned, 2> > InterestingIdentifierMap; - - /// A mapping from all interesting identifiers to the set of module - /// files in which those identifiers are considered interesting. - InterestingIdentifierMap InterestingIdentifiers; - - /// Write the block-info block for the global module index file. - void emitBlockInfoBlock(llvm::BitstreamWriter &Stream); - - /// Retrieve the module file information for the given file. - ModuleFileInfo &getModuleFileInfo(const FileEntry *File) { - llvm::MapVector<const FileEntry *, ModuleFileInfo>::iterator Known - = ModuleFiles.find(File); - if (Known != ModuleFiles.end()) - return Known->second; - - unsigned NewID = ModuleFiles.size(); - ModuleFileInfo &Info = ModuleFiles[File]; - Info.ID = NewID; - return Info; - } - - public: - explicit GlobalModuleIndexBuilder( - FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr) - : FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr) {} - - /// Load the contents of the given module file into the builder. - /// - /// \returns true if an error occurred, false otherwise. - bool loadModuleFile(const FileEntry *File); - - /// Write the index to the given bitstream. - /// \returns true if an error occurred, false otherwise. - bool writeIndex(llvm::BitstreamWriter &Stream); - }; -} - -static void emitBlockID(unsigned ID, const char *Name, - llvm::BitstreamWriter &Stream, - SmallVectorImpl<uint64_t> &Record) { - Record.clear(); - Record.push_back(ID); - Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); - - // Emit the block name if present. - if (!Name || Name[0] == 0) return; - Record.clear(); - while (*Name) - Record.push_back(*Name++); - Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); -} - -static void emitRecordID(unsigned ID, const char *Name, - llvm::BitstreamWriter &Stream, - SmallVectorImpl<uint64_t> &Record) { - Record.clear(); - Record.push_back(ID); - while (*Name) - Record.push_back(*Name++); - Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); -} - -void -GlobalModuleIndexBuilder::emitBlockInfoBlock(llvm::BitstreamWriter &Stream) { - SmallVector<uint64_t, 64> Record; - Stream.EnterBlockInfoBlock(); - -#define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record) -#define RECORD(X) emitRecordID(X, #X, Stream, Record) - BLOCK(GLOBAL_INDEX_BLOCK); - RECORD(INDEX_METADATA); - RECORD(MODULE); - RECORD(IDENTIFIER_INDEX); -#undef RECORD -#undef BLOCK - - Stream.ExitBlock(); -} - -namespace { - class InterestingASTIdentifierLookupTrait - : public serialization::reader::ASTIdentifierLookupTraitBase { - - public: - /// The identifier and whether it is "interesting". - typedef std::pair<StringRef, bool> data_type; - - data_type ReadData(const internal_key_type& k, - const unsigned char* d, - unsigned DataLen) { - // The first bit indicates whether this identifier is interesting. - // That's all we care about. - using namespace llvm::support; - unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d); - bool IsInteresting = RawID & 0x01; - return std::make_pair(k, IsInteresting); - } - }; -} - -bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { - // Open the module file. - - auto Buffer = FileMgr.getBufferForFile(File, /*isVolatile=*/true); - if (!Buffer) { - return true; - } - - // Initialize the input stream - llvm::BitstreamCursor InStream(PCHContainerRdr.ExtractPCH(**Buffer)); - - // Sniff for the signature. - if (InStream.Read(8) != 'C' || - InStream.Read(8) != 'P' || - InStream.Read(8) != 'C' || - InStream.Read(8) != 'H') { - return true; - } - - // Record this module file and assign it a unique ID (if it doesn't have - // one already). - unsigned ID = getModuleFileInfo(File).ID; - - // Search for the blocks and records we care about. - enum { Other, ControlBlock, ASTBlock, DiagnosticOptionsBlock } State = Other; - bool Done = false; - while (!Done) { - llvm::BitstreamEntry Entry = InStream.advance(); - switch (Entry.Kind) { - case llvm::BitstreamEntry::Error: - Done = true; - continue; - - case llvm::BitstreamEntry::Record: - // In the 'other' state, just skip the record. We don't care. - if (State == Other) { - InStream.skipRecord(Entry.ID); - continue; - } - - // Handle potentially-interesting records below. - break; - - case llvm::BitstreamEntry::SubBlock: - if (Entry.ID == CONTROL_BLOCK_ID) { - if (InStream.EnterSubBlock(CONTROL_BLOCK_ID)) - return true; - - // Found the control block. - State = ControlBlock; - continue; - } - - if (Entry.ID == AST_BLOCK_ID) { - if (InStream.EnterSubBlock(AST_BLOCK_ID)) - return true; - - // Found the AST block. - State = ASTBlock; - continue; - } - - if (Entry.ID == UNHASHED_CONTROL_BLOCK_ID) { - if (InStream.EnterSubBlock(UNHASHED_CONTROL_BLOCK_ID)) - return true; - - // Found the Diagnostic Options block. - State = DiagnosticOptionsBlock; - continue; - } - - if (InStream.SkipBlock()) - return true; - - continue; - - case llvm::BitstreamEntry::EndBlock: - State = Other; - continue; - } - - // Read the given record. - SmallVector<uint64_t, 64> Record; - StringRef Blob; - unsigned Code = InStream.readRecord(Entry.ID, Record, &Blob); - - // Handle module dependencies. - if (State == ControlBlock && Code == IMPORTS) { - // Load each of the imported PCH files. - unsigned Idx = 0, N = Record.size(); - while (Idx < N) { - // Read information about the AST file. - - // Skip the imported kind - ++Idx; - - // Skip the import location - ++Idx; - - // Load stored size/modification time. - off_t StoredSize = (off_t)Record[Idx++]; - time_t StoredModTime = (time_t)Record[Idx++]; - - // Skip the stored signature. - // FIXME: we could read the signature out of the import and validate it. - ASTFileSignature StoredSignature = { - {{(uint32_t)Record[Idx++], (uint32_t)Record[Idx++], - (uint32_t)Record[Idx++], (uint32_t)Record[Idx++], - (uint32_t)Record[Idx++]}}}; - - // Skip the module name (currently this is only used for prebuilt - // modules while here we are only dealing with cached). - Idx += Record[Idx] + 1; - - // Retrieve the imported file name. - unsigned Length = Record[Idx++]; - SmallString<128> ImportedFile(Record.begin() + Idx, - Record.begin() + Idx + Length); - Idx += Length; - - // Find the imported module file. - const FileEntry *DependsOnFile - = FileMgr.getFile(ImportedFile, /*openFile=*/false, - /*cacheFailure=*/false); - - if (!DependsOnFile) - return true; - - // Save the information in ImportedModuleFileInfo so we can verify after - // loading all pcms. - ImportedModuleFiles.insert(std::make_pair( - DependsOnFile, ImportedModuleFileInfo(StoredSize, StoredModTime, - StoredSignature))); - - // Record the dependency. - unsigned DependsOnID = getModuleFileInfo(DependsOnFile).ID; - getModuleFileInfo(File).Dependencies.push_back(DependsOnID); - } - - continue; - } - - // Handle the identifier table - if (State == ASTBlock && Code == IDENTIFIER_TABLE && Record[0] > 0) { - typedef llvm::OnDiskIterableChainedHashTable< - InterestingASTIdentifierLookupTrait> InterestingIdentifierTable; - std::unique_ptr<InterestingIdentifierTable> Table( - InterestingIdentifierTable::Create( - (const unsigned char *)Blob.data() + Record[0], - (const unsigned char *)Blob.data() + sizeof(uint32_t), - (const unsigned char *)Blob.data())); - for (InterestingIdentifierTable::data_iterator D = Table->data_begin(), - DEnd = Table->data_end(); - D != DEnd; ++D) { - std::pair<StringRef, bool> Ident = *D; - if (Ident.second) - InterestingIdentifiers[Ident.first].push_back(ID); - else - (void)InterestingIdentifiers[Ident.first]; - } - } - - // Get Signature. - if (State == DiagnosticOptionsBlock && Code == SIGNATURE) - getModuleFileInfo(File).Signature = { - {{(uint32_t)Record[0], (uint32_t)Record[1], (uint32_t)Record[2], - (uint32_t)Record[3], (uint32_t)Record[4]}}}; - - // We don't care about this record. - } - - return false; -} - -namespace { - -/// Trait used to generate the identifier index as an on-disk hash -/// table. -class IdentifierIndexWriterTrait { -public: - typedef StringRef key_type; - typedef StringRef key_type_ref; - typedef SmallVector<unsigned, 2> data_type; - typedef const SmallVector<unsigned, 2> &data_type_ref; - typedef unsigned hash_value_type; - typedef unsigned offset_type; - - static hash_value_type ComputeHash(key_type_ref Key) { - return llvm::djbHash(Key); - } - - std::pair<unsigned,unsigned> - EmitKeyDataLength(raw_ostream& Out, key_type_ref Key, data_type_ref Data) { - using namespace llvm::support; - endian::Writer LE(Out, little); - unsigned KeyLen = Key.size(); - unsigned DataLen = Data.size() * 4; - LE.write<uint16_t>(KeyLen); - LE.write<uint16_t>(DataLen); - return std::make_pair(KeyLen, DataLen); - } - - void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) { - Out.write(Key.data(), KeyLen); - } - - void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data, - unsigned DataLen) { - using namespace llvm::support; - for (unsigned I = 0, N = Data.size(); I != N; ++I) - endian::write<uint32_t>(Out, Data[I], little); - } -}; - -} - -bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { - for (auto MapEntry : ImportedModuleFiles) { - auto *File = MapEntry.first; - ImportedModuleFileInfo &Info = MapEntry.second; - if (getModuleFileInfo(File).Signature) { - if (getModuleFileInfo(File).Signature != Info.StoredSignature) - // Verify Signature. - return true; - } else if (Info.StoredSize != File->getSize() || - Info.StoredModTime != File->getModificationTime()) - // Verify Size and ModTime. - return true; - } - - using namespace llvm; - - // Emit the file header. - Stream.Emit((unsigned)'B', 8); - Stream.Emit((unsigned)'C', 8); - Stream.Emit((unsigned)'G', 8); - Stream.Emit((unsigned)'I', 8); - - // Write the block-info block, which describes the records in this bitcode - // file. - emitBlockInfoBlock(Stream); - - Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3); - - // Write the metadata. - SmallVector<uint64_t, 2> Record; - Record.push_back(CurrentVersion); - Stream.EmitRecord(INDEX_METADATA, Record); - - // Write the set of known module files. - for (ModuleFilesMap::iterator M = ModuleFiles.begin(), - MEnd = ModuleFiles.end(); - M != MEnd; ++M) { - Record.clear(); - Record.push_back(M->second.ID); - Record.push_back(M->first->getSize()); - Record.push_back(M->first->getModificationTime()); - - // File name - StringRef Name(M->first->getName()); - Record.push_back(Name.size()); - Record.append(Name.begin(), Name.end()); - - // Dependencies - Record.push_back(M->second.Dependencies.size()); - Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end()); - Stream.EmitRecord(MODULE, Record); - } - - // Write the identifier -> module file mapping. - { - llvm::OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator; - IdentifierIndexWriterTrait Trait; - - // Populate the hash table. - for (InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(), - IEnd = InterestingIdentifiers.end(); - I != IEnd; ++I) { - Generator.insert(I->first(), I->second, Trait); - } - - // Create the on-disk hash table in a buffer. - SmallString<4096> IdentifierTable; - uint32_t BucketOffset; - { - using namespace llvm::support; - llvm::raw_svector_ostream Out(IdentifierTable); - // Make sure that no bucket is at offset 0 - endian::write<uint32_t>(Out, 0, little); - BucketOffset = Generator.Emit(Out, Trait); - } - - // Create a blob abbreviation - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned IDTableAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - // Write the identifier table - uint64_t Record[] = {IDENTIFIER_INDEX, BucketOffset}; - Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable); - } - - Stream.ExitBlock(); - return false; -} - -GlobalModuleIndex::ErrorCode -GlobalModuleIndex::writeIndex(FileManager &FileMgr, - const PCHContainerReader &PCHContainerRdr, - StringRef Path) { - llvm::SmallString<128> IndexPath; - IndexPath += Path; - llvm::sys::path::append(IndexPath, IndexFileName); - - // Coordinate building the global index file with other processes that might - // try to do the same. - llvm::LockFileManager Locked(IndexPath); - switch (Locked) { - case llvm::LockFileManager::LFS_Error: - return EC_IOError; - - case llvm::LockFileManager::LFS_Owned: - // We're responsible for building the index ourselves. Do so below. - break; - - case llvm::LockFileManager::LFS_Shared: - // Someone else is responsible for building the index. We don't care - // when they finish, so we're done. - return EC_Building; - } - - // The module index builder. - GlobalModuleIndexBuilder Builder(FileMgr, PCHContainerRdr); - - // Load each of the module files. - std::error_code EC; - for (llvm::sys::fs::directory_iterator D(Path, EC), DEnd; - D != DEnd && !EC; - D.increment(EC)) { - // If this isn't a module file, we don't care. - if (llvm::sys::path::extension(D->path()) != ".pcm") { - // ... unless it's a .pcm.lock file, which indicates that someone is - // in the process of rebuilding a module. They'll rebuild the index - // at the end of that translation unit, so we don't have to. - if (llvm::sys::path::extension(D->path()) == ".pcm.lock") - return EC_Building; - - continue; - } - - // If we can't find the module file, skip it. - const FileEntry *ModuleFile = FileMgr.getFile(D->path()); - if (!ModuleFile) - continue; - - // Load this module file. - if (Builder.loadModuleFile(ModuleFile)) - return EC_IOError; - } - - // The output buffer, into which the global index will be written. - SmallVector<char, 16> OutputBuffer; - { - llvm::BitstreamWriter OutputStream(OutputBuffer); - if (Builder.writeIndex(OutputStream)) - return EC_IOError; - } - - // Write the global index file to a temporary file. - llvm::SmallString<128> IndexTmpPath; - int TmpFD; - if (llvm::sys::fs::createUniqueFile(IndexPath + "-%%%%%%%%", TmpFD, - IndexTmpPath)) - return EC_IOError; - - // Open the temporary global index file for output. - llvm::raw_fd_ostream Out(TmpFD, true); - if (Out.has_error()) - return EC_IOError; - - // Write the index. - Out.write(OutputBuffer.data(), OutputBuffer.size()); - Out.close(); - if (Out.has_error()) - return EC_IOError; - - // Remove the old index file. It isn't relevant any more. - llvm::sys::fs::remove(IndexPath); - - // Rename the newly-written index file to the proper name. - if (llvm::sys::fs::rename(IndexTmpPath, IndexPath)) { - // Rename failed; just remove the - llvm::sys::fs::remove(IndexTmpPath); - return EC_IOError; - } - - // We're done. - return EC_None; -} - -namespace { - class GlobalIndexIdentifierIterator : public IdentifierIterator { - /// The current position within the identifier lookup table. - IdentifierIndexTable::key_iterator Current; - - /// The end position within the identifier lookup table. - IdentifierIndexTable::key_iterator End; - - public: - explicit GlobalIndexIdentifierIterator(IdentifierIndexTable &Idx) { - Current = Idx.key_begin(); - End = Idx.key_end(); - } - - StringRef Next() override { - if (Current == End) - return StringRef(); - - StringRef Result = *Current; - ++Current; - return Result; - } - }; -} - -IdentifierIterator *GlobalModuleIndex::createIdentifierIterator() const { - IdentifierIndexTable &Table = - *static_cast<IdentifierIndexTable *>(IdentifierIndex); - return new GlobalIndexIdentifierIterator(Table); -} diff --git a/gnu/llvm/tools/clang/lib/Serialization/Module.cpp b/gnu/llvm/tools/clang/lib/Serialization/Module.cpp deleted file mode 100644 index 580e46e4f24..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/Module.cpp +++ /dev/null @@ -1,95 +0,0 @@ -//===- Module.cpp - Module description ------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the Module class, which describes a module that has -// been loaded from an AST file. -// -//===----------------------------------------------------------------------===// - -#include "clang/Serialization/Module.h" -#include "ASTReaderInternals.h" -#include "clang/Serialization/ContinuousRangeMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/raw_ostream.h" - -using namespace clang; -using namespace serialization; -using namespace reader; - -ModuleFile::~ModuleFile() { - delete static_cast<ASTIdentifierLookupTable *>(IdentifierLookupTable); - delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable); - delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable); -} - -template<typename Key, typename Offset, unsigned InitialCapacity> -static void -dumpLocalRemap(StringRef Name, - const ContinuousRangeMap<Key, Offset, InitialCapacity> &Map) { - if (Map.begin() == Map.end()) - return; - - using MapType = ContinuousRangeMap<Key, Offset, InitialCapacity>; - - llvm::errs() << " " << Name << ":\n"; - for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end(); - I != IEnd; ++I) { - llvm::errs() << " " << I->first << " -> " << I->second << "\n"; - } -} - -LLVM_DUMP_METHOD void ModuleFile::dump() { - llvm::errs() << "\nModule: " << FileName << "\n"; - if (!Imports.empty()) { - llvm::errs() << " Imports: "; - for (unsigned I = 0, N = Imports.size(); I != N; ++I) { - if (I) - llvm::errs() << ", "; - llvm::errs() << Imports[I]->FileName; - } - llvm::errs() << "\n"; - } - - // Remapping tables. - llvm::errs() << " Base source location offset: " << SLocEntryBaseOffset - << '\n'; - dumpLocalRemap("Source location offset local -> global map", SLocRemap); - - llvm::errs() << " Base identifier ID: " << BaseIdentifierID << '\n' - << " Number of identifiers: " << LocalNumIdentifiers << '\n'; - dumpLocalRemap("Identifier ID local -> global map", IdentifierRemap); - - llvm::errs() << " Base macro ID: " << BaseMacroID << '\n' - << " Number of macros: " << LocalNumMacros << '\n'; - dumpLocalRemap("Macro ID local -> global map", MacroRemap); - - llvm::errs() << " Base submodule ID: " << BaseSubmoduleID << '\n' - << " Number of submodules: " << LocalNumSubmodules << '\n'; - dumpLocalRemap("Submodule ID local -> global map", SubmoduleRemap); - - llvm::errs() << " Base selector ID: " << BaseSelectorID << '\n' - << " Number of selectors: " << LocalNumSelectors << '\n'; - dumpLocalRemap("Selector ID local -> global map", SelectorRemap); - - llvm::errs() << " Base preprocessed entity ID: " << BasePreprocessedEntityID - << '\n' - << " Number of preprocessed entities: " - << NumPreprocessedEntities << '\n'; - dumpLocalRemap("Preprocessed entity ID local -> global map", - PreprocessedEntityRemap); - - llvm::errs() << " Base type index: " << BaseTypeIndex << '\n' - << " Number of types: " << LocalNumTypes << '\n'; - dumpLocalRemap("Type index local -> global map", TypeRemap); - - llvm::errs() << " Base decl ID: " << BaseDeclID << '\n' - << " Number of decls: " << LocalNumDecls << '\n'; - dumpLocalRemap("Decl ID local -> global map", DeclRemap); -} diff --git a/gnu/llvm/tools/clang/lib/Serialization/ModuleFileExtension.cpp b/gnu/llvm/tools/clang/lib/Serialization/ModuleFileExtension.cpp deleted file mode 100644 index 5bd0a1ce660..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/ModuleFileExtension.cpp +++ /dev/null @@ -1,21 +0,0 @@ -//===-- ModuleFileExtension.cpp - Module File Extensions ------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -#include "clang/Serialization/ModuleFileExtension.h" -#include "llvm/ADT/Hashing.h" -using namespace clang; - -ModuleFileExtension::~ModuleFileExtension() { } - -llvm::hash_code ModuleFileExtension::hashExtension(llvm::hash_code Code) const { - return Code; -} - -ModuleFileExtensionWriter::~ModuleFileExtensionWriter() { } - -ModuleFileExtensionReader::~ModuleFileExtensionReader() { } diff --git a/gnu/llvm/tools/clang/lib/Serialization/ModuleManager.cpp b/gnu/llvm/tools/clang/lib/Serialization/ModuleManager.cpp deleted file mode 100644 index 54e0c08c5bc..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/ModuleManager.cpp +++ /dev/null @@ -1,510 +0,0 @@ -//===- ModuleManager.cpp - Module Manager ---------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the ModuleManager class, which manages a set of loaded -// modules for the ASTReader. -// -//===----------------------------------------------------------------------===// - -#include "clang/Serialization/ModuleManager.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/LLVM.h" -#include "clang/Basic/MemoryBufferCache.h" -#include "clang/Lex/HeaderSearch.h" -#include "clang/Lex/ModuleMap.h" -#include "clang/Serialization/GlobalModuleIndex.h" -#include "clang/Serialization/Module.h" -#include "clang/Serialization/PCHContainerOperations.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator.h" -#include "llvm/Support/Chrono.h" -#include "llvm/Support/DOTGraphTraits.h" -#include "llvm/Support/ErrorOr.h" -#include "llvm/Support/GraphWriter.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/VirtualFileSystem.h" -#include <algorithm> -#include <cassert> -#include <memory> -#include <string> -#include <system_error> - -using namespace clang; -using namespace serialization; - -ModuleFile *ModuleManager::lookupByFileName(StringRef Name) const { - const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false, - /*cacheFailure=*/false); - if (Entry) - return lookup(Entry); - - return nullptr; -} - -ModuleFile *ModuleManager::lookupByModuleName(StringRef Name) const { - if (const Module *Mod = HeaderSearchInfo.getModuleMap().findModule(Name)) - if (const FileEntry *File = Mod->getASTFile()) - return lookup(File); - - return nullptr; -} - -ModuleFile *ModuleManager::lookup(const FileEntry *File) const { - auto Known = Modules.find(File); - if (Known == Modules.end()) - return nullptr; - - return Known->second; -} - -std::unique_ptr<llvm::MemoryBuffer> -ModuleManager::lookupBuffer(StringRef Name) { - const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false, - /*cacheFailure=*/false); - return std::move(InMemoryBuffers[Entry]); -} - -static bool checkSignature(ASTFileSignature Signature, - ASTFileSignature ExpectedSignature, - std::string &ErrorStr) { - if (!ExpectedSignature || Signature == ExpectedSignature) - return false; - - ErrorStr = - Signature ? "signature mismatch" : "could not read module signature"; - return true; -} - -static void updateModuleImports(ModuleFile &MF, ModuleFile *ImportedBy, - SourceLocation ImportLoc) { - if (ImportedBy) { - MF.ImportedBy.insert(ImportedBy); - ImportedBy->Imports.insert(&MF); - } else { - if (!MF.DirectlyImported) - MF.ImportLoc = ImportLoc; - - MF.DirectlyImported = true; - } -} - -ModuleManager::AddModuleResult -ModuleManager::addModule(StringRef FileName, ModuleKind Type, - SourceLocation ImportLoc, ModuleFile *ImportedBy, - unsigned Generation, - off_t ExpectedSize, time_t ExpectedModTime, - ASTFileSignature ExpectedSignature, - ASTFileSignatureReader ReadSignature, - ModuleFile *&Module, - std::string &ErrorStr) { - Module = nullptr; - - // Look for the file entry. This only fails if the expected size or - // modification time differ. - const FileEntry *Entry; - if (Type == MK_ExplicitModule || Type == MK_PrebuiltModule) { - // If we're not expecting to pull this file out of the module cache, it - // might have a different mtime due to being moved across filesystems in - // a distributed build. The size must still match, though. (As must the - // contents, but we can't check that.) - ExpectedModTime = 0; - } - if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, Entry)) { - ErrorStr = "module file out of date"; - return OutOfDate; - } - - if (!Entry && FileName != "-") { - ErrorStr = "module file not found"; - return Missing; - } - - // Check whether we already loaded this module, before - if (ModuleFile *ModuleEntry = Modules.lookup(Entry)) { - // Check the stored signature. - if (checkSignature(ModuleEntry->Signature, ExpectedSignature, ErrorStr)) - return OutOfDate; - - Module = ModuleEntry; - updateModuleImports(*ModuleEntry, ImportedBy, ImportLoc); - return AlreadyLoaded; - } - - // Allocate a new module. - auto NewModule = llvm::make_unique<ModuleFile>(Type, Generation); - NewModule->Index = Chain.size(); - NewModule->FileName = FileName.str(); - NewModule->File = Entry; - NewModule->ImportLoc = ImportLoc; - NewModule->InputFilesValidationTimestamp = 0; - - if (NewModule->Kind == MK_ImplicitModule) { - std::string TimestampFilename = NewModule->getTimestampFilename(); - llvm::vfs::Status Status; - // A cached stat value would be fine as well. - if (!FileMgr.getNoncachedStatValue(TimestampFilename, Status)) - NewModule->InputFilesValidationTimestamp = - llvm::sys::toTimeT(Status.getLastModificationTime()); - } - - // Load the contents of the module - if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) { - // The buffer was already provided for us. - NewModule->Buffer = &PCMCache->addBuffer(FileName, std::move(Buffer)); - // Since the cached buffer is reused, it is safe to close the file - // descriptor that was opened while stat()ing the PCM in - // lookupModuleFile() above, it won't be needed any longer. - Entry->closeFile(); - } else if (llvm::MemoryBuffer *Buffer = PCMCache->lookupBuffer(FileName)) { - NewModule->Buffer = Buffer; - // As above, the file descriptor is no longer needed. - Entry->closeFile(); - } else { - // Open the AST file. - llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf((std::error_code())); - if (FileName == "-") { - Buf = llvm::MemoryBuffer::getSTDIN(); - } else { - // Get a buffer of the file and close the file descriptor when done. - Buf = FileMgr.getBufferForFile(NewModule->File, - /*IsVolatile=*/false, - /*ShouldClose=*/true); - } - - if (!Buf) { - ErrorStr = Buf.getError().message(); - return Missing; - } - - NewModule->Buffer = &PCMCache->addBuffer(FileName, std::move(*Buf)); - } - - // Initialize the stream. - NewModule->Data = PCHContainerRdr.ExtractPCH(*NewModule->Buffer); - - // Read the signature eagerly now so that we can check it. Avoid calling - // ReadSignature unless there's something to check though. - if (ExpectedSignature && checkSignature(ReadSignature(NewModule->Data), - ExpectedSignature, ErrorStr)) { - // Try to remove the buffer. If it can't be removed, then it was already - // validated by this process. - if (!PCMCache->tryToRemoveBuffer(NewModule->FileName)) - FileMgr.invalidateCache(NewModule->File); - return OutOfDate; - } - - // We're keeping this module. Store it everywhere. - Module = Modules[Entry] = NewModule.get(); - - updateModuleImports(*NewModule, ImportedBy, ImportLoc); - - if (!NewModule->isModule()) - PCHChain.push_back(NewModule.get()); - if (!ImportedBy) - Roots.push_back(NewModule.get()); - - Chain.push_back(std::move(NewModule)); - return NewlyLoaded; -} - -void ModuleManager::removeModules( - ModuleIterator First, - llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully, - ModuleMap *modMap) { - auto Last = end(); - if (First == Last) - return; - - // Explicitly clear VisitOrder since we might not notice it is stale. - VisitOrder.clear(); - - // Collect the set of module file pointers that we'll be removing. - llvm::SmallPtrSet<ModuleFile *, 4> victimSet( - (llvm::pointer_iterator<ModuleIterator>(First)), - (llvm::pointer_iterator<ModuleIterator>(Last))); - - auto IsVictim = [&](ModuleFile *MF) { - return victimSet.count(MF); - }; - // Remove any references to the now-destroyed modules. - for (auto I = begin(); I != First; ++I) { - I->Imports.remove_if(IsVictim); - I->ImportedBy.remove_if(IsVictim); - } - Roots.erase(std::remove_if(Roots.begin(), Roots.end(), IsVictim), - Roots.end()); - - // Remove the modules from the PCH chain. - for (auto I = First; I != Last; ++I) { - if (!I->isModule()) { - PCHChain.erase(std::find(PCHChain.begin(), PCHChain.end(), &*I), - PCHChain.end()); - break; - } - } - - // Delete the modules and erase them from the various structures. - for (ModuleIterator victim = First; victim != Last; ++victim) { - Modules.erase(victim->File); - - if (modMap) { - StringRef ModuleName = victim->ModuleName; - if (Module *mod = modMap->findModule(ModuleName)) { - mod->setASTFile(nullptr); - } - } - - // Files that didn't make it through ReadASTCore successfully will be - // rebuilt (or there was an error). Invalidate them so that we can load the - // new files that will be renamed over the old ones. - // - // The PCMCache tracks whether the module was successfully loaded in another - // thread/context; in that case, it won't need to be rebuilt (and we can't - // safely invalidate it anyway). - if (LoadedSuccessfully.count(&*victim) == 0 && - !PCMCache->tryToRemoveBuffer(victim->FileName)) - FileMgr.invalidateCache(victim->File); - } - - // Delete the modules. - Chain.erase(Chain.begin() + (First - begin()), Chain.end()); -} - -void -ModuleManager::addInMemoryBuffer(StringRef FileName, - std::unique_ptr<llvm::MemoryBuffer> Buffer) { - const FileEntry *Entry = - FileMgr.getVirtualFile(FileName, Buffer->getBufferSize(), 0); - InMemoryBuffers[Entry] = std::move(Buffer); -} - -ModuleManager::VisitState *ModuleManager::allocateVisitState() { - // Fast path: if we have a cached state, use it. - if (FirstVisitState) { - VisitState *Result = FirstVisitState; - FirstVisitState = FirstVisitState->NextState; - Result->NextState = nullptr; - return Result; - } - - // Allocate and return a new state. - return new VisitState(size()); -} - -void ModuleManager::returnVisitState(VisitState *State) { - assert(State->NextState == nullptr && "Visited state is in list?"); - State->NextState = FirstVisitState; - FirstVisitState = State; -} - -void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) { - GlobalIndex = Index; - if (!GlobalIndex) { - ModulesInCommonWithGlobalIndex.clear(); - return; - } - - // Notify the global module index about all of the modules we've already - // loaded. - for (ModuleFile &M : *this) - if (!GlobalIndex->loadedModuleFile(&M)) - ModulesInCommonWithGlobalIndex.push_back(&M); -} - -void ModuleManager::moduleFileAccepted(ModuleFile *MF) { - if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF)) - return; - - ModulesInCommonWithGlobalIndex.push_back(MF); -} - -ModuleManager::ModuleManager(FileManager &FileMgr, MemoryBufferCache &PCMCache, - const PCHContainerReader &PCHContainerRdr, - const HeaderSearch& HeaderSearchInfo) - : FileMgr(FileMgr), PCMCache(&PCMCache), PCHContainerRdr(PCHContainerRdr), - HeaderSearchInfo(HeaderSearchInfo) {} - -ModuleManager::~ModuleManager() { delete FirstVisitState; } - -void ModuleManager::visit(llvm::function_ref<bool(ModuleFile &M)> Visitor, - llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) { - // If the visitation order vector is the wrong size, recompute the order. - if (VisitOrder.size() != Chain.size()) { - unsigned N = size(); - VisitOrder.clear(); - VisitOrder.reserve(N); - - // Record the number of incoming edges for each module. When we - // encounter a module with no incoming edges, push it into the queue - // to seed the queue. - SmallVector<ModuleFile *, 4> Queue; - Queue.reserve(N); - llvm::SmallVector<unsigned, 4> UnusedIncomingEdges; - UnusedIncomingEdges.resize(size()); - for (ModuleFile &M : llvm::reverse(*this)) { - unsigned Size = M.ImportedBy.size(); - UnusedIncomingEdges[M.Index] = Size; - if (!Size) - Queue.push_back(&M); - } - - // Traverse the graph, making sure to visit a module before visiting any - // of its dependencies. - while (!Queue.empty()) { - ModuleFile *CurrentModule = Queue.pop_back_val(); - VisitOrder.push_back(CurrentModule); - - // For any module that this module depends on, push it on the - // stack (if it hasn't already been marked as visited). - for (auto M = CurrentModule->Imports.rbegin(), - MEnd = CurrentModule->Imports.rend(); - M != MEnd; ++M) { - // Remove our current module as an impediment to visiting the - // module we depend on. If we were the last unvisited module - // that depends on this particular module, push it into the - // queue to be visited. - unsigned &NumUnusedEdges = UnusedIncomingEdges[(*M)->Index]; - if (NumUnusedEdges && (--NumUnusedEdges == 0)) - Queue.push_back(*M); - } - } - - assert(VisitOrder.size() == N && "Visitation order is wrong?"); - - delete FirstVisitState; - FirstVisitState = nullptr; - } - - VisitState *State = allocateVisitState(); - unsigned VisitNumber = State->NextVisitNumber++; - - // If the caller has provided us with a hit-set that came from the global - // module index, mark every module file in common with the global module - // index that is *not* in that set as 'visited'. - if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) { - for (unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I) - { - ModuleFile *M = ModulesInCommonWithGlobalIndex[I]; - if (!ModuleFilesHit->count(M)) - State->VisitNumber[M->Index] = VisitNumber; - } - } - - for (unsigned I = 0, N = VisitOrder.size(); I != N; ++I) { - ModuleFile *CurrentModule = VisitOrder[I]; - // Should we skip this module file? - if (State->VisitNumber[CurrentModule->Index] == VisitNumber) - continue; - - // Visit the module. - assert(State->VisitNumber[CurrentModule->Index] == VisitNumber - 1); - State->VisitNumber[CurrentModule->Index] = VisitNumber; - if (!Visitor(*CurrentModule)) - continue; - - // The visitor has requested that cut off visitation of any - // module that the current module depends on. To indicate this - // behavior, we mark all of the reachable modules as having been visited. - ModuleFile *NextModule = CurrentModule; - do { - // For any module that this module depends on, push it on the - // stack (if it hasn't already been marked as visited). - for (llvm::SetVector<ModuleFile *>::iterator - M = NextModule->Imports.begin(), - MEnd = NextModule->Imports.end(); - M != MEnd; ++M) { - if (State->VisitNumber[(*M)->Index] != VisitNumber) { - State->Stack.push_back(*M); - State->VisitNumber[(*M)->Index] = VisitNumber; - } - } - - if (State->Stack.empty()) - break; - - // Pop the next module off the stack. - NextModule = State->Stack.pop_back_val(); - } while (true); - } - - returnVisitState(State); -} - -bool ModuleManager::lookupModuleFile(StringRef FileName, - off_t ExpectedSize, - time_t ExpectedModTime, - const FileEntry *&File) { - if (FileName == "-") { - File = nullptr; - return false; - } - - // Open the file immediately to ensure there is no race between stat'ing and - // opening the file. - File = FileMgr.getFile(FileName, /*openFile=*/true, /*cacheFailure=*/false); - if (!File) - return false; - - if ((ExpectedSize && ExpectedSize != File->getSize()) || - (ExpectedModTime && ExpectedModTime != File->getModificationTime())) - // Do not destroy File, as it may be referenced. If we need to rebuild it, - // it will be destroyed by removeModules. - return true; - - return false; -} - -#ifndef NDEBUG -namespace llvm { - - template<> - struct GraphTraits<ModuleManager> { - using NodeRef = ModuleFile *; - using ChildIteratorType = llvm::SetVector<ModuleFile *>::const_iterator; - using nodes_iterator = pointer_iterator<ModuleManager::ModuleConstIterator>; - - static ChildIteratorType child_begin(NodeRef Node) { - return Node->Imports.begin(); - } - - static ChildIteratorType child_end(NodeRef Node) { - return Node->Imports.end(); - } - - static nodes_iterator nodes_begin(const ModuleManager &Manager) { - return nodes_iterator(Manager.begin()); - } - - static nodes_iterator nodes_end(const ModuleManager &Manager) { - return nodes_iterator(Manager.end()); - } - }; - - template<> - struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits { - explicit DOTGraphTraits(bool IsSimple = false) - : DefaultDOTGraphTraits(IsSimple) {} - - static bool renderGraphFromBottomUp() { return true; } - - std::string getNodeLabel(ModuleFile *M, const ModuleManager&) { - return M->ModuleName; - } - }; - -} // namespace llvm - -void ModuleManager::viewGraph() { - llvm::ViewGraph(*this, "Modules"); -} -#endif diff --git a/gnu/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h b/gnu/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h deleted file mode 100644 index ded7cd14644..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h +++ /dev/null @@ -1,347 +0,0 @@ -//===- MultiOnDiskHashTable.h - Merged set of hash tables -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides a hash table data structure suitable for incremental and -// distributed storage across a set of files. -// -// Multiple hash tables from different files are implicitly merged to improve -// performance, and on reload the merged table will override those from other -// files. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H -#define LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/TinyPtrVector.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/EndianStream.h" -#include "llvm/Support/OnDiskHashTable.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cstdint> -#include <vector> - -namespace clang { -namespace serialization { - -/// A collection of on-disk hash tables, merged when relevant for performance. -template<typename Info> class MultiOnDiskHashTable { -public: - /// A handle to a file, used when overriding tables. - using file_type = typename Info::file_type; - - /// A pointer to an on-disk representation of the hash table. - using storage_type = const unsigned char *; - - using external_key_type = typename Info::external_key_type; - using internal_key_type = typename Info::internal_key_type; - using data_type = typename Info::data_type; - using data_type_builder = typename Info::data_type_builder; - using hash_value_type = unsigned; - -private: - /// The generator is permitted to read our merged table. - template<typename ReaderInfo, typename WriterInfo> - friend class MultiOnDiskHashTableGenerator; - - /// A hash table stored on disk. - struct OnDiskTable { - using HashTable = llvm::OnDiskIterableChainedHashTable<Info>; - - file_type File; - HashTable Table; - - OnDiskTable(file_type File, unsigned NumBuckets, unsigned NumEntries, - storage_type Buckets, storage_type Payload, storage_type Base, - const Info &InfoObj) - : File(File), - Table(NumBuckets, NumEntries, Buckets, Payload, Base, InfoObj) {} - }; - - struct MergedTable { - std::vector<file_type> Files; - llvm::DenseMap<internal_key_type, data_type> Data; - }; - - using Table = llvm::PointerUnion<OnDiskTable *, MergedTable *>; - using TableVector = llvm::TinyPtrVector<void *>; - - /// The current set of on-disk and merged tables. - /// We manually store the opaque value of the Table because TinyPtrVector - /// can't cope with holding a PointerUnion directly. - /// There can be at most one MergedTable in this vector, and if present, - /// it is the first table. - TableVector Tables; - - /// Files corresponding to overridden tables that we've not yet - /// discarded. - llvm::TinyPtrVector<file_type> PendingOverrides; - - struct AsOnDiskTable { - using result_type = OnDiskTable *; - - result_type operator()(void *P) const { - return Table::getFromOpaqueValue(P).template get<OnDiskTable *>(); - } - }; - - using table_iterator = - llvm::mapped_iterator<TableVector::iterator, AsOnDiskTable>; - using table_range = llvm::iterator_range<table_iterator>; - - /// The current set of on-disk tables. - table_range tables() { - auto Begin = Tables.begin(), End = Tables.end(); - if (getMergedTable()) - ++Begin; - return llvm::make_range(llvm::map_iterator(Begin, AsOnDiskTable()), - llvm::map_iterator(End, AsOnDiskTable())); - } - - MergedTable *getMergedTable() const { - // If we already have a merged table, it's the first one. - return Tables.empty() ? nullptr : Table::getFromOpaqueValue(*Tables.begin()) - .template dyn_cast<MergedTable*>(); - } - - /// Delete all our current on-disk tables. - void clear() { - for (auto *T : tables()) - delete T; - if (auto *M = getMergedTable()) - delete M; - Tables.clear(); - } - - void removeOverriddenTables() { - llvm::DenseSet<file_type> Files; - Files.insert(PendingOverrides.begin(), PendingOverrides.end()); - // Explicitly capture Files to work around an MSVC 2015 rejects-valid bug. - auto ShouldRemove = [&Files](void *T) -> bool { - auto *ODT = Table::getFromOpaqueValue(T).template get<OnDiskTable *>(); - bool Remove = Files.count(ODT->File); - if (Remove) - delete ODT; - return Remove; - }; - Tables.erase(std::remove_if(tables().begin().getCurrent(), Tables.end(), - ShouldRemove), - Tables.end()); - PendingOverrides.clear(); - } - - void condense() { - MergedTable *Merged = getMergedTable(); - if (!Merged) - Merged = new MergedTable; - - // Read in all the tables and merge them together. - // FIXME: Be smarter about which tables we merge. - for (auto *ODT : tables()) { - auto &HT = ODT->Table; - Info &InfoObj = HT.getInfoObj(); - - for (auto I = HT.data_begin(), E = HT.data_end(); I != E; ++I) { - auto *LocalPtr = I.getItem(); - - // FIXME: Don't rely on the OnDiskHashTable format here. - auto L = InfoObj.ReadKeyDataLength(LocalPtr); - const internal_key_type &Key = InfoObj.ReadKey(LocalPtr, L.first); - data_type_builder ValueBuilder(Merged->Data[Key]); - InfoObj.ReadDataInto(Key, LocalPtr + L.first, L.second, - ValueBuilder); - } - - Merged->Files.push_back(ODT->File); - delete ODT; - } - - Tables.clear(); - Tables.push_back(Table(Merged).getOpaqueValue()); - } - -public: - MultiOnDiskHashTable() = default; - - MultiOnDiskHashTable(MultiOnDiskHashTable &&O) - : Tables(std::move(O.Tables)), - PendingOverrides(std::move(O.PendingOverrides)) { - O.Tables.clear(); - } - - MultiOnDiskHashTable &operator=(MultiOnDiskHashTable &&O) { - if (&O == this) - return *this; - clear(); - Tables = std::move(O.Tables); - O.Tables.clear(); - PendingOverrides = std::move(O.PendingOverrides); - return *this; - } - - ~MultiOnDiskHashTable() { clear(); } - - /// Add the table \p Data loaded from file \p File. - void add(file_type File, storage_type Data, Info InfoObj = Info()) { - using namespace llvm::support; - - storage_type Ptr = Data; - - uint32_t BucketOffset = endian::readNext<uint32_t, little, unaligned>(Ptr); - - // Read the list of overridden files. - uint32_t NumFiles = endian::readNext<uint32_t, little, unaligned>(Ptr); - // FIXME: Add a reserve() to TinyPtrVector so that we don't need to make - // an additional copy. - llvm::SmallVector<file_type, 16> OverriddenFiles; - OverriddenFiles.reserve(NumFiles); - for (/**/; NumFiles != 0; --NumFiles) - OverriddenFiles.push_back(InfoObj.ReadFileRef(Ptr)); - PendingOverrides.insert(PendingOverrides.end(), OverriddenFiles.begin(), - OverriddenFiles.end()); - - // Read the OnDiskChainedHashTable header. - storage_type Buckets = Data + BucketOffset; - auto NumBucketsAndEntries = - OnDiskTable::HashTable::readNumBucketsAndEntries(Buckets); - - // Register the table. - Table NewTable = new OnDiskTable(File, NumBucketsAndEntries.first, - NumBucketsAndEntries.second, - Buckets, Ptr, Data, std::move(InfoObj)); - Tables.push_back(NewTable.getOpaqueValue()); - } - - /// Find and read the lookup results for \p EKey. - data_type find(const external_key_type &EKey) { - data_type Result; - - if (!PendingOverrides.empty()) - removeOverriddenTables(); - - if (Tables.size() > static_cast<unsigned>(Info::MaxTables)) - condense(); - - internal_key_type Key = Info::GetInternalKey(EKey); - auto KeyHash = Info::ComputeHash(Key); - - if (MergedTable *M = getMergedTable()) { - auto It = M->Data.find(Key); - if (It != M->Data.end()) - Result = It->second; - } - - data_type_builder ResultBuilder(Result); - - for (auto *ODT : tables()) { - auto &HT = ODT->Table; - auto It = HT.find_hashed(Key, KeyHash); - if (It != HT.end()) - HT.getInfoObj().ReadDataInto(Key, It.getDataPtr(), It.getDataLen(), - ResultBuilder); - } - - return Result; - } - - /// Read all the lookup results into a single value. This only makes - /// sense if merging values across keys is meaningful. - data_type findAll() { - data_type Result; - data_type_builder ResultBuilder(Result); - - if (!PendingOverrides.empty()) - removeOverriddenTables(); - - if (MergedTable *M = getMergedTable()) { - for (auto &KV : M->Data) - Info::MergeDataInto(KV.second, ResultBuilder); - } - - for (auto *ODT : tables()) { - auto &HT = ODT->Table; - Info &InfoObj = HT.getInfoObj(); - for (auto I = HT.data_begin(), E = HT.data_end(); I != E; ++I) { - auto *LocalPtr = I.getItem(); - - // FIXME: Don't rely on the OnDiskHashTable format here. - auto L = InfoObj.ReadKeyDataLength(LocalPtr); - const internal_key_type &Key = InfoObj.ReadKey(LocalPtr, L.first); - InfoObj.ReadDataInto(Key, LocalPtr + L.first, L.second, ResultBuilder); - } - } - - return Result; - } -}; - -/// Writer for the on-disk hash table. -template<typename ReaderInfo, typename WriterInfo> -class MultiOnDiskHashTableGenerator { - using BaseTable = MultiOnDiskHashTable<ReaderInfo>; - using Generator = llvm::OnDiskChainedHashTableGenerator<WriterInfo>; - - Generator Gen; - -public: - MultiOnDiskHashTableGenerator() : Gen() {} - - void insert(typename WriterInfo::key_type_ref Key, - typename WriterInfo::data_type_ref Data, WriterInfo &Info) { - Gen.insert(Key, Data, Info); - } - - void emit(llvm::SmallVectorImpl<char> &Out, WriterInfo &Info, - const BaseTable *Base) { - using namespace llvm::support; - - llvm::raw_svector_ostream OutStream(Out); - - // Write our header information. - { - endian::Writer Writer(OutStream, little); - - // Reserve four bytes for the bucket offset. - Writer.write<uint32_t>(0); - - if (auto *Merged = Base ? Base->getMergedTable() : nullptr) { - // Write list of overridden files. - Writer.write<uint32_t>(Merged->Files.size()); - for (const auto &F : Merged->Files) - Info.EmitFileRef(OutStream, F); - - // Add all merged entries from Base to the generator. - for (auto &KV : Merged->Data) { - if (!Gen.contains(KV.first, Info)) - Gen.insert(KV.first, Info.ImportData(KV.second), Info); - } - } else { - Writer.write<uint32_t>(0); - } - } - - // Write the table itself. - uint32_t BucketOffset = Gen.Emit(OutStream, Info); - - // Replace the first four bytes with the bucket offset. - endian::write32le(Out.data(), BucketOffset); - } -}; - -} // namespace serialization -} // namespace clang - -#endif // LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H diff --git a/gnu/llvm/tools/clang/lib/Serialization/PCHContainerOperations.cpp b/gnu/llvm/tools/clang/lib/Serialization/PCHContainerOperations.cpp deleted file mode 100644 index fbc613efeb6..00000000000 --- a/gnu/llvm/tools/clang/lib/Serialization/PCHContainerOperations.cpp +++ /dev/null @@ -1,69 +0,0 @@ -//=== Serialization/PCHContainerOperations.cpp - PCH Containers -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines PCHContainerOperations and RawPCHContainerOperation. -// -//===----------------------------------------------------------------------===// - -#include "clang/Serialization/PCHContainerOperations.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/Lex/ModuleLoader.h" -#include "llvm/Bitcode/BitstreamReader.h" -#include "llvm/Support/raw_ostream.h" -#include <utility> - -using namespace clang; - -PCHContainerWriter::~PCHContainerWriter() {} -PCHContainerReader::~PCHContainerReader() {} - -namespace { - -/// A PCHContainerGenerator that writes out the PCH to a flat file. -class RawPCHContainerGenerator : public ASTConsumer { - std::shared_ptr<PCHBuffer> Buffer; - std::unique_ptr<raw_pwrite_stream> OS; - -public: - RawPCHContainerGenerator(std::unique_ptr<llvm::raw_pwrite_stream> OS, - std::shared_ptr<PCHBuffer> Buffer) - : Buffer(std::move(Buffer)), OS(std::move(OS)) {} - - ~RawPCHContainerGenerator() override = default; - - void HandleTranslationUnit(ASTContext &Ctx) override { - if (Buffer->IsComplete) { - // Make sure it hits disk now. - *OS << Buffer->Data; - OS->flush(); - } - // Free the space of the temporary buffer. - llvm::SmallVector<char, 0> Empty; - Buffer->Data = std::move(Empty); - } -}; - -} // anonymous namespace - -std::unique_ptr<ASTConsumer> RawPCHContainerWriter::CreatePCHContainerGenerator( - CompilerInstance &CI, const std::string &MainFileName, - const std::string &OutputFileName, std::unique_ptr<llvm::raw_pwrite_stream> OS, - std::shared_ptr<PCHBuffer> Buffer) const { - return llvm::make_unique<RawPCHContainerGenerator>(std::move(OS), Buffer); -} - -StringRef -RawPCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer) const { - return Buffer.getBuffer(); -} - -PCHContainerOperations::PCHContainerOperations() { - registerWriter(llvm::make_unique<RawPCHContainerWriter>()); - registerReader(llvm::make_unique<RawPCHContainerReader>()); -} |
