[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