[cfe-commits] r167239 - in /cfe/trunk: lib/Lex/PPDirectives.cpp unittests/Lex/CMakeLists.txt unittests/Lex/PPCallbacksTest.cpp
Argyrios Kyrtzidis
akyrtzi at gmail.com
Thu Nov 1 10:52:58 PDT 2012
Author: akirtzidis
Date: Thu Nov 1 12:52:58 2012
New Revision: 167239
URL: http://llvm.org/viewvc/llvm-project?rev=167239&view=rev
Log:
Make the FilenameRange of the InclusionDirective callback more accurate,
preserve the macro location of the range end if the filename came from a macro.
Patch by Kim Gräsman!
Added:
cfe/trunk/unittests/Lex/PPCallbacksTest.cpp
Modified:
cfe/trunk/lib/Lex/PPDirectives.cpp
cfe/trunk/unittests/Lex/CMakeLists.txt
Modified: cfe/trunk/lib/Lex/PPDirectives.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=167239&r1=167238&r2=167239&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPDirectives.cpp (original)
+++ cfe/trunk/lib/Lex/PPDirectives.cpp Thu Nov 1 12:52:58 2012
@@ -1296,7 +1296,7 @@
case tok::string_literal:
Filename = getSpelling(FilenameTok, FilenameBuffer);
End = FilenameTok.getLocation();
- CharEnd = End.getLocWithOffset(Filename.size());
+ CharEnd = End.getLocWithOffset(FilenameTok.getLength());
break;
case tok::less:
@@ -1306,7 +1306,7 @@
if (ConcatenateIncludeName(FilenameBuffer, End))
return; // Found <eod> but no ">"? Diagnostic already emitted.
Filename = FilenameBuffer.str();
- CharEnd = getLocForEndOfToken(End);
+ CharEnd = End.getLocWithOffset(1);
break;
default:
Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
Modified: cfe/trunk/unittests/Lex/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Lex/CMakeLists.txt?rev=167239&r1=167238&r2=167239&view=diff
==============================================================================
--- cfe/trunk/unittests/Lex/CMakeLists.txt (original)
+++ cfe/trunk/unittests/Lex/CMakeLists.txt Thu Nov 1 12:52:58 2012
@@ -1,6 +1,7 @@
add_clang_unittest(LexTests
LexerTest.cpp
PreprocessingRecordTest.cpp
+ PPCallbacksTest.cpp
)
target_link_libraries(LexTests
Added: cfe/trunk/unittests/Lex/PPCallbacksTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Lex/PPCallbacksTest.cpp?rev=167239&view=auto
==============================================================================
--- cfe/trunk/unittests/Lex/PPCallbacksTest.cpp (added)
+++ cfe/trunk/unittests/Lex/PPCallbacksTest.cpp Thu Nov 1 12:52:58 2012
@@ -0,0 +1,248 @@
+//===- 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/Basic/Diagnostic.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/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/PathV2.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::sys;
+using namespace clang;
+
+namespace {
+
+// Stub out module loading.
+class VoidModuleLoader : public ModuleLoader {
+ virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
+ Module::NameVisibilityKind Visibility,
+ bool IsInclusionDirective) {
+ 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) {
+ 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;
+};
+
+// PPCallbacks test fixture.
+class PPCallbacksTest : public ::testing::Test {
+protected:
+ PPCallbacksTest()
+ : FileMgr(FileMgrOpts),
+ DiagID(new DiagnosticIDs()),
+ DiagOpts(new DiagnosticOptions()),
+ Diags(DiagID, DiagOpts.getPtr(), 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;
+ IntrusiveRefCntPtr<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 = path::parent_path(HeaderPath);
+ const DirectoryEntry *DE = FileMgr.getDirectory(SearchPath);
+ DirectoryLookup DL(DE, SrcMgr::C_User, true, 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) {
+ MemoryBuffer *Buf = MemoryBuffer::getMemBuffer(SourceText);
+ (void)SourceMgr.createMainFileIDForMemBuffer(Buf);
+
+ VoidModuleLoader ModLoader;
+
+ IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts = new HeaderSearchOptions();
+ HeaderSearch HeaderInfo(HSOpts, FileMgr, Diags, LangOpts, Target.getPtr());
+ AddFakeHeader(HeaderInfo, HeaderPath, SystemHeader);
+
+ IntrusiveRefCntPtr<PreprocessorOptions> PPOpts = new PreprocessorOptions();
+ Preprocessor PP(PPOpts, Diags, LangOpts,
+ Target.getPtr(),
+ SourceMgr, HeaderInfo, ModLoader,
+ /*IILookup =*/ 0,
+ /*OwnsHeaderSearch =*/false,
+ /*DelayInitialization =*/ false);
+ InclusionDirectiveCallbacks* Callbacks = new InclusionDirectiveCallbacks;
+ PP.addPPCallbacks(Callbacks); // Takes ownership.
+
+ // 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;
+ }
+};
+
+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));
+}
+
+#pragma clang diagnostic ignored "-Wtrigraphs"
+
+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));
+}
+
+} // anonoymous namespace
More information about the cfe-commits
mailing list