blob: b85609bf4e05bc8db5a967d5327b17fb1b623597 [file] [log] [blame]
//===- ASTRecordReader.h - Helper classes for reading AST -------*- C++ -*-===//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// This file defines classes that are useful in the implementation of
// the ASTReader.
#include "clang/AST/ASTContext.h"
#include "clang/AST/AbstractBasicReader.h"
#include "clang/Lex/Token.h"
#include "clang/Serialization/ASTReader.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
namespace clang {
class OMPTraitInfo;
class OMPChildren;
/// An object for streaming information from a record.
class ASTRecordReader
: public serialization::DataStreamBasicReader<ASTRecordReader> {
using ModuleFile = serialization::ModuleFile;
ASTReader *Reader;
ModuleFile *F;
unsigned Idx = 0;
ASTReader::RecordData Record;
using RecordData = ASTReader::RecordData;
using RecordDataImpl = ASTReader::RecordDataImpl;
/// Construct an ASTRecordReader that uses the default encoding scheme.
ASTRecordReader(ASTReader &Reader, ModuleFile &F)
: DataStreamBasicReader(Reader.getContext()), Reader(&Reader), F(&F) {}
/// Reads a record with id AbbrevID from Cursor, resetting the
/// internal state.
Expected<unsigned> readRecord(llvm::BitstreamCursor &Cursor,
unsigned AbbrevID);
/// Is this a module file for a module (rather than a PCH or similar).
bool isModule() const { return F->isModule(); }
/// Retrieve the AST context that this AST reader supplements.
ASTContext &getContext() { return Reader->getContext(); }
/// The current position in this record.
unsigned getIdx() const { return Idx; }
/// The length of this record.
size_t size() const { return Record.size(); }
/// An arbitrary index in this record.
const uint64_t &operator[](size_t N) { return Record[N]; }
/// Returns the last value in this record.
uint64_t back() { return Record.back(); }
/// Returns the current value in this record, and advances to the
/// next value.
uint64_t readInt() { return Record[Idx++]; }
ArrayRef<uint64_t> readIntArray(unsigned Len) {
auto Array = llvm::makeArrayRef(Record).slice(Idx, Len);
Idx += Len;
return Array;
/// Returns the current value in this record, without advancing.
uint64_t peekInt() { return Record[Idx]; }
/// Skips the specified number of values.
void skipInts(unsigned N) { Idx += N; }
/// Retrieve the global submodule ID its local ID number.
getGlobalSubmoduleID(unsigned LocalID) {
return Reader->getGlobalSubmoduleID(*F, LocalID);
/// Retrieve the submodule that corresponds to a global submodule ID.
Module *getSubmodule(serialization::SubmoduleID GlobalID) {
return Reader->getSubmodule(GlobalID);
/// Read the record that describes the lexical contents of a DC.
bool readLexicalDeclContextStorage(uint64_t Offset, DeclContext *DC) {
return Reader->ReadLexicalDeclContextStorage(*F, F->DeclsCursor, Offset,
/// Read the record that describes the visible contents of a DC.
bool readVisibleDeclContextStorage(uint64_t Offset,
serialization::DeclID ID) {
return Reader->ReadVisibleDeclContextStorage(*F, F->DeclsCursor, Offset,
ExplicitSpecifier readExplicitSpec() {
uint64_t Kind = readInt();
bool HasExpr = Kind & 0x1;
Kind = Kind >> 1;
return ExplicitSpecifier(HasExpr ? readExpr() : nullptr,
/// Read information about an exception specification (inherited).
//readExceptionSpecInfo(SmallVectorImpl<QualType> &ExceptionStorage);
/// Get the global offset corresponding to a local offset.
uint64_t getGlobalBitOffset(uint64_t LocalOffset) {
return Reader->getGlobalBitOffset(*F, LocalOffset);
/// Reads a statement.
Stmt *readStmt() { return Reader->ReadStmt(*F); }
Stmt *readStmtRef() { return readStmt(); /* FIXME: readSubStmt? */ }
/// Reads an expression.
Expr *readExpr() { return Reader->ReadExpr(*F); }
/// Reads a sub-statement operand during statement reading.
Stmt *readSubStmt() { return Reader->ReadSubStmt(); }
/// Reads a sub-expression operand during statement reading.
Expr *readSubExpr() { return Reader->ReadSubExpr(); }
/// Reads a declaration with the given local ID in the given module.
/// \returns The requested declaration, casted to the given return type.
template<typename T>
T *GetLocalDeclAs(uint32_t LocalID) {
return cast_or_null<T>(Reader->GetLocalDecl(*F, LocalID));
/// Reads a TemplateArgumentLocInfo appropriate for the
/// given TemplateArgument kind, advancing Idx.
readTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind);
/// Reads a TemplateArgumentLoc, advancing Idx.
TemplateArgumentLoc readTemplateArgumentLoc();
const ASTTemplateArgumentListInfo*
/// Reads a declarator info from the given record, advancing Idx.
TypeSourceInfo *readTypeSourceInfo();
/// Reads the location information for a type.
void readTypeLoc(TypeLoc TL);
/// Map a local type ID within a given AST file to a global type ID.
serialization::TypeID getGlobalTypeID(unsigned LocalID) const {
return Reader->getGlobalTypeID(*F, LocalID);
Qualifiers readQualifiers() {
return Qualifiers::fromOpaqueValue(readInt());
/// Read a type from the current position in the record.
QualType readType() {
return Reader->readType(*F, Record, Idx);
QualType readQualType() {
return readType();
/// Reads a declaration ID from the given position in this record.
/// \returns The declaration ID read from the record, adjusted to a global ID.
serialization::DeclID readDeclID() {
return Reader->ReadDeclID(*F, Record, Idx);
/// Reads a declaration from the given position in a record in the
/// given module, advancing Idx.
Decl *readDecl() {
return Reader->ReadDecl(*F, Record, Idx);
Decl *readDeclRef() {
return readDecl();
/// Reads a declaration from the given position in the record,
/// advancing Idx.
/// \returns The declaration read from this location, casted to the given
/// result type.
template<typename T>
T *readDeclAs() {
return Reader->ReadDeclAs<T>(*F, Record, Idx);
IdentifierInfo *readIdentifier() {
return Reader->readIdentifier(*F, Record, Idx);
/// Read a selector from the Record, advancing Idx.
Selector readSelector() {
return Reader->ReadSelector(*F, Record, Idx);
/// Read a declaration name, advancing Idx.
// DeclarationName readDeclarationName(); (inherited)
DeclarationNameLoc readDeclarationNameLoc(DeclarationName Name);
DeclarationNameInfo readDeclarationNameInfo();
void readQualifierInfo(QualifierInfo &Info);
/// Return a nested name specifier, advancing Idx.
// NestedNameSpecifier *readNestedNameSpecifier(); (inherited)
NestedNameSpecifierLoc readNestedNameSpecifierLoc();
/// Read a template name, advancing Idx.
// TemplateName readTemplateName(); (inherited)
/// Read a template argument, advancing Idx. (inherited)
// TemplateArgument readTemplateArgument();
using DataStreamBasicReader::readTemplateArgument;
TemplateArgument readTemplateArgument(bool Canonicalize) {
TemplateArgument Arg = readTemplateArgument();
if (Canonicalize) {
Arg = getContext().getCanonicalTemplateArgument(Arg);
return Arg;
/// Read a template parameter list, advancing Idx.
TemplateParameterList *readTemplateParameterList();
/// Read a template argument array, advancing Idx.
void readTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
bool Canonicalize = false);
/// Read a UnresolvedSet structure, advancing Idx.
void readUnresolvedSet(LazyASTUnresolvedSet &Set);
/// Read a C++ base specifier, advancing Idx.
CXXBaseSpecifier readCXXBaseSpecifier();
/// Read a CXXCtorInitializer array, advancing Idx.
CXXCtorInitializer **readCXXCtorInitializers();
CXXTemporary *readCXXTemporary() {
return Reader->ReadCXXTemporary(*F, Record, Idx);
/// Read an OMPTraitInfo object, advancing Idx.
OMPTraitInfo *readOMPTraitInfo();
/// Read an OpenMP clause, advancing Idx.
OMPClause *readOMPClause();
/// Read an OpenMP children, advancing Idx.
void readOMPChildren(OMPChildren *Data);
/// Read a source location, advancing Idx.
SourceLocation readSourceLocation() {
return Reader->ReadSourceLocation(*F, Record, Idx);
/// Read a source range, advancing Idx.
SourceRange readSourceRange() {
return Reader->ReadSourceRange(*F, Record, Idx);
/// Read an arbitrary constant value, advancing Idx.
// APValue readAPValue(); (inherited)
/// Read an integral value, advancing Idx.
// llvm::APInt readAPInt(); (inherited)
/// Read a signed integral value, advancing Idx.
// llvm::APSInt readAPSInt(); (inherited)
/// Read a floating-point value, advancing Idx.
llvm::APFloat readAPFloat(const llvm::fltSemantics &Sem);
/// Read a boolean value, advancing Idx.
bool readBool() { return readInt() != 0; }
/// Read a 32-bit unsigned value; required to satisfy BasicReader.
uint32_t readUInt32() {
return uint32_t(readInt());
/// Read a 64-bit unsigned value; required to satisfy BasicReader.
uint64_t readUInt64() {
return readInt();
/// Read a string, advancing Idx.
std::string readString() {
return Reader->ReadString(Record, Idx);
/// Read a path, advancing Idx.
std::string readPath() {
return Reader->ReadPath(*F, Record, Idx);
/// Read a version tuple, advancing Idx.
VersionTuple readVersionTuple() {
return ASTReader::ReadVersionTuple(Record, Idx);
/// Reads one attribute from the current stream position, advancing Idx.
Attr *readAttr();
/// Reads attributes from the current stream position, advancing Idx.
void readAttributes(AttrVec &Attrs);
/// Reads a token out of a record, advancing Idx.
Token readToken() {
return Reader->ReadToken(*F, Record, Idx);
void recordSwitchCaseID(SwitchCase *SC, unsigned ID) {
Reader->RecordSwitchCaseID(SC, ID);
/// Retrieve the switch-case statement with the given ID.
SwitchCase *getSwitchCaseWithID(unsigned ID) {
return Reader->getSwitchCaseWithID(ID);
/// Helper class that saves the current stream position and
/// then restores it when destroyed.
struct SavedStreamPosition {
explicit SavedStreamPosition(llvm::BitstreamCursor &Cursor)
: Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) {}
~SavedStreamPosition() {
if (llvm::Error Err = Cursor.JumpToBit(Offset))
"Cursor should always be able to go back, failed: " +
llvm::BitstreamCursor &Cursor;
uint64_t Offset;
inline void PCHValidator::Error(const char *Msg) {
} // namespace clang