Collect directives in PPCallback.

This commit is contained in:
ykiko
2024-12-07 01:45:56 +08:00
parent d6921634ac
commit eaeb9b3ed7
8 changed files with 294 additions and 190 deletions

View File

@@ -8,6 +8,8 @@
#include <clang/Tooling/Syntax/Tokens.h>
#include <clang/Sema/Sema.h>
#include <Support/Support.h>
namespace std {
template <>

View File

@@ -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 {

View File

@@ -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