|
@@ -17,6 +17,7 @@
|
|
#include "clang/Lex/PPCallbacks.h"
|
|
#include "clang/Lex/PPCallbacks.h"
|
|
#include "clang/Basic/SourceLocation.h"
|
|
#include "clang/Basic/SourceLocation.h"
|
|
#include "clang/Basic/IdentifierTable.h"
|
|
#include "clang/Basic/IdentifierTable.h"
|
|
|
|
+#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/Optional.h"
|
|
#include "llvm/ADT/Optional.h"
|
|
#include "llvm/Support/Allocator.h"
|
|
#include "llvm/Support/Allocator.h"
|
|
@@ -299,6 +300,44 @@ namespace clang {
|
|
/// and are referenced by the iterator using negative indices.
|
|
/// and are referenced by the iterator using negative indices.
|
|
std::vector<PreprocessedEntity *> LoadedPreprocessedEntities;
|
|
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.
|
|
/// \brief Global (loaded or local) ID for a preprocessed entity.
|
|
/// Negative values are used to indicate preprocessed entities
|
|
/// Negative values are used to indicate preprocessed entities
|
|
/// loaded from the external source while non-negative values are used to
|
|
/// loaded from the external source while non-negative values are used to
|
|
@@ -349,7 +388,7 @@ namespace clang {
|
|
|
|
|
|
public:
|
|
public:
|
|
/// \brief Construct a new preprocessing record.
|
|
/// \brief Construct a new preprocessing record.
|
|
- explicit PreprocessingRecord(SourceManager &SM);
|
|
|
|
|
|
+ PreprocessingRecord(SourceManager &SM, bool RecordConditionalDirectives);
|
|
|
|
|
|
/// \brief Allocate memory in the preprocessing record.
|
|
/// \brief Allocate memory in the preprocessing record.
|
|
void *Allocate(unsigned Size, unsigned Align = 8) {
|
|
void *Allocate(unsigned Size, unsigned Align = 8) {
|
|
@@ -517,7 +556,25 @@ namespace clang {
|
|
|
|
|
|
/// \brief Add a new preprocessed entity to this record.
|
|
/// \brief Add a new preprocessed entity to this record.
|
|
void addPreprocessedEntity(PreprocessedEntity *Entity);
|
|
void 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.
|
|
/// \brief Set the external source for preprocessed entities.
|
|
void SetExternalSource(ExternalPreprocessingRecordSource &Source);
|
|
void SetExternalSource(ExternalPreprocessingRecordSource &Source);
|
|
|
|
|
|
@@ -530,6 +587,7 @@ namespace clang {
|
|
/// \c MacroInfo.
|
|
/// \c MacroInfo.
|
|
MacroDefinition *findMacroDefinition(const MacroInfo *MI);
|
|
MacroDefinition *findMacroDefinition(const MacroInfo *MI);
|
|
|
|
|
|
|
|
+ private:
|
|
virtual void MacroExpands(const Token &Id, const MacroInfo* MI,
|
|
virtual void MacroExpands(const Token &Id, const MacroInfo* MI,
|
|
SourceRange Range);
|
|
SourceRange Range);
|
|
virtual void MacroDefined(const Token &Id, const MacroInfo *MI);
|
|
virtual void MacroDefined(const Token &Id, const MacroInfo *MI);
|
|
@@ -542,8 +600,14 @@ namespace clang {
|
|
SourceLocation EndLoc,
|
|
SourceLocation EndLoc,
|
|
StringRef SearchPath,
|
|
StringRef SearchPath,
|
|
StringRef RelativePath);
|
|
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);
|
|
|
|
|
|
- private:
|
|
|
|
/// \brief Cached result of the last \see getPreprocessedEntitiesInRange
|
|
/// \brief Cached result of the last \see getPreprocessedEntitiesInRange
|
|
/// query.
|
|
/// query.
|
|
struct {
|
|
struct {
|