123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- //===- unittests/Lex/PPCallbacksTest.cpp - PPCallbacks tests ------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===--------------------------------------------------------------===//
- #include "clang/Lex/Preprocessor.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/ModuleLoader.h"
- #include "clang/Lex/PreprocessorOptions.h"
- #include "clang/Parse/Parser.h"
- #include "clang/Sema/Sema.h"
- #include "llvm/ADT/SmallString.h"
- #include "llvm/Support/Path.h"
- #include "gtest/gtest.h"
- using namespace clang;
- namespace {
- // Stub out module loading.
- class VoidModuleLoader : public ModuleLoader {
- ModuleLoadResult loadModule(SourceLocation ImportLoc,
- ModuleIdPath Path,
- Module::NameVisibilityKind Visibility,
- bool IsInclusionDirective) override {
- return ModuleLoadResult();
- }
- void makeModuleVisible(Module *Mod,
- Module::NameVisibilityKind Visibility,
- SourceLocation ImportLoc,
- bool Complain) override { }
- GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override
- { return nullptr; }
- bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override
- { return 0; };
- };
- // Stub to collect data from InclusionDirective callbacks.
- class InclusionDirectiveCallbacks : public PPCallbacks {
- public:
- void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
- StringRef FileName, bool IsAngled,
- CharSourceRange FilenameRange, const FileEntry *File,
- StringRef SearchPath, StringRef RelativePath,
- const Module *Imported) override {
- this->HashLoc = HashLoc;
- this->IncludeTok = IncludeTok;
- this->FileName = FileName.str();
- this->IsAngled = IsAngled;
- this->FilenameRange = FilenameRange;
- this->File = File;
- this->SearchPath = SearchPath.str();
- this->RelativePath = RelativePath.str();
- this->Imported = Imported;
- }
- SourceLocation HashLoc;
- Token IncludeTok;
- SmallString<16> FileName;
- bool IsAngled;
- CharSourceRange FilenameRange;
- const FileEntry* File;
- SmallString<16> SearchPath;
- SmallString<16> RelativePath;
- const Module* Imported;
- };
- // Stub to collect data from PragmaOpenCLExtension callbacks.
- class PragmaOpenCLExtensionCallbacks : public PPCallbacks {
- public:
- typedef struct {
- SmallString<16> Name;
- unsigned State;
- } CallbackParameters;
- PragmaOpenCLExtensionCallbacks() : Name("Not called."), State(99) {};
- void PragmaOpenCLExtension(clang::SourceLocation NameLoc,
- const clang::IdentifierInfo *Name,
- clang::SourceLocation StateLoc,
- unsigned State) override {
- this->NameLoc = NameLoc;
- this->Name = Name->getName();
- this->StateLoc = StateLoc;
- this->State = State;
- };
- SourceLocation NameLoc;
- SmallString<16> Name;
- SourceLocation StateLoc;
- unsigned State;
- };
- // PPCallbacks test fixture.
- class PPCallbacksTest : public ::testing::Test {
- protected:
- PPCallbacksTest()
- : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()),
- DiagOpts(new DiagnosticOptions()),
- Diags(DiagID, DiagOpts.get(), new IgnoringDiagConsumer()),
- SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions()) {
- TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
- Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
- }
- FileSystemOptions FileMgrOpts;
- FileManager FileMgr;
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
- IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
- DiagnosticsEngine Diags;
- SourceManager SourceMgr;
- LangOptions LangOpts;
- std::shared_ptr<TargetOptions> TargetOpts;
- IntrusiveRefCntPtr<TargetInfo> Target;
- // Register a header path as a known file and add its location
- // to search path.
- void AddFakeHeader(HeaderSearch& HeaderInfo, const char* HeaderPath,
- bool IsSystemHeader) {
- // Tell FileMgr about header.
- FileMgr.getVirtualFile(HeaderPath, 0, 0);
- // Add header's parent path to search path.
- StringRef SearchPath = llvm::sys::path::parent_path(HeaderPath);
- const DirectoryEntry *DE = FileMgr.getDirectory(SearchPath);
- DirectoryLookup DL(DE, SrcMgr::C_User, false);
- HeaderInfo.AddSearchPath(DL, IsSystemHeader);
- }
- // Get the raw source string of the range.
- StringRef GetSourceString(CharSourceRange Range) {
- const char* B = SourceMgr.getCharacterData(Range.getBegin());
- const char* E = SourceMgr.getCharacterData(Range.getEnd());
- return StringRef(B, E - B);
- }
- // Run lexer over SourceText and collect FilenameRange from
- // the InclusionDirective callback.
- CharSourceRange InclusionDirectiveFilenameRange(const char* SourceText,
- const char* HeaderPath, bool SystemHeader) {
- std::unique_ptr<llvm::MemoryBuffer> Buf =
- llvm::MemoryBuffer::getMemBuffer(SourceText);
- SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
- VoidModuleLoader ModLoader;
- IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts = new HeaderSearchOptions();
- HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts,
- Target.get());
- AddFakeHeader(HeaderInfo, HeaderPath, SystemHeader);
- IntrusiveRefCntPtr<PreprocessorOptions> PPOpts = new PreprocessorOptions();
- Preprocessor PP(PPOpts, Diags, LangOpts, SourceMgr, HeaderInfo, ModLoader,
- /*IILookup =*/nullptr,
- /*OwnsHeaderSearch =*/false);
- PP.Initialize(*Target);
- InclusionDirectiveCallbacks* Callbacks = new InclusionDirectiveCallbacks;
- PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks));
- // 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 filename range.
- return Callbacks->FilenameRange;
- }
- PragmaOpenCLExtensionCallbacks::CallbackParameters
- PragmaOpenCLExtensionCall(const char* SourceText) {
- LangOptions OpenCLLangOpts;
- OpenCLLangOpts.OpenCL = 1;
- std::unique_ptr<llvm::MemoryBuffer> SourceBuf =
- llvm::MemoryBuffer::getMemBuffer(SourceText, "test.cl");
- SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(SourceBuf)));
- VoidModuleLoader ModLoader;
- HeaderSearch HeaderInfo(new HeaderSearchOptions, SourceMgr, Diags,
- OpenCLLangOpts, Target.get());
- Preprocessor PP(new PreprocessorOptions(), Diags, OpenCLLangOpts, SourceMgr,
- HeaderInfo, ModLoader, /*IILookup =*/nullptr,
- /*OwnsHeaderSearch =*/false);
- PP.Initialize(*Target);
- // parser actually sets correct pragma handlers for preprocessor
- // according to LangOptions, so we init Parser to register opencl
- // pragma handlers
- ASTContext Context(OpenCLLangOpts, SourceMgr,
- PP.getIdentifierTable(), PP.getSelectorTable(),
- PP.getBuiltinInfo());
- Context.InitBuiltinTypes(*Target);
- ASTConsumer Consumer;
- Sema S(PP, Context, Consumer);
- Parser P(PP, S, false);
- PragmaOpenCLExtensionCallbacks* Callbacks = new PragmaOpenCLExtensionCallbacks;
- PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks));
- // Lex source text.
- PP.EnterMainSourceFile();
- while (true) {
- Token Tok;
- PP.Lex(Tok);
- if (Tok.is(tok::eof))
- break;
- }
- PragmaOpenCLExtensionCallbacks::CallbackParameters RetVal = {
- Callbacks->Name,
- Callbacks->State
- };
- return RetVal;
- }
- };
- TEST_F(PPCallbacksTest, QuotedFilename) {
- const char* Source =
- "#include \"quoted.h\"\n";
- CharSourceRange Range =
- InclusionDirectiveFilenameRange(Source, "/quoted.h", false);
- ASSERT_EQ("\"quoted.h\"", GetSourceString(Range));
- }
- TEST_F(PPCallbacksTest, AngledFilename) {
- const char* Source =
- "#include <angled.h>\n";
- CharSourceRange Range =
- InclusionDirectiveFilenameRange(Source, "/angled.h", true);
- ASSERT_EQ("<angled.h>", GetSourceString(Range));
- }
- TEST_F(PPCallbacksTest, QuotedInMacro) {
- const char* Source =
- "#define MACRO_QUOTED \"quoted.h\"\n"
- "#include MACRO_QUOTED\n";
- CharSourceRange Range =
- InclusionDirectiveFilenameRange(Source, "/quoted.h", false);
- ASSERT_EQ("\"quoted.h\"", GetSourceString(Range));
- }
- TEST_F(PPCallbacksTest, AngledInMacro) {
- const char* Source =
- "#define MACRO_ANGLED <angled.h>\n"
- "#include MACRO_ANGLED\n";
- CharSourceRange Range =
- InclusionDirectiveFilenameRange(Source, "/angled.h", true);
- ASSERT_EQ("<angled.h>", GetSourceString(Range));
- }
- TEST_F(PPCallbacksTest, StringizedMacroArgument) {
- const char* Source =
- "#define MACRO_STRINGIZED(x) #x\n"
- "#include MACRO_STRINGIZED(quoted.h)\n";
- CharSourceRange Range =
- InclusionDirectiveFilenameRange(Source, "/quoted.h", false);
- ASSERT_EQ("\"quoted.h\"", GetSourceString(Range));
- }
- TEST_F(PPCallbacksTest, ConcatenatedMacroArgument) {
- const char* Source =
- "#define MACRO_ANGLED <angled.h>\n"
- "#define MACRO_CONCAT(x, y) x ## _ ## y\n"
- "#include MACRO_CONCAT(MACRO, ANGLED)\n";
- CharSourceRange Range =
- InclusionDirectiveFilenameRange(Source, "/angled.h", false);
- ASSERT_EQ("<angled.h>", GetSourceString(Range));
- }
- TEST_F(PPCallbacksTest, TrigraphFilename) {
- const char* Source =
- "#include \"tri\?\?-graph.h\"\n";
- CharSourceRange Range =
- InclusionDirectiveFilenameRange(Source, "/tri~graph.h", false);
- ASSERT_EQ("\"tri\?\?-graph.h\"", GetSourceString(Range));
- }
- TEST_F(PPCallbacksTest, TrigraphInMacro) {
- const char* Source =
- "#define MACRO_TRIGRAPH \"tri\?\?-graph.h\"\n"
- "#include MACRO_TRIGRAPH\n";
- CharSourceRange Range =
- InclusionDirectiveFilenameRange(Source, "/tri~graph.h", false);
- ASSERT_EQ("\"tri\?\?-graph.h\"", GetSourceString(Range));
- }
- TEST_F(PPCallbacksTest, OpenCLExtensionPragmaEnabled) {
- const char* Source =
- "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n";
- PragmaOpenCLExtensionCallbacks::CallbackParameters Parameters =
- PragmaOpenCLExtensionCall(Source);
- ASSERT_EQ("cl_khr_fp64", Parameters.Name);
- unsigned ExpectedState = 1;
- ASSERT_EQ(ExpectedState, Parameters.State);
- }
- TEST_F(PPCallbacksTest, OpenCLExtensionPragmaDisabled) {
- const char* Source =
- "#pragma OPENCL EXTENSION cl_khr_fp16 : disable\n";
- PragmaOpenCLExtensionCallbacks::CallbackParameters Parameters =
- PragmaOpenCLExtensionCall(Source);
- ASSERT_EQ("cl_khr_fp16", Parameters.Name);
- unsigned ExpectedState = 0;
- ASSERT_EQ(ExpectedState, Parameters.State);
- }
- } // anonoymous namespace
|