diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
commit | 0b57cec536236d46e3dba9bd041533462f33dbb7 (patch) | |
tree | 56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp | |
parent | 718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff) |
Notes
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp | 516 |
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); -} |