Collect directives in PPCallback.
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
#include <clang/Tooling/Syntax/Tokens.h>
|
||||
#include <clang/Sema/Sema.h>
|
||||
|
||||
#include <Support/Support.h>
|
||||
|
||||
namespace std {
|
||||
|
||||
template <>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <Compiler/Clang.h>
|
||||
#include <Compiler/Directive.h>
|
||||
#include <Compiler/Resolver.h>
|
||||
|
||||
#include <Support/Error.h>
|
||||
|
||||
namespace clice {
|
||||
@@ -13,9 +15,11 @@ public:
|
||||
|
||||
ASTInfo(std::unique_ptr<clang::ASTFrontendAction> action,
|
||||
std::unique_ptr<clang::CompilerInstance> instance,
|
||||
std::unique_ptr<clang::syntax::TokenBuffer> tokBuf) :
|
||||
action(std::move(action)), instance(std::move(instance)), tokBuf_(std::move(tokBuf)) {
|
||||
resolver_ = std::make_unique<TemplateResolver>(this->instance->getSema());
|
||||
std::unique_ptr<clang::syntax::TokenBuffer> tokBuf,
|
||||
llvm::DenseMap<clang::FileID, Directive>&& directives) :
|
||||
action(std::move(action)), instance(std::move(instance)), m_TokBuf(std::move(tokBuf)),
|
||||
m_Directives(std::move(directives)) {
|
||||
m_Resolver = std::make_unique<TemplateResolver>(this->instance->getSema());
|
||||
}
|
||||
|
||||
ASTInfo(const ASTInfo&) = delete;
|
||||
@@ -50,19 +54,38 @@ public:
|
||||
}
|
||||
|
||||
clang::syntax::TokenBuffer& tokBuf() {
|
||||
assert(tokBuf_ && "Token buffer is not available");
|
||||
return *tokBuf_;
|
||||
assert(m_TokBuf && "Token buffer is not available");
|
||||
return *m_TokBuf;
|
||||
}
|
||||
|
||||
TemplateResolver& resolver() {
|
||||
return *resolver_;
|
||||
return *m_Resolver;
|
||||
}
|
||||
|
||||
auto& directives() {
|
||||
return m_Directives;
|
||||
}
|
||||
|
||||
Directive& directive(clang::FileID id) {
|
||||
return m_Directives[id];
|
||||
}
|
||||
|
||||
/// Get the length of the token at the given location.
|
||||
auto getTokenLength(clang::SourceLocation loc) {
|
||||
return clang::Lexer::MeasureTokenLength(loc, srcMgr(), instance->getLangOpts());
|
||||
}
|
||||
|
||||
/// Get the spelling of the token at the given location.
|
||||
llvm::StringRef getTokenSpelling(clang::SourceLocation loc) {
|
||||
return llvm::StringRef(srcMgr().getCharacterData(loc), getTokenLength(loc));
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<clang::ASTFrontendAction> action;
|
||||
std::unique_ptr<clang::CompilerInstance> instance;
|
||||
std::unique_ptr<clang::syntax::TokenBuffer> tokBuf_;
|
||||
std::unique_ptr<TemplateResolver> resolver_;
|
||||
std::unique_ptr<clang::syntax::TokenBuffer> m_TokBuf;
|
||||
std::unique_ptr<TemplateResolver> m_Resolver;
|
||||
llvm::DenseMap<clang::FileID, Directive> m_Directives;
|
||||
};
|
||||
|
||||
struct PCHInfo {
|
||||
|
||||
@@ -4,63 +4,68 @@
|
||||
|
||||
namespace clice {
|
||||
|
||||
/// Represents a full conditional preprocessing block, from #if to #endif.
|
||||
struct IfBlock {
|
||||
/// Represents a single conditional branch (e.g., #if, #ifdef, #elif).
|
||||
struct Branch {
|
||||
/// Location of the directive.
|
||||
/// NOTE: The `#` is a separate token and not necessarily adjacent.
|
||||
clang::SourceLocation location;
|
||||
struct Include {};
|
||||
|
||||
/// Location of the condition expression.
|
||||
clang::SourceLocation condition;
|
||||
|
||||
/// Evaluated value of the condition.
|
||||
clang::PPCallbacks::ConditionValueKind value;
|
||||
struct Condition {
|
||||
enum BranchKind : uint8_t {
|
||||
If = 0,
|
||||
Elif,
|
||||
Ifdef,
|
||||
Elifdef,
|
||||
Ifndef,
|
||||
Elifndef,
|
||||
Else,
|
||||
EndIf,
|
||||
};
|
||||
|
||||
/// Initial #if, #ifdef, or #ifndef directive.
|
||||
Branch if_;
|
||||
enum ConditionValue : uint8_t {
|
||||
True = 0,
|
||||
False,
|
||||
Skipped,
|
||||
None,
|
||||
};
|
||||
|
||||
/// #elif, #elifdef, or #elifndef directives.
|
||||
std::vector<Branch> elifs;
|
||||
/// Kind of the branch.
|
||||
BranchKind kind;
|
||||
|
||||
/// Location of the #else directive, if present.
|
||||
clang::SourceLocation elseLoc;
|
||||
/// Value of the condition.
|
||||
ConditionValue value;
|
||||
|
||||
/// Location of the #endif directive.
|
||||
clang::SourceLocation endifLoc;
|
||||
/// Location of the directive identifier.
|
||||
clang::SourceLocation loc;
|
||||
|
||||
/// Range of the condition.
|
||||
clang::SourceRange conditionRange;
|
||||
};
|
||||
|
||||
struct MacroRef {
|
||||
enum Kind : uint8_t {
|
||||
Def = 0,
|
||||
Ref,
|
||||
Undef,
|
||||
};
|
||||
|
||||
/// Kind of the macro reference.
|
||||
Kind kind;
|
||||
|
||||
/// The location of the macro name.
|
||||
clang::SourceLocation loc;
|
||||
|
||||
/// The macro definition information.
|
||||
const clang::MacroInfo* macro;
|
||||
};
|
||||
|
||||
/// Do we need to store pragma information?
|
||||
struct Pragma {};
|
||||
|
||||
struct Directive {
|
||||
/// map from the location of if/ifdef/ifndef to the corresponding if block.
|
||||
llvm::DenseMap<clang::SourceLocation, IfBlock> ifBlocks;
|
||||
};
|
||||
std::vector<Include> includes;
|
||||
std::vector<Condition> conditions;
|
||||
std::vector<MacroRef> macros;
|
||||
|
||||
struct Directives {
|
||||
clang::Preprocessor& preproc;
|
||||
clang::SourceManager& sourceManager;
|
||||
llvm::DenseMap<clang::FileID, Directive> x;
|
||||
|
||||
clang::CommentHandler* handler();
|
||||
std::unique_ptr<clang::PPCallbacks> callback();
|
||||
/// Tell preprocessor to collect directives information and store them in `directives`.
|
||||
static void attach(clang::Preprocessor& pp,
|
||||
llvm::DenseMap<clang::FileID, Directive>& directives);
|
||||
};
|
||||
|
||||
} // namespace clice
|
||||
|
||||
namespace clice2 {
|
||||
|
||||
struct Directive {
|
||||
|
||||
};
|
||||
|
||||
// A class that record detailed information about preprocessing, like `TokenBuffer`.
|
||||
class PPBuffer {
|
||||
private:
|
||||
llvm::DenseMap<clang::FileID, Directive> directives;
|
||||
};
|
||||
|
||||
class PPCollector : public clang::PPCallbacks {
|
||||
};
|
||||
|
||||
} // namespace clice2
|
||||
|
||||
Reference in New Issue
Block a user