summaryrefslogtreecommitdiffstats
path: root/include/clang/Lex/PreprocessingRecord.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Lex/PreprocessingRecord.h')
-rw-r--r--include/clang/Lex/PreprocessingRecord.h111
1 files changed, 102 insertions, 9 deletions
diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h
index 53da19e..45e3a5d 100644
--- a/include/clang/Lex/PreprocessingRecord.h
+++ b/include/clang/Lex/PreprocessingRecord.h
@@ -17,8 +17,11 @@
#include "clang/Lex/PPCallbacks.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Compiler.h"
#include <vector>
namespace clang {
@@ -85,7 +88,7 @@ namespace clang {
/// \brief Retrieve the source range that covers this entire preprocessed
/// entity.
- SourceRange getSourceRange() const { return Range; }
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
/// \brief Returns true if there was a problem loading the preprocessed
/// entity.
@@ -269,6 +272,13 @@ namespace clang {
/// preprocessed entities that \arg Range encompasses.
virtual std::pair<unsigned, unsigned>
findPreprocessedEntitiesInRange(SourceRange Range) = 0;
+
+ /// \brief Optionally returns true or false if the preallocated preprocessed
+ /// entity with index \arg Index came from file \arg FID.
+ virtual llvm::Optional<bool> isPreprocessedEntityInFileID(unsigned Index,
+ FileID FID) {
+ return llvm::Optional<bool>();
+ }
};
/// \brief A record of the steps taken while preprocessing a source file,
@@ -276,10 +286,6 @@ namespace clang {
/// expanded, etc.
class PreprocessingRecord : public PPCallbacks {
SourceManager &SourceMgr;
-
- /// \brief Whether we should include nested macro expansions in
- /// the preprocessing record.
- bool IncludeNestedMacroExpansions;
/// \brief Allocator used to store preprocessing objects.
llvm::BumpPtrAllocator BumpAlloc;
@@ -295,6 +301,44 @@ namespace clang {
/// and are referenced by the iterator using negative indices.
std::vector<PreprocessedEntity *> LoadedPreprocessedEntities;
+ bool RecordCondDirectives;
+ unsigned CondDirectiveNextIdx;
+ SmallVector<unsigned, 6> CondDirectiveStack;
+
+ class CondDirectiveLoc {
+ SourceLocation Loc;
+ unsigned Idx;
+
+ public:
+ CondDirectiveLoc(SourceLocation Loc, unsigned Idx) : Loc(Loc), Idx(Idx) {}
+
+ SourceLocation getLoc() const { return Loc; }
+ unsigned getIdx() const { return Idx; }
+
+ class Comp {
+ SourceManager &SM;
+ public:
+ explicit Comp(SourceManager &SM) : SM(SM) {}
+ bool operator()(const CondDirectiveLoc &LHS,
+ const CondDirectiveLoc &RHS) {
+ return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS.getLoc());
+ }
+ bool operator()(const CondDirectiveLoc &LHS, SourceLocation RHS) {
+ return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS);
+ }
+ bool operator()(SourceLocation LHS, const CondDirectiveLoc &RHS) {
+ return SM.isBeforeInTranslationUnit(LHS, RHS.getLoc());
+ }
+ };
+ };
+
+ typedef std::vector<CondDirectiveLoc> CondDirectiveLocsTy;
+ /// \brief The locations of conditional directives in source order.
+ CondDirectiveLocsTy CondDirectiveLocs;
+
+ void addCondDirectiveLoc(CondDirectiveLoc DirLoc);
+ unsigned findCondDirectiveIdx(SourceLocation Loc) const;
+
/// \brief Global (loaded or local) ID for a preprocessed entity.
/// Negative values are used to indicate preprocessed entities
/// loaded from the external source while non-negative values are used to
@@ -345,7 +389,7 @@ namespace clang {
public:
/// \brief Construct a new preprocessing record.
- PreprocessingRecord(SourceManager &SM, bool IncludeNestedMacroExpansions);
+ PreprocessingRecord(SourceManager &SM, bool RecordConditionalDirectives);
/// \brief Allocate memory in the preprocessing record.
void *Allocate(unsigned Size, unsigned Align = 8) {
@@ -386,7 +430,7 @@ namespace clang {
iterator() : Self(0), Position(0) { }
- iterator(PreprocessingRecord *Self, int Position)
+ iterator(PreprocessingRecord *Self, PPEntityID Position)
: Self(Self), Position(Position) { }
value_type operator*() const {
@@ -471,6 +515,7 @@ namespace clang {
X.Position -= D;
return X;
}
+ friend class PreprocessingRecord;
};
friend class iterator;
@@ -496,11 +541,41 @@ namespace clang {
/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
/// that source range \arg R encompasses.
+ ///
+ /// \param R the range to look for preprocessed entities.
+ ///
std::pair<iterator, iterator> getPreprocessedEntitiesInRange(SourceRange R);
+ /// \brief 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 isEntityInFileID(iterator PPEI, FileID FID);
+
/// \brief Add a new preprocessed entity to this record.
- void addPreprocessedEntity(PreprocessedEntity *Entity);
-
+ PPEntityID addPreprocessedEntity(PreprocessedEntity *Entity);
+
+ /// \brief Returns true if this PreprocessingRecord is keeping track of
+ /// conditional directives locations.
+ bool isRecordingConditionalDirectives() const {
+ return RecordCondDirectives;
+ }
+
+ /// \brief Returns true if the given range intersects with a conditional
+ /// directive. if a #if/#endif block is fully contained within the range,
+ /// this function will return false.
+ bool rangeIntersectsConditionalDirective(SourceRange Range) const;
+
+ /// \brief Returns true if the given locations are in different regions,
+ /// separated by conditional directive blocks.
+ bool areInDifferentConditionalDirectiveRegion(SourceLocation LHS,
+ SourceLocation RHS) const {
+ return findCondDirectiveIdx(LHS) != findCondDirectiveIdx(RHS);
+ }
+
/// \brief Set the external source for preprocessed entities.
void SetExternalSource(ExternalPreprocessingRecordSource &Source);
@@ -513,6 +588,7 @@ namespace clang {
/// \c MacroInfo.
MacroDefinition *findMacroDefinition(const MacroInfo *MI);
+ private:
virtual void MacroExpands(const Token &Id, const MacroInfo* MI,
SourceRange Range);
virtual void MacroDefined(const Token &Id, const MacroInfo *MI);
@@ -525,6 +601,23 @@ namespace clang {
SourceLocation EndLoc,
StringRef SearchPath,
StringRef RelativePath);
+ virtual void If(SourceLocation Loc, SourceRange ConditionRange);
+ virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
+ SourceLocation IfLoc);
+ virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok);
+ virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok);
+ virtual void Else(SourceLocation Loc, SourceLocation IfLoc);
+ virtual void Endif(SourceLocation Loc, SourceLocation IfLoc);
+
+ /// \brief Cached result of the last \see getPreprocessedEntitiesInRange
+ /// query.
+ struct {
+ SourceRange Range;
+ std::pair<PPEntityID, PPEntityID> Result;
+ } CachedRangeQuery;
+
+ std::pair<PPEntityID, PPEntityID>
+ getPreprocessedEntitiesInRangeSlow(SourceRange R);
friend class ASTReader;
friend class ASTWriter;
OpenPOWER on IntegriCloud