1cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis//===- unittests/Lex/PPCallbacksTest.cpp - PPCallbacks tests ------===//
2cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis//
3cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis//                     The LLVM Compiler Infrastructure
4cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis//
5cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source
6cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis// License. See LICENSE.TXT for details.
7cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis//
8cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis//===--------------------------------------------------------------===//
9cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
101050e8b2252d89a0004a6fd25a58dab88b5ee625Chandler Carruth#include "clang/Lex/Preprocessor.h"
11651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/AST/ASTConsumer.h"
12651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/AST/ASTContext.h"
13cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis#include "clang/Basic/Diagnostic.h"
146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "clang/Basic/DiagnosticOptions.h"
15cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis#include "clang/Basic/FileManager.h"
16cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis#include "clang/Basic/LangOptions.h"
17cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis#include "clang/Basic/SourceManager.h"
18cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis#include "clang/Basic/TargetInfo.h"
19cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis#include "clang/Basic/TargetOptions.h"
20cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis#include "clang/Lex/HeaderSearch.h"
21cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis#include "clang/Lex/HeaderSearchOptions.h"
22cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis#include "clang/Lex/ModuleLoader.h"
23cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis#include "clang/Lex/PreprocessorOptions.h"
24a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen#include "clang/Parse/Parser.h"
25a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen#include "clang/Sema/Sema.h"
26cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis#include "llvm/ADT/SmallString.h"
278229d22e6449851b89361bf2f41804557328be63Rafael Espindola#include "llvm/Support/Path.h"
28cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis#include "gtest/gtest.h"
29cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
30cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidisusing namespace clang;
31cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
32cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidisnamespace {
33cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
34cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis// Stub out module loading.
35cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidisclass VoidModuleLoader : public ModuleLoader {
366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  ModuleLoadResult loadModule(SourceLocation ImportLoc,
376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                              ModuleIdPath Path,
386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                              Module::NameVisibilityKind Visibility,
396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                              bool IsInclusionDirective) override {
407dff05bf3019995798def5d1066e4282b8578df6Douglas Gregor    return ModuleLoadResult();
41cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  }
421a4191d0697098c424646654784399b839f87bc4NAKAMURA Takumi
436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void makeModuleVisible(Module *Mod,
446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                         Module::NameVisibilityKind Visibility,
45b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar                         SourceLocation ImportLoc) override { }
466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override
48c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    { return nullptr; }
496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override
5087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    { return 0; }
51cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis};
52cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
53cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis// Stub to collect data from InclusionDirective callbacks.
54cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidisclass InclusionDirectiveCallbacks : public PPCallbacks {
55cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidispublic:
5658878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
5758878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar                          StringRef FileName, bool IsAngled,
5858878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar                          CharSourceRange FilenameRange, const FileEntry *File,
5958878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar                          StringRef SearchPath, StringRef RelativePath,
6058878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar                          const Module *Imported) override {
61cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      this->HashLoc = HashLoc;
62cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      this->IncludeTok = IncludeTok;
63cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      this->FileName = FileName.str();
64cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      this->IsAngled = IsAngled;
65cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      this->FilenameRange = FilenameRange;
66cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      this->File = File;
67cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      this->SearchPath = SearchPath.str();
68cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      this->RelativePath = RelativePath.str();
69cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      this->Imported = Imported;
70cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  }
71cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
72cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  SourceLocation HashLoc;
73cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  Token IncludeTok;
74cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  SmallString<16> FileName;
75cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  bool IsAngled;
76cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  CharSourceRange FilenameRange;
77cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  const FileEntry* File;
78cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  SmallString<16> SearchPath;
79cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  SmallString<16> RelativePath;
80cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  const Module* Imported;
81cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis};
82cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
83a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen// Stub to collect data from PragmaOpenCLExtension callbacks.
84a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainenclass PragmaOpenCLExtensionCallbacks : public PPCallbacks {
85a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainenpublic:
86a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  typedef struct {
8774ecbd5babae58907e6338a5f79ec4eb4401c0dcAlexey Samsonov    SmallString<16> Name;
88a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    unsigned State;
89a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  } CallbackParameters;
90a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
9187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  PragmaOpenCLExtensionCallbacks() : Name("Not called."), State(99) {}
92a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
9358878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar  void PragmaOpenCLExtension(clang::SourceLocation NameLoc,
9458878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar                             const clang::IdentifierInfo *Name,
9558878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar                             clang::SourceLocation StateLoc,
9658878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar                             unsigned State) override {
97a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen      this->NameLoc = NameLoc;
9874ecbd5babae58907e6338a5f79ec4eb4401c0dcAlexey Samsonov      this->Name = Name->getName();
99a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen      this->StateLoc = StateLoc;
100a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen      this->State = State;
10187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  }
102a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
103a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  SourceLocation NameLoc;
10474ecbd5babae58907e6338a5f79ec4eb4401c0dcAlexey Samsonov  SmallString<16> Name;
105a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  SourceLocation StateLoc;
106a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  unsigned State;
107a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen};
108a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
109cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis// PPCallbacks test fixture.
110cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidisclass PPCallbacksTest : public ::testing::Test {
111cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidisprotected:
112cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  PPCallbacksTest()
11387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      : InMemoryFileSystem(new vfs::InMemoryFileSystem),
11487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        FileMgr(FileSystemOptions(), InMemoryFileSystem),
11587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        DiagID(new DiagnosticIDs()), DiagOpts(new DiagnosticOptions()),
116c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        Diags(DiagID, DiagOpts.get(), new IgnoringDiagConsumer()),
117c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions()) {
118cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
119c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
120cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  }
121cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
12287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
123cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  FileManager FileMgr;
124cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
125cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
126cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  DiagnosticsEngine Diags;
127cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  SourceManager SourceMgr;
128cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  LangOptions LangOpts;
129c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::shared_ptr<TargetOptions> TargetOpts;
130cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  IntrusiveRefCntPtr<TargetInfo> Target;
131cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
132cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  // Register a header path as a known file and add its location
133cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  // to search path.
134cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  void AddFakeHeader(HeaderSearch& HeaderInfo, const char* HeaderPath,
135cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    bool IsSystemHeader) {
136cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      // Tell FileMgr about header.
13787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      InMemoryFileSystem->addFile(HeaderPath, 0,
13887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                                  llvm::MemoryBuffer::getMemBuffer("\n"));
139cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
140cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      // Add header's parent path to search path.
141176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      StringRef SearchPath = llvm::sys::path::parent_path(HeaderPath);
142cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      const DirectoryEntry *DE = FileMgr.getDirectory(SearchPath);
1431ea6bc0fd9c1ff9fa03e8a829a79c4167445d503Daniel Dunbar      DirectoryLookup DL(DE, SrcMgr::C_User, false);
144cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      HeaderInfo.AddSearchPath(DL, IsSystemHeader);
145cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  }
146cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
147cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  // Get the raw source string of the range.
148cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  StringRef GetSourceString(CharSourceRange Range) {
149cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    const char* B = SourceMgr.getCharacterData(Range.getBegin());
150cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    const char* E = SourceMgr.getCharacterData(Range.getEnd());
151cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
152cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    return StringRef(B, E - B);
153cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  }
154cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
155cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  // Run lexer over SourceText and collect FilenameRange from
156cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  // the InclusionDirective callback.
157cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  CharSourceRange InclusionDirectiveFilenameRange(const char* SourceText,
158cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      const char* HeaderPath, bool SystemHeader) {
159176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    std::unique_ptr<llvm::MemoryBuffer> Buf =
160176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::MemoryBuffer::getMemBuffer(SourceText);
161176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
162cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
163cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    VoidModuleLoader ModLoader;
164cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
165cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts = new HeaderSearchOptions();
166ee0cd37fe4a9f4e2ee73ae34cf93c410cb299a82Manuel Klimek    HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts,
167c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                            Target.get());
168cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    AddFakeHeader(HeaderInfo, HeaderPath, SystemHeader);
169cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
170cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    IntrusiveRefCntPtr<PreprocessorOptions> PPOpts = new PreprocessorOptions();
1716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    Preprocessor PP(PPOpts, Diags, LangOpts, SourceMgr, HeaderInfo, ModLoader,
172c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    /*IILookup =*/nullptr,
1736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                    /*OwnsHeaderSearch =*/false);
1746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    PP.Initialize(*Target);
175cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    InclusionDirectiveCallbacks* Callbacks = new InclusionDirectiveCallbacks;
176176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks));
177cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
178cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    // Lex source text.
179cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    PP.EnterMainSourceFile();
180cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
181cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    while (true) {
182cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      Token Tok;
183cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      PP.Lex(Tok);
184cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis      if (Tok.is(tok::eof))
185cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis        break;
186cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    }
187cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
188cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    // Callbacks have been executed at this point -- return filename range.
189cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    return Callbacks->FilenameRange;
190cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  }
191a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
192a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  PragmaOpenCLExtensionCallbacks::CallbackParameters
193a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  PragmaOpenCLExtensionCall(const char* SourceText) {
194a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    LangOptions OpenCLLangOpts;
195a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    OpenCLLangOpts.OpenCL = 1;
196a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
197176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    std::unique_ptr<llvm::MemoryBuffer> SourceBuf =
198176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::MemoryBuffer::getMemBuffer(SourceText, "test.cl");
199176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(SourceBuf)));
200a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
201a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    VoidModuleLoader ModLoader;
202ee0cd37fe4a9f4e2ee73ae34cf93c410cb299a82Manuel Klimek    HeaderSearch HeaderInfo(new HeaderSearchOptions, SourceMgr, Diags,
203c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                            OpenCLLangOpts, Target.get());
204a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
2056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    Preprocessor PP(new PreprocessorOptions(), Diags, OpenCLLangOpts, SourceMgr,
206c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    HeaderInfo, ModLoader, /*IILookup =*/nullptr,
2076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                    /*OwnsHeaderSearch =*/false);
2086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    PP.Initialize(*Target);
209a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
210a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    // parser actually sets correct pragma handlers for preprocessor
211a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    // according to LangOptions, so we init Parser to register opencl
212a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    // pragma handlers
2136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    ASTContext Context(OpenCLLangOpts, SourceMgr,
214a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen                       PP.getIdentifierTable(), PP.getSelectorTable(),
2156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                       PP.getBuiltinInfo());
2166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    Context.InitBuiltinTypes(*Target);
2176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
218a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    ASTConsumer Consumer;
219a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    Sema S(PP, Context, Consumer);
220a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    Parser P(PP, S, false);
221a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    PragmaOpenCLExtensionCallbacks* Callbacks = new PragmaOpenCLExtensionCallbacks;
222176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks));
223a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
224a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    // Lex source text.
225a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    PP.EnterMainSourceFile();
226a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    while (true) {
227a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen      Token Tok;
228a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen      PP.Lex(Tok);
229a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen      if (Tok.is(tok::eof))
230a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen        break;
231a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    }
232a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
233a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    PragmaOpenCLExtensionCallbacks::CallbackParameters RetVal = {
23474ecbd5babae58907e6338a5f79ec4eb4401c0dcAlexey Samsonov      Callbacks->Name,
235a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen      Callbacks->State
236a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    };
237a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    return RetVal;
238a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  }
239cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis};
240cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
241cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios KyrtzidisTEST_F(PPCallbacksTest, QuotedFilename) {
242cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  const char* Source =
243cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    "#include \"quoted.h\"\n";
244cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
245cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  CharSourceRange Range =
246cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    InclusionDirectiveFilenameRange(Source, "/quoted.h", false);
247cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
248cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  ASSERT_EQ("\"quoted.h\"", GetSourceString(Range));
249cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis}
250cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
251cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios KyrtzidisTEST_F(PPCallbacksTest, AngledFilename) {
252cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  const char* Source =
253cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    "#include <angled.h>\n";
254cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
255cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  CharSourceRange Range =
256cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    InclusionDirectiveFilenameRange(Source, "/angled.h", true);
257cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
258cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  ASSERT_EQ("<angled.h>", GetSourceString(Range));
259cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis}
260cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
261cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios KyrtzidisTEST_F(PPCallbacksTest, QuotedInMacro) {
262cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  const char* Source =
263cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    "#define MACRO_QUOTED \"quoted.h\"\n"
264cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    "#include MACRO_QUOTED\n";
265cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
266cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  CharSourceRange Range =
267cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    InclusionDirectiveFilenameRange(Source, "/quoted.h", false);
268cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
269cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  ASSERT_EQ("\"quoted.h\"", GetSourceString(Range));
270cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis}
271cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
272cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios KyrtzidisTEST_F(PPCallbacksTest, AngledInMacro) {
273cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  const char* Source =
274cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    "#define MACRO_ANGLED <angled.h>\n"
275cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    "#include MACRO_ANGLED\n";
276cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
277cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  CharSourceRange Range =
278cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    InclusionDirectiveFilenameRange(Source, "/angled.h", true);
279cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
280cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  ASSERT_EQ("<angled.h>", GetSourceString(Range));
281cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis}
282cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
283cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios KyrtzidisTEST_F(PPCallbacksTest, StringizedMacroArgument) {
284cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  const char* Source =
285cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    "#define MACRO_STRINGIZED(x) #x\n"
286cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    "#include MACRO_STRINGIZED(quoted.h)\n";
287cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
288cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  CharSourceRange Range =
289cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    InclusionDirectiveFilenameRange(Source, "/quoted.h", false);
290cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
291cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  ASSERT_EQ("\"quoted.h\"", GetSourceString(Range));
292cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis}
293cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
294cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios KyrtzidisTEST_F(PPCallbacksTest, ConcatenatedMacroArgument) {
295cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  const char* Source =
296cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    "#define MACRO_ANGLED <angled.h>\n"
297cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    "#define MACRO_CONCAT(x, y) x ## _ ## y\n"
298cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    "#include MACRO_CONCAT(MACRO, ANGLED)\n";
299cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
300cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  CharSourceRange Range =
301cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    InclusionDirectiveFilenameRange(Source, "/angled.h", false);
302cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
303cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  ASSERT_EQ("<angled.h>", GetSourceString(Range));
304cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis}
305cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
306cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios KyrtzidisTEST_F(PPCallbacksTest, TrigraphFilename) {
307cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  const char* Source =
3087164095ea1c804740e00d54d05a7e8d1f876c674Benjamin Kramer    "#include \"tri\?\?-graph.h\"\n";
309cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
310cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  CharSourceRange Range =
311cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    InclusionDirectiveFilenameRange(Source, "/tri~graph.h", false);
312cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
3137164095ea1c804740e00d54d05a7e8d1f876c674Benjamin Kramer  ASSERT_EQ("\"tri\?\?-graph.h\"", GetSourceString(Range));
314cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis}
315cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
316cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios KyrtzidisTEST_F(PPCallbacksTest, TrigraphInMacro) {
317cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  const char* Source =
3187164095ea1c804740e00d54d05a7e8d1f876c674Benjamin Kramer    "#define MACRO_TRIGRAPH \"tri\?\?-graph.h\"\n"
319cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    "#include MACRO_TRIGRAPH\n";
320cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
321cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis  CharSourceRange Range =
322cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis    InclusionDirectiveFilenameRange(Source, "/tri~graph.h", false);
323cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
3247164095ea1c804740e00d54d05a7e8d1f876c674Benjamin Kramer  ASSERT_EQ("\"tri\?\?-graph.h\"", GetSourceString(Range));
325cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis}
326cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis
327a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka JaaskelainenTEST_F(PPCallbacksTest, OpenCLExtensionPragmaEnabled) {
328a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  const char* Source =
329a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n";
330a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
331a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  PragmaOpenCLExtensionCallbacks::CallbackParameters Parameters =
332a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    PragmaOpenCLExtensionCall(Source);
333a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
334a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  ASSERT_EQ("cl_khr_fp64", Parameters.Name);
335a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  unsigned ExpectedState = 1;
336a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  ASSERT_EQ(ExpectedState, Parameters.State);
337a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen}
338a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
339a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka JaaskelainenTEST_F(PPCallbacksTest, OpenCLExtensionPragmaDisabled) {
340a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  const char* Source =
341a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    "#pragma OPENCL EXTENSION cl_khr_fp16 : disable\n";
342a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
343a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  PragmaOpenCLExtensionCallbacks::CallbackParameters Parameters =
344a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen    PragmaOpenCLExtensionCall(Source);
345a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
346a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  ASSERT_EQ("cl_khr_fp16", Parameters.Name);
347a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  unsigned ExpectedState = 0;
348a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen  ASSERT_EQ(ExpectedState, Parameters.State);
349a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen}
350a0950e83cae5df77c00d02d7f77a166979cd2b8bPekka Jaaskelainen
351cfa1caa92611184f59c2f3e606c53ddcc726449aArgyrios Kyrtzidis} // anonoymous namespace
352