aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-12-20 19:53:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-12-20 19:53:05 +0000
commit0b57cec536236d46e3dba9bd041533462f33dbb7 (patch)
tree56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
parent718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff)
Notes
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp516
1 files changed, 0 insertions, 516 deletions
diff --git a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
deleted file mode 100644
index 115256db4809..000000000000
--- a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
+++ /dev/null
@@ -1,516 +0,0 @@
-//===- PreprocessingRecord.cpp - Record of Preprocessing ------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the PreprocessingRecord class, which maintains a record
-// of what occurred during preprocessing, and its helpers.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Lex/PreprocessingRecord.h"
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/LLVM.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/TokenKinds.h"
-#include "clang/Lex/MacroInfo.h"
-#include "clang/Lex/Token.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/Support/Capacity.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <cstring>
-#include <iterator>
-#include <utility>
-#include <vector>
-
-using namespace clang;
-
-ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() =
- default;
-
-InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
- InclusionKind Kind, StringRef FileName,
- bool InQuotes, bool ImportedModule,
- const FileEntry *File, SourceRange Range)
- : PreprocessingDirective(InclusionDirectiveKind, Range), InQuotes(InQuotes),
- Kind(Kind), ImportedModule(ImportedModule), File(File) {
- char *Memory = (char *)PPRec.Allocate(FileName.size() + 1, alignof(char));
- memcpy(Memory, FileName.data(), FileName.size());
- Memory[FileName.size()] = 0;
- this->FileName = StringRef(Memory, FileName.size());
-}
-
-PreprocessingRecord::PreprocessingRecord(SourceManager &SM) : SourceMgr(SM) {}
-
-/// Returns a pair of [Begin, End) iterators of preprocessed entities
-/// that source range \p Range encompasses.
-llvm::iterator_range<PreprocessingRecord::iterator>
-PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) {
- if (Range.isInvalid())
- return llvm::make_range(iterator(), iterator());
-
- if (CachedRangeQuery.Range == Range) {
- return llvm::make_range(iterator(this, CachedRangeQuery.Result.first),
- iterator(this, CachedRangeQuery.Result.second));
- }
-
- std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range);
-
- CachedRangeQuery.Range = Range;
- CachedRangeQuery.Result = Res;
-
- return llvm::make_range(iterator(this, Res.first),
- iterator(this, Res.second));
-}
-
-static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID,
- SourceManager &SM) {
- assert(FID.isValid());
- if (!PPE)
- return false;
-
- SourceLocation Loc = PPE->getSourceRange().getBegin();
- if (Loc.isInvalid())
- return false;
-
- return SM.isInFileID(SM.getFileLoc(Loc), FID);
-}
-
-/// Returns true if the preprocessed entity that \arg PPEI iterator
-/// points to is coming from the file \arg FID.
-///
-/// Can be used to avoid implicit deserializations of preallocated
-/// preprocessed entities if we only care about entities of a specific file
-/// and not from files \#included in the range given at
-/// \see getPreprocessedEntitiesInRange.
-bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) {
- if (FID.isInvalid())
- return false;
-
- int Pos = std::distance(iterator(this, 0), PPEI);
- if (Pos < 0) {
- if (unsigned(-Pos-1) >= LoadedPreprocessedEntities.size()) {
- assert(0 && "Out-of bounds loaded preprocessed entity");
- return false;
- }
- assert(ExternalSource && "No external source to load from");
- unsigned LoadedIndex = LoadedPreprocessedEntities.size()+Pos;
- if (PreprocessedEntity *PPE = LoadedPreprocessedEntities[LoadedIndex])
- return isPreprocessedEntityIfInFileID(PPE, FID, SourceMgr);
-
- // See if the external source can see if the entity is in the file without
- // deserializing it.
- Optional<bool> IsInFile =
- ExternalSource->isPreprocessedEntityInFileID(LoadedIndex, FID);
- if (IsInFile.hasValue())
- return IsInFile.getValue();
-
- // The external source did not provide a definite answer, go and deserialize
- // the entity to check it.
- return isPreprocessedEntityIfInFileID(
- getLoadedPreprocessedEntity(LoadedIndex),
- FID, SourceMgr);
- }
-
- if (unsigned(Pos) >= PreprocessedEntities.size()) {
- assert(0 && "Out-of bounds local preprocessed entity");
- return false;
- }
- return isPreprocessedEntityIfInFileID(PreprocessedEntities[Pos],
- FID, SourceMgr);
-}
-
-/// Returns a pair of [Begin, End) iterators of preprocessed entities
-/// that source range \arg R encompasses.
-std::pair<int, int>
-PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(SourceRange Range) {
- assert(Range.isValid());
- assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
-
- std::pair<unsigned, unsigned>
- Local = findLocalPreprocessedEntitiesInRange(Range);
-
- // Check if range spans local entities.
- if (!ExternalSource || SourceMgr.isLocalSourceLocation(Range.getBegin()))
- return std::make_pair(Local.first, Local.second);
-
- std::pair<unsigned, unsigned>
- Loaded = ExternalSource->findPreprocessedEntitiesInRange(Range);
-
- // Check if range spans local entities.
- if (Loaded.first == Loaded.second)
- return std::make_pair(Local.first, Local.second);
-
- unsigned TotalLoaded = LoadedPreprocessedEntities.size();
-
- // Check if range spans loaded entities.
- if (Local.first == Local.second)
- return std::make_pair(int(Loaded.first)-TotalLoaded,
- int(Loaded.second)-TotalLoaded);
-
- // Range spands loaded and local entities.
- return std::make_pair(int(Loaded.first)-TotalLoaded, Local.second);
-}
-
-std::pair<unsigned, unsigned>
-PreprocessingRecord::findLocalPreprocessedEntitiesInRange(
- SourceRange Range) const {
- if (Range.isInvalid())
- return std::make_pair(0,0);
- assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
-
- unsigned Begin = findBeginLocalPreprocessedEntity(Range.getBegin());
- unsigned End = findEndLocalPreprocessedEntity(Range.getEnd());
- return std::make_pair(Begin, End);
-}
-
-namespace {
-
-template <SourceLocation (SourceRange::*getRangeLoc)() const>
-struct PPEntityComp {
- const SourceManager &SM;
-
- explicit PPEntityComp(const SourceManager &SM) : SM(SM) {}
-
- bool operator()(PreprocessedEntity *L, PreprocessedEntity *R) const {
- SourceLocation LHS = getLoc(L);
- SourceLocation RHS = getLoc(R);
- return SM.isBeforeInTranslationUnit(LHS, RHS);
- }
-
- bool operator()(PreprocessedEntity *L, SourceLocation RHS) const {
- SourceLocation LHS = getLoc(L);
- return SM.isBeforeInTranslationUnit(LHS, RHS);
- }
-
- bool operator()(SourceLocation LHS, PreprocessedEntity *R) const {
- SourceLocation RHS = getLoc(R);
- return SM.isBeforeInTranslationUnit(LHS, RHS);
- }
-
- SourceLocation getLoc(PreprocessedEntity *PPE) const {
- SourceRange Range = PPE->getSourceRange();
- return (Range.*getRangeLoc)();
- }
-};
-
-} // namespace
-
-unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity(
- SourceLocation Loc) const {
- if (SourceMgr.isLoadedSourceLocation(Loc))
- return 0;
-
- size_t Count = PreprocessedEntities.size();
- size_t Half;
- std::vector<PreprocessedEntity *>::const_iterator
- First = PreprocessedEntities.begin();
- std::vector<PreprocessedEntity *>::const_iterator I;
-
- // 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;
- I = First;
- std::advance(I, Half);
- if (SourceMgr.isBeforeInTranslationUnit((*I)->getSourceRange().getEnd(),
- Loc)){
- First = I;
- ++First;
- Count = Count - Half - 1;
- } else
- Count = Half;
- }
-
- return First - PreprocessedEntities.begin();
-}
-
-unsigned
-PreprocessingRecord::findEndLocalPreprocessedEntity(SourceLocation Loc) const {
- if (SourceMgr.isLoadedSourceLocation(Loc))
- return 0;
-
- auto I = llvm::upper_bound(PreprocessedEntities, Loc,
- PPEntityComp<&SourceRange::getBegin>(SourceMgr));
- return I - PreprocessedEntities.begin();
-}
-
-PreprocessingRecord::PPEntityID
-PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
- assert(Entity);
- SourceLocation BeginLoc = Entity->getSourceRange().getBegin();
-
- if (isa<MacroDefinitionRecord>(Entity)) {
- assert((PreprocessedEntities.empty() ||
- !SourceMgr.isBeforeInTranslationUnit(
- BeginLoc,
- PreprocessedEntities.back()->getSourceRange().getBegin())) &&
- "a macro definition was encountered out-of-order");
- PreprocessedEntities.push_back(Entity);
- return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
- }
-
- // Check normal case, this entity begin location is after the previous one.
- if (PreprocessedEntities.empty() ||
- !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
- PreprocessedEntities.back()->getSourceRange().getBegin())) {
- PreprocessedEntities.push_back(Entity);
- return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
- }
-
- // The entity's location is not after the previous one; this can happen with
- // include directives that form the filename using macros, e.g:
- // "#include MACRO(STUFF)"
- // or with macro expansions inside macro arguments where the arguments are
- // not expanded in the same order as listed, e.g:
- // \code
- // #define M1 1
- // #define M2 2
- // #define FM(x,y) y x
- // FM(M1, M2)
- // \endcode
-
- using pp_iter = std::vector<PreprocessedEntity *>::iterator;
-
- // Usually there are few macro expansions when defining the filename, do a
- // linear search for a few entities.
- unsigned count = 0;
- for (pp_iter RI = PreprocessedEntities.end(),
- Begin = PreprocessedEntities.begin();
- RI != Begin && count < 4; --RI, ++count) {
- pp_iter I = RI;
- --I;
- if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc,
- (*I)->getSourceRange().getBegin())) {
- pp_iter insertI = PreprocessedEntities.insert(RI, Entity);
- return getPPEntityID(insertI - PreprocessedEntities.begin(),
- /*isLoaded=*/false);
- }
- }
-
- // Linear search unsuccessful. Do a binary search.
- pp_iter I =
- llvm::upper_bound(PreprocessedEntities, BeginLoc,
- PPEntityComp<&SourceRange::getBegin>(SourceMgr));
- pp_iter insertI = PreprocessedEntities.insert(I, Entity);
- return getPPEntityID(insertI - PreprocessedEntities.begin(),
- /*isLoaded=*/false);
-}
-
-void PreprocessingRecord::SetExternalSource(
- ExternalPreprocessingRecordSource &Source) {
- assert(!ExternalSource &&
- "Preprocessing record already has an external source");
- ExternalSource = &Source;
-}
-
-unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
- unsigned Result = LoadedPreprocessedEntities.size();
- LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
- + NumEntities);
- return Result;
-}
-
-unsigned PreprocessingRecord::allocateSkippedRanges(unsigned NumRanges) {
- unsigned Result = SkippedRanges.size();
- SkippedRanges.resize(SkippedRanges.size() + NumRanges);
- SkippedRangesAllLoaded = false;
- return Result;
-}
-
-void PreprocessingRecord::ensureSkippedRangesLoaded() {
- if (SkippedRangesAllLoaded || !ExternalSource)
- return;
- for (unsigned Index = 0; Index != SkippedRanges.size(); ++Index) {
- if (SkippedRanges[Index].isInvalid())
- SkippedRanges[Index] = ExternalSource->ReadSkippedRange(Index);
- }
- SkippedRangesAllLoaded = true;
-}
-
-void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
- MacroDefinitionRecord *Def) {
- MacroDefinitions[Macro] = Def;
-}
-
-/// Retrieve the preprocessed entity at the given ID.
-PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
- if (PPID.ID < 0) {
- unsigned Index = -PPID.ID - 1;
- assert(Index < LoadedPreprocessedEntities.size() &&
- "Out-of bounds loaded preprocessed entity");
- return getLoadedPreprocessedEntity(Index);
- }
-
- if (PPID.ID == 0)
- return nullptr;
- unsigned Index = PPID.ID - 1;
- assert(Index < PreprocessedEntities.size() &&
- "Out-of bounds local preprocessed entity");
- return PreprocessedEntities[Index];
-}
-
-/// Retrieve the loaded preprocessed entity at the given index.
-PreprocessedEntity *
-PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) {
- assert(Index < LoadedPreprocessedEntities.size() &&
- "Out-of bounds loaded preprocessed entity");
- assert(ExternalSource && "No external source to load from");
- PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index];
- if (!Entity) {
- Entity = ExternalSource->ReadPreprocessedEntity(Index);
- if (!Entity) // Failed to load.
- Entity = new (*this)
- PreprocessedEntity(PreprocessedEntity::InvalidKind, SourceRange());
- }
- return Entity;
-}
-
-MacroDefinitionRecord *
-PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
- llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *>::iterator Pos =
- MacroDefinitions.find(MI);
- if (Pos == MacroDefinitions.end())
- return nullptr;
-
- return Pos->second;
-}
-
-void PreprocessingRecord::addMacroExpansion(const Token &Id,
- const MacroInfo *MI,
- SourceRange Range) {
- // We don't record nested macro expansions.
- if (Id.getLocation().isMacroID())
- return;
-
- if (MI->isBuiltinMacro())
- addPreprocessedEntity(new (*this)
- MacroExpansion(Id.getIdentifierInfo(), Range));
- else if (MacroDefinitionRecord *Def = findMacroDefinition(MI))
- addPreprocessedEntity(new (*this) MacroExpansion(Def, Range));
-}
-
-void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok,
- const MacroDefinition &MD) {
- // This is not actually a macro expansion but record it as a macro reference.
- if (MD)
- addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
- MacroNameTok.getLocation());
-}
-
-void PreprocessingRecord::Ifndef(SourceLocation Loc, const Token &MacroNameTok,
- const MacroDefinition &MD) {
- // This is not actually a macro expansion but record it as a macro reference.
- if (MD)
- addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
- MacroNameTok.getLocation());
-}
-
-void PreprocessingRecord::Defined(const Token &MacroNameTok,
- const MacroDefinition &MD,
- SourceRange Range) {
- // This is not actually a macro expansion but record it as a macro reference.
- if (MD)
- addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
- MacroNameTok.getLocation());
-}
-
-void PreprocessingRecord::SourceRangeSkipped(SourceRange Range,
- SourceLocation EndifLoc) {
- assert(Range.isValid());
- SkippedRanges.emplace_back(Range.getBegin(), EndifLoc);
-}
-
-void PreprocessingRecord::MacroExpands(const Token &Id,
- const MacroDefinition &MD,
- SourceRange Range,
- const MacroArgs *Args) {
- addMacroExpansion(Id, MD.getMacroInfo(), Range);
-}
-
-void PreprocessingRecord::MacroDefined(const Token &Id,
- const MacroDirective *MD) {
- const MacroInfo *MI = MD->getMacroInfo();
- SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
- MacroDefinitionRecord *Def =
- new (*this) MacroDefinitionRecord(Id.getIdentifierInfo(), R);
- addPreprocessedEntity(Def);
- MacroDefinitions[MI] = Def;
-}
-
-void PreprocessingRecord::MacroUndefined(const Token &Id,
- const MacroDefinition &MD,
- const MacroDirective *Undef) {
- MD.forAllDefinitions([&](MacroInfo *MI) { MacroDefinitions.erase(MI); });
-}
-
-void PreprocessingRecord::InclusionDirective(
- SourceLocation HashLoc,
- const Token &IncludeTok,
- StringRef FileName,
- bool IsAngled,
- CharSourceRange FilenameRange,
- const FileEntry *File,
- StringRef SearchPath,
- StringRef RelativePath,
- const Module *Imported,
- SrcMgr::CharacteristicKind FileType) {
- InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
-
- switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
- case tok::pp_include:
- Kind = InclusionDirective::Include;
- break;
-
- case tok::pp_import:
- Kind = InclusionDirective::Import;
- break;
-
- case tok::pp_include_next:
- Kind = InclusionDirective::IncludeNext;
- break;
-
- case tok::pp___include_macros:
- Kind = InclusionDirective::IncludeMacros;
- break;
-
- default:
- llvm_unreachable("Unknown include directive kind");
- }
-
- SourceLocation EndLoc;
- if (!IsAngled) {
- EndLoc = FilenameRange.getBegin();
- } else {
- EndLoc = FilenameRange.getEnd();
- if (FilenameRange.isCharRange())
- EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects
- // a token range.
- }
- clang::InclusionDirective *ID =
- new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled,
- (bool)Imported, File,
- SourceRange(HashLoc, EndLoc));
- addPreprocessedEntity(ID);
-}
-
-size_t PreprocessingRecord::getTotalMemory() const {
- return BumpAlloc.getTotalMemory()
- + llvm::capacity_in_bytes(MacroDefinitions)
- + llvm::capacity_in_bytes(PreprocessedEntities)
- + llvm::capacity_in_bytes(LoadedPreprocessedEntities)
- + llvm::capacity_in_bytes(SkippedRanges);
-}