-
-
Save T35R6braPwgDJKq/6439fda090e4ee8440d726f8dafa4dbb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//===- unittests/Analysis/MacroExpansionContextTest.cpp - -----------------===// | |
// | |
// 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 | |
// | |
//===----------------------------------------------------------------------===// | |
#include "clang/Analysis/MacroExpansionContext.h" | |
#include "clang/AST/ASTConsumer.h" | |
#include "clang/AST/ASTContext.h" | |
#include "clang/Basic/Diagnostic.h" | |
#include "clang/Basic/DiagnosticOptions.h" | |
#include "clang/Basic/FileManager.h" | |
#include "clang/Basic/LangOptions.h" | |
#include "clang/Basic/SourceManager.h" | |
#include "clang/Basic/TargetInfo.h" | |
#include "clang/Basic/TargetOptions.h" | |
#include "clang/Lex/HeaderSearch.h" | |
#include "clang/Lex/HeaderSearchOptions.h" | |
#include "clang/Lex/Preprocessor.h" | |
#include "clang/Lex/PreprocessorOptions.h" | |
#include "clang/Parse/Parser.h" | |
#include "llvm/ADT/SmallString.h" | |
#include "gtest/gtest.h" | |
// static bool HACK_EnableDebugInUnitTest = (::llvm::DebugFlag = true); | |
namespace clang { | |
namespace analysis { | |
namespace { | |
class MacroExpansionContextTest : public ::testing::Test { | |
protected: | |
MacroExpansionContextTest() | |
: InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem), | |
FileMgr(FileSystemOptions(), InMemoryFileSystem), | |
DiagID(new DiagnosticIDs()), DiagOpts(new DiagnosticOptions()), | |
Diags(DiagID, DiagOpts.get(), new IgnoringDiagConsumer()), | |
SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions()) { | |
TargetOpts->Triple = "x86_64-pc-linux-unknown"; | |
Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); | |
LangOpts.CPlusPlus20 = 1; // For __VA_OPT__ | |
} | |
IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem; | |
FileManager FileMgr; | |
IntrusiveRefCntPtr<DiagnosticIDs> DiagID; | |
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; | |
DiagnosticsEngine Diags; | |
SourceManager SourceMgr; | |
LangOptions LangOpts; | |
std::shared_ptr<TargetOptions> TargetOpts; | |
IntrusiveRefCntPtr<TargetInfo> Target; | |
std::unique_ptr<MacroExpansionContext> | |
getMacroExpansionContextFor(StringRef SourceText) { | |
std::unique_ptr<llvm::MemoryBuffer> Buf = | |
llvm::MemoryBuffer::getMemBuffer(SourceText); | |
SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf))); | |
TrivialModuleLoader ModLoader; | |
HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr, | |
Diags, LangOpts, Target.get()); | |
Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts, | |
SourceMgr, HeaderInfo, ModLoader, | |
/*IILookup =*/nullptr, | |
/*OwnsHeaderSearch =*/false); | |
PP.Initialize(*Target); | |
auto Ctx = std::make_unique<MacroExpansionContext>(LangOpts); | |
Ctx->registerForPreprocessor(PP); | |
// Lex source text. | |
PP.EnterMainSourceFile(); | |
while (true) { | |
Token Tok; | |
PP.Lex(Tok); | |
if (Tok.is(tok::eof)) | |
break; | |
} | |
// Callbacks have been executed at this point. | |
return Ctx; | |
} | |
/// Returns the expansion location to main file at the given row and column. | |
SourceLocation at(unsigned row, unsigned col) const { | |
SourceLocation Loc = | |
SourceMgr.translateLineCol(SourceMgr.getMainFileID(), row, col); | |
return SourceMgr.getExpansionLoc(Loc); | |
} | |
static std::string dumpExpandedTexts(const MacroExpansionContext &Ctx) { | |
std::string Buf; | |
llvm::raw_string_ostream OS{Buf}; | |
Ctx.dumpExpandedTextsToStream(OS); | |
return OS.str(); | |
} | |
static std::string dumpExpansionRanges(const MacroExpansionContext &Ctx) { | |
std::string Buf; | |
llvm::raw_string_ostream OS{Buf}; | |
Ctx.dumpExpansionRangesToStream(OS); | |
return OS.str(); | |
} | |
}; | |
TEST_F(MacroExpansionContextTest, Custom) { | |
// From the GCC website. | |
const auto Ctx = getMacroExpansionContextFor(R"code( | |
#define CONCATMACRO(parm) L##parm | |
int f(wchar_t *b){} | |
int main() | |
{ | |
int a= f(CONCATMACRO("TEST")); | |
int b= f(L"TEST"); | |
return 0; | |
} | |
)code"); | |
Ctx->dumpExpansionRanges(); | |
//> :6:14, :6:33 | |
Ctx->dumpExpandedTexts(); | |
//> :6:14 -> 'L"TEST"' | |
printf("Exp: %s\n",Ctx->getExpandedText(at(6, 14)).getValue()); | |
//Exp: L"TEST" | |
printf("Org: %s\n",Ctx->getOriginalText(at(6, 14)).getValue()); | |
//Org: CONCATMACRO("TEST")); | |
// int b= f(L"TEST"); | |
// return 0; | |
//} | |
StringRef sourceText = clang::Lexer::getSourceText(CharSourceRange(SourceRange(at(6, 14),at(6, 33)),false),SourceMgr, LangOpts); | |
printf("sourceText: %s\n",sourceText); | |
// sourceText: CONCATMACRO("TEST")); | |
// int b= f(L"TEST"); | |
// return 0; | |
// } | |
} | |
/** | |
gcc mectest.cpp -lgtest -lstdc++ -lclang -lLLVM -lclang-cpp -g -o mectest | |
./mectest | |
[==========] Running 1 test from 1 test suite. | |
[----------] Global test environment set-up. | |
[----------] 1 test from MacroExpansionContextTest | |
[ RUN ] MacroExpansionContextTest.Custom | |
=============== ExpansionRanges =============== | |
> :6:14, :6:33 | |
=============== ExpandedTokens =============== | |
> :6:14 -> 'L"TEST"' | |
Exp: L"TEST" | |
Org: CONCATMACRO("TEST")); | |
int b= f(L"TEST"); | |
return 0; | |
} | |
sourceText: CONCATMACRO("TEST")); | |
int b= f(L"TEST"); | |
return 0; | |
} | |
[ OK ] MacroExpansionContextTest.Custom (15 ms) | |
[----------] 1 test from MacroExpansionContextTest (15 ms total) | |
[----------] Global test environment tear-down | |
[==========] 1 test from 1 test suite ran. (15 ms total) | |
[ PASSED ] 1 test. | |
*/ | |
} // namespace | |
} // namespace analysis | |
} // namespace clang | |
int main(int argc, char **argv) { | |
::testing::InitGoogleTest(&argc, argv); | |
return RUN_ALL_TESTS(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment