From: Pekka Jaaskelainen Date: Sat, 12 Oct 2013 09:29:48 +0000 (+0000) Subject: Callback support for OpenCL extension pragmas. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a0950e83cae5df77c00d02d7f77a166979cd2b8b;p=clang Callback support for OpenCL extension pragmas. Patch from Rami Ylimäki and Mikael Lepistö! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192531 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index 73cfb0aefc..0e11218279 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -217,6 +217,13 @@ public: diag::Mapping mapping, StringRef Str) { } + /// \brief Called when an OpenCL extension is either disabled or + /// enabled with a pragma. + virtual void PragmaOpenCLExtension(SourceLocation NameLoc, + const IdentifierInfo *Name, + SourceLocation StateLoc, unsigned State) { + } + /// \brief Callback invoked when a \#pragma warning directive is read. virtual void PragmaWarning(SourceLocation Loc, StringRef WarningSpec, ArrayRef Ids) { @@ -413,6 +420,13 @@ public: Second->PragmaDiagnostic(Loc, Namespace, mapping, Str); } + virtual void PragmaOpenCLExtension(SourceLocation NameLoc, + const IdentifierInfo *Name, + SourceLocation StateLoc, unsigned State) { + First->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State); + Second->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State); + } + virtual void PragmaWarning(SourceLocation Loc, StringRef WarningSpec, ArrayRef Ids) { First->PragmaWarning(Loc, WarningSpec, Ids); diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index 10ad5df629..8a374e0fce 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -728,6 +728,7 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable); return; } + SourceLocation StateLoc = Tok.getLocation(); PP.Lex(Tok); if (Tok.isNot(tok::eod)) { @@ -747,6 +748,10 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, Toks[0].setAnnotationValue(data.getOpaqueValue()); PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); + + if (PP.getPPCallbacks()) + PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename, + StateLoc, state); } /// \brief Handle '#pragma omp ...' when OpenMP is disabled. diff --git a/unittests/Lex/CMakeLists.txt b/unittests/Lex/CMakeLists.txt index 78838c0829..cb3b9275db 100644 --- a/unittests/Lex/CMakeLists.txt +++ b/unittests/Lex/CMakeLists.txt @@ -5,5 +5,5 @@ add_clang_unittest(LexTests ) target_link_libraries(LexTests - clangLex + clangLex clangParse clangSema ) diff --git a/unittests/Lex/Makefile b/unittests/Lex/Makefile index bb9c6bc390..fa233ce25f 100644 --- a/unittests/Lex/Makefile +++ b/unittests/Lex/Makefile @@ -9,7 +9,8 @@ CLANG_LEVEL = ../.. TESTNAME = Lex -LINK_COMPONENTS := support mc -USEDLIBS = clangLex.a clangBasic.a +LINK_COMPONENTS := mcparser support mc +USEDLIBS = clangParse.a clangSema.a clangAnalysis.a clangEdit.a \ + clangAST.a clangLex.a clangBasic.a include $(CLANG_LEVEL)/unittests/Makefile diff --git a/unittests/Lex/PPCallbacksTest.cpp b/unittests/Lex/PPCallbacksTest.cpp index 4e0a4331dc..8c6df1d00a 100644 --- a/unittests/Lex/PPCallbacksTest.cpp +++ b/unittests/Lex/PPCallbacksTest.cpp @@ -18,6 +18,10 @@ #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 "clang/AST/ASTContext.h" +#include "clang/AST/ASTConsumer.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Path.h" #include "gtest/gtest.h" @@ -77,6 +81,31 @@ public: const Module* Imported; }; +// Stub to collect data from PragmaOpenCLExtension callbacks. +class PragmaOpenCLExtensionCallbacks : public PPCallbacks { +public: + typedef struct { + StringRef Name; + unsigned State; + } CallbackParameters; + + PragmaOpenCLExtensionCallbacks() : Name("Not called."), State(99) {}; + + void PragmaOpenCLExtension( + clang::SourceLocation NameLoc, const clang::IdentifierInfo *Name, + clang::SourceLocation StateLoc, unsigned State) { + this->NameLoc = NameLoc; + this->Name = Name->getName().str(); + this->StateLoc = StateLoc; + this->State = State; + }; + + SourceLocation NameLoc; + StringRef Name; + SourceLocation StateLoc; + unsigned State; +}; + // PPCallbacks test fixture. class PPCallbacksTest : public ::testing::Test { protected: @@ -159,6 +188,53 @@ protected: // Callbacks have been executed at this point -- return filename range. return Callbacks->FilenameRange; } + + PragmaOpenCLExtensionCallbacks::CallbackParameters + PragmaOpenCLExtensionCall(const char* SourceText) { + LangOptions OpenCLLangOpts; + OpenCLLangOpts.OpenCL = 1; + + MemoryBuffer* sourceBuf = MemoryBuffer::getMemBuffer(SourceText, "test.cl"); + (void)SourceMgr.createMainFileIDForMemBuffer(sourceBuf); + + VoidModuleLoader ModLoader; + HeaderSearch HeaderInfo(new HeaderSearchOptions, FileMgr, Diags, + OpenCLLangOpts, Target.getPtr()); + + Preprocessor PP(new PreprocessorOptions(), Diags, OpenCLLangOpts, + Target.getPtr(), + SourceMgr, HeaderInfo, ModLoader, + /*IILookup =*/ 0, + /*OwnsHeaderSearch =*/false, + /*DelayInitialization =*/ false); + + // parser actually sets correct pragma handlers for preprocessor + // according to LangOptions, so we init Parser to register opencl + // pragma handlers + ASTContext Context(OpenCLLangOpts, SourceMgr, Target.getPtr(), + PP.getIdentifierTable(), PP.getSelectorTable(), + PP.getBuiltinInfo(), 0); + ASTConsumer Consumer; + Sema S(PP, Context, Consumer); + Parser P(PP, S, false); + PragmaOpenCLExtensionCallbacks* Callbacks = new PragmaOpenCLExtensionCallbacks; + PP.addPPCallbacks(Callbacks); // Takes ownership. + + // Lex source text. + PP.EnterMainSourceFile(); + while (true) { + Token Tok; + PP.Lex(Tok); + if (Tok.is(tok::eof)) + break; + } + + PragmaOpenCLExtensionCallbacks::CallbackParameters RetVal = { + Callbacks->Name.str(), + Callbacks->State + }; + return RetVal; + } }; TEST_F(PPCallbacksTest, QuotedFilename) { @@ -247,4 +323,28 @@ TEST_F(PPCallbacksTest, TrigraphInMacro) { 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