[PATCH] D63329: Allow static linking of libc++ on Linux, just like -static-libstdc++

2019-06-14 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

In D63329#1543407 , @lebedev.ri wrote:

> Tests?


I can add a test, but I'd first like to know if this would be accepted. Test 
would be along the lines of "test/Driver/fuchsia.cpp" line 36, where it tests 
"-static-libstdc++".


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D63329/new/

https://reviews.llvm.org/D63329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D63329: Allow static linking of libc++ on Linux, just like -static-libstdc++

2019-06-14 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv created this revision.
erikjv added reviewers: dlj, cfe-commits.
Herald added a reviewer: EricWF.
Herald added a subscriber: jfb.
Herald added a project: clang.

Dynamic linking against libc++ on Linux was already supported, as is
dynamic and static linking against libstdc++. What was missing is being
able to statically link against libc++. This can be used by applications
that choose to use libc++ instead of libstdc++, but do not (or can not)
require the dynamic libraries of libc++(abi) to be installed.


Repository:
  rC Clang

https://reviews.llvm.org/D63329

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Gnu.cpp


Index: clang/lib/Driver/ToolChains/Gnu.cpp
===
--- clang/lib/Driver/ToolChains/Gnu.cpp
+++ clang/lib/Driver/ToolChains/Gnu.cpp
@@ -528,11 +528,14 @@
   if (D.CCCIsCXX() &&
   !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
 if (ToolChain.ShouldLinkCXXStdlib(Args)) {
-  bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
+  bool OnlyLibstdcxxStatic = (Args.hasArg(options::OPT_static_libstdcxx) ||
+  Args.hasArg(options::OPT_static_libcxx)) &&
  !Args.hasArg(options::OPT_static);
   if (OnlyLibstdcxxStatic)
 CmdArgs.push_back("-Bstatic");
   ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+  if (Args.hasArg(options::OPT_static_libcxx)) // libc++ links against 
libc++abi, so we have to pull that in too.
+CmdArgs.push_back("-lc++abi");
   if (OnlyLibstdcxxStatic)
 CmdArgs.push_back("-Bdynamic");
 }
@@ -564,6 +567,13 @@
 // FIXME: Does this really make sense for all GNU toolchains?
 WantPthread = true;
 
+  // FIXME: libc++ dynamically links against libpthread, so for static
+  // linking, we need to supply that dependency.
+  if (Args.hasArg(options::OPT_static_libcxx))
+// FIXME: Again, like above, does this really make sense for all GNU
+// toolchains?
+WantPthread = true;
+
   AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
 
   if (WantPthread && !isAndroid)
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2602,6 +2602,7 @@
 def specs : Separate<["-", "--"], "specs">, Flags<[Unsupported]>;
 def static_libgcc : Flag<["-"], "static-libgcc">;
 def static_libstdcxx : Flag<["-"], "static-libstdc++">;
+def static_libcxx : Flag<["-"], "static-libc++">;
 def static : Flag<["-", "--"], "static">, Flags<[NoArgumentUnused]>;
 def std_default_EQ : Joined<["-"], "std-default=">;
 def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>,


Index: clang/lib/Driver/ToolChains/Gnu.cpp
===
--- clang/lib/Driver/ToolChains/Gnu.cpp
+++ clang/lib/Driver/ToolChains/Gnu.cpp
@@ -528,11 +528,14 @@
   if (D.CCCIsCXX() &&
   !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
 if (ToolChain.ShouldLinkCXXStdlib(Args)) {
-  bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
+  bool OnlyLibstdcxxStatic = (Args.hasArg(options::OPT_static_libstdcxx) ||
+  Args.hasArg(options::OPT_static_libcxx)) &&
  !Args.hasArg(options::OPT_static);
   if (OnlyLibstdcxxStatic)
 CmdArgs.push_back("-Bstatic");
   ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+  if (Args.hasArg(options::OPT_static_libcxx)) // libc++ links against libc++abi, so we have to pull that in too.
+CmdArgs.push_back("-lc++abi");
   if (OnlyLibstdcxxStatic)
 CmdArgs.push_back("-Bdynamic");
 }
@@ -564,6 +567,13 @@
 // FIXME: Does this really make sense for all GNU toolchains?
 WantPthread = true;
 
+  // FIXME: libc++ dynamically links against libpthread, so for static
+  // linking, we need to supply that dependency.
+  if (Args.hasArg(options::OPT_static_libcxx))
+// FIXME: Again, like above, does this really make sense for all GNU
+// toolchains?
+WantPthread = true;
+
   AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
 
   if (WantPthread && !isAndroid)
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2602,6 +2602,7 @@
 def specs : Separate<["-", "--"], "specs">, Flags<[Unsupported]>;
 def static_libgcc : Flag<["-"], "static-libgcc">;
 def static_libstdcxx : Flag<["-"], "static-libstdc++">;
+def static_libcxx : Flag<["-"], "static-libc++">;
 def static : Flag<["-", "--"], "static">, Flags<[NoArgumentUnused]>;
 def std_default_EQ : Joined<["-"], "std-default=">;
 def std_EQ 

[PATCH] D45815: [libclang] Add options to limit skipping of function bodies

2018-04-26 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

About the timing testing: I'm not very familiar with boost, but it probably has 
a library that's using templates more than either LLVM or Qt. Maybe you can 
test one of those too?

LGTM otherwise.


Repository:
  rC Clang

https://reviews.llvm.org/D45815



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D38615: [libclang] Only mark CXCursors for explicit attributes with a type

2018-04-24 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv closed this revision.
erikjv added a comment.

Committed as r330692


https://reviews.llvm.org/D38615



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2018-01-05 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

lgtm. Ilya?


https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D40643: [libclang] Add function to get the buffer for a file

2017-12-06 Thread Erik Verbruggen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL319881: [libclang] Add function to get the buffer for a file 
(authored by erikjv).

Changed prior to commit:
  https://reviews.llvm.org/D40643?vs=124904=125677#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D40643

Files:
  cfe/trunk/include/clang-c/Index.h
  cfe/trunk/tools/libclang/CIndex.cpp


Index: cfe/trunk/include/clang-c/Index.h
===
--- cfe/trunk/include/clang-c/Index.h
+++ cfe/trunk/include/clang-c/Index.h
@@ -32,7 +32,7 @@
  * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
  */
 #define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 43
+#define CINDEX_VERSION_MINOR 44
 
 #define CINDEX_VERSION_ENCODE(major, minor) ( \
   ((major) * 1)   \
@@ -404,6 +404,21 @@
 const char *file_name);
 
 /**
+ * \brief Retrieve the buffer associated with the given file.
+ *
+ * \param tu the translation unit
+ *
+ * \param file the file for which to retrieve the buffer.
+ *
+ * \param size [out] if non-NULL, will be set to the size of the buffer.
+ *
+ * \returns a pointer to the buffer in memory that holds the contents of
+ * \p file, or a NULL pointer when the file is not loaded.
+ */
+CINDEX_LINKAGE const char *clang_getFileContents(CXTranslationUnit tu,
+ CXFile file, size_t *size);
+
+/**
  * \brief Returns non-zero if the \c file1 and \c file2 point to the same file,
  * or they are both NULL.
  */
Index: cfe/trunk/tools/libclang/CIndex.cpp
===
--- cfe/trunk/tools/libclang/CIndex.cpp
+++ cfe/trunk/tools/libclang/CIndex.cpp
@@ -4162,6 +4162,27 @@
   return const_cast(FMgr.getFile(file_name));
 }
 
+const char *clang_getFileContents(CXTranslationUnit TU, CXFile file,
+  size_t *size) {
+  if (isNotUsableTU(TU)) {
+LOG_BAD_TU(TU);
+return nullptr;
+  }
+
+  const SourceManager  = cxtu::getASTUnit(TU)->getSourceManager();
+  FileID fid = SM.translateFile(static_cast(file));
+  bool Invalid = true;
+  llvm::MemoryBuffer *buf = SM.getBuffer(fid, );
+  if (Invalid) {
+if (size)
+  *size = 0;
+return nullptr;
+  }
+  if (size)
+*size = buf->getBufferSize();
+  return buf->getBufferStart();
+}
+
 unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit TU,
 CXFile file) {
   if (isNotUsableTU(TU)) {


Index: cfe/trunk/include/clang-c/Index.h
===
--- cfe/trunk/include/clang-c/Index.h
+++ cfe/trunk/include/clang-c/Index.h
@@ -32,7 +32,7 @@
  * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
  */
 #define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 43
+#define CINDEX_VERSION_MINOR 44
 
 #define CINDEX_VERSION_ENCODE(major, minor) ( \
   ((major) * 1)   \
@@ -404,6 +404,21 @@
 const char *file_name);
 
 /**
+ * \brief Retrieve the buffer associated with the given file.
+ *
+ * \param tu the translation unit
+ *
+ * \param file the file for which to retrieve the buffer.
+ *
+ * \param size [out] if non-NULL, will be set to the size of the buffer.
+ *
+ * \returns a pointer to the buffer in memory that holds the contents of
+ * \p file, or a NULL pointer when the file is not loaded.
+ */
+CINDEX_LINKAGE const char *clang_getFileContents(CXTranslationUnit tu,
+ CXFile file, size_t *size);
+
+/**
  * \brief Returns non-zero if the \c file1 and \c file2 point to the same file,
  * or they are both NULL.
  */
Index: cfe/trunk/tools/libclang/CIndex.cpp
===
--- cfe/trunk/tools/libclang/CIndex.cpp
+++ cfe/trunk/tools/libclang/CIndex.cpp
@@ -4162,6 +4162,27 @@
   return const_cast(FMgr.getFile(file_name));
 }
 
+const char *clang_getFileContents(CXTranslationUnit TU, CXFile file,
+  size_t *size) {
+  if (isNotUsableTU(TU)) {
+LOG_BAD_TU(TU);
+return nullptr;
+  }
+
+  const SourceManager  = cxtu::getASTUnit(TU)->getSourceManager();
+  FileID fid = SM.translateFile(static_cast(file));
+  bool Invalid = true;
+  llvm::MemoryBuffer *buf = SM.getBuffer(fid, );
+  if (Invalid) {
+if (size)
+  *size = 0;
+return nullptr;
+  }
+  if (size)
+*size = buf->getBufferSize();
+  return buf->getBufferStart();
+}
+
 unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit TU,
 CXFile file) {
   if (isNotUsableTU(TU)) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D40643: [libclang] Add function to get the buffer for a file

2017-11-30 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv updated this revision to Diff 124904.
erikjv added a comment.

Bumped the CINDEX_VERSION_MINOR.


https://reviews.llvm.org/D40643

Files:
  include/clang-c/Index.h
  tools/libclang/CIndex.cpp


Index: tools/libclang/CIndex.cpp
===
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -4151,6 +4151,27 @@
   return const_cast(FMgr.getFile(file_name));
 }
 
+const char *clang_getFileContents(CXTranslationUnit TU, CXFile file,
+  size_t *size) {
+  if (isNotUsableTU(TU)) {
+LOG_BAD_TU(TU);
+return nullptr;
+  }
+
+  const SourceManager  = cxtu::getASTUnit(TU)->getSourceManager();
+  FileID fid = SM.translateFile(static_cast(file));
+  bool Invalid = true;
+  llvm::MemoryBuffer *buf = SM.getBuffer(fid, );
+  if (Invalid) {
+if (size)
+  *size = 0;
+return nullptr;
+  }
+  if (size)
+*size = buf->getBufferSize();
+  return buf->getBufferStart();
+}
+
 unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit TU,
 CXFile file) {
   if (isNotUsableTU(TU)) {
Index: include/clang-c/Index.h
===
--- include/clang-c/Index.h
+++ include/clang-c/Index.h
@@ -32,7 +32,7 @@
  * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
  */
 #define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 43
+#define CINDEX_VERSION_MINOR 44
 
 #define CINDEX_VERSION_ENCODE(major, minor) ( \
   ((major) * 1)   \
@@ -394,6 +394,21 @@
 const char *file_name);
 
 /**
+ * \brief Retrieve the buffer associated with the given file.
+ *
+ * \param tu the translation unit
+ *
+ * \param file the file for which to retrieve the buffer.
+ *
+ * \param size [out] if non-NULL, will be set to the size of the buffer.
+ *
+ * \returns a pointer to the buffer in memory that holds the contents of
+ * \p file, or a NULL pointer when the file is not loaded.
+ */
+CINDEX_LINKAGE const char *clang_getFileContents(CXTranslationUnit tu,
+ CXFile file, size_t *size);
+
+/**
  * \brief Returns non-zero if the \c file1 and \c file2 point to the same file,
  * or they are both NULL.
  */


Index: tools/libclang/CIndex.cpp
===
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -4151,6 +4151,27 @@
   return const_cast(FMgr.getFile(file_name));
 }
 
+const char *clang_getFileContents(CXTranslationUnit TU, CXFile file,
+  size_t *size) {
+  if (isNotUsableTU(TU)) {
+LOG_BAD_TU(TU);
+return nullptr;
+  }
+
+  const SourceManager  = cxtu::getASTUnit(TU)->getSourceManager();
+  FileID fid = SM.translateFile(static_cast(file));
+  bool Invalid = true;
+  llvm::MemoryBuffer *buf = SM.getBuffer(fid, );
+  if (Invalid) {
+if (size)
+  *size = 0;
+return nullptr;
+  }
+  if (size)
+*size = buf->getBufferSize();
+  return buf->getBufferStart();
+}
+
 unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit TU,
 CXFile file) {
   if (isNotUsableTU(TU)) {
Index: include/clang-c/Index.h
===
--- include/clang-c/Index.h
+++ include/clang-c/Index.h
@@ -32,7 +32,7 @@
  * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
  */
 #define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 43
+#define CINDEX_VERSION_MINOR 44
 
 #define CINDEX_VERSION_ENCODE(major, minor) ( \
   ((major) * 1)   \
@@ -394,6 +394,21 @@
 const char *file_name);
 
 /**
+ * \brief Retrieve the buffer associated with the given file.
+ *
+ * \param tu the translation unit
+ *
+ * \param file the file for which to retrieve the buffer.
+ *
+ * \param size [out] if non-NULL, will be set to the size of the buffer.
+ *
+ * \returns a pointer to the buffer in memory that holds the contents of
+ * \p file, or a NULL pointer when the file is not loaded.
+ */
+CINDEX_LINKAGE const char *clang_getFileContents(CXTranslationUnit tu,
+ CXFile file, size_t *size);
+
+/**
  * \brief Returns non-zero if the \c file1 and \c file2 point to the same file,
  * or they are both NULL.
  */
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33765: Show correct column nr. when multi-byte utf8 chars are used.

2017-11-30 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv updated this revision to Diff 124903.
erikjv added a comment.

I moved all code to the TextDiagnostics, so all other interfaces still get byte 
offsets.


https://reviews.llvm.org/D33765

Files:
  lib/Frontend/TextDiagnostic.cpp
  test/Misc/diag-utf8.cpp


Index: test/Misc/diag-utf8.cpp
===
--- /dev/null
+++ test/Misc/diag-utf8.cpp
@@ -0,0 +1,10 @@
+// RUN: not %clang_cc1 -fsyntax-only %s 2>&1 | FileCheck %s
+
+struct Foo { int member; };
+
+void f(Foo foo)
+{
+"ideeen" << foo; // CHECK: {{.*[/\\]}}diag-utf8.cpp:7:14: error: invalid 
operands to binary expression ('const char *' and 'Foo')
+"ideëen" << foo; // CHECK: {{.*[/\\]}}diag-utf8.cpp:8:14: error: invalid 
operands to binary expression ('const char *' and 'Foo')
+"idez̈en" << foo; // CHECK: {{.*[/\\]}}diag-utf8.cpp:9:14: error: invalid 
operands to binary expression ('const char *' and 'Foo')
+}
Index: lib/Frontend/TextDiagnostic.cpp
===
--- lib/Frontend/TextDiagnostic.cpp
+++ lib/Frontend/TextDiagnostic.cpp
@@ -19,6 +19,7 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Locale.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/Unicode.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
 
@@ -818,6 +819,28 @@
   if (DiagOpts->ShowColumn)
 // Compute the column number.
 if (unsigned ColNo = PLoc.getColumn()) {
+  // Correct the column number for multi-byte UTF-8 code-points.
+  bool Invalid = false;
+  StringRef BufData = Loc.getBufferData();
+  if (!Invalid) {
+const char *BufStart = BufData.data();
+const char *BufEnd = BufStart + BufData.size();
+
+// Decompose the location into a FID/Offset pair.
+std::pair LocInfo = Loc.getDecomposedLoc();
+FileID FID = LocInfo.first;
+const SourceManager  = Loc.getManager();
+const char *LineStart =
+BufStart +
+SM.getDecomposedLoc(SM.translateLineCol(FID, LineNo, 1)).second;
+if (LineStart + ColNo < BufEnd) {
+  StringRef SourceLine(LineStart, ColNo);
+  int CorrectedColNo = llvm::sys::unicode::columnWidthUTF8(SourceLine);
+  if (CorrectedColNo != -1)
+ColNo = unsigned(CorrectedColNo);
+}
+  }
+
   if (DiagOpts->getFormat() == DiagnosticOptions::MSVC) {
 OS << ',';
 // Visual Studio 2010 or earlier expects column number to be off by one


Index: test/Misc/diag-utf8.cpp
===
--- /dev/null
+++ test/Misc/diag-utf8.cpp
@@ -0,0 +1,10 @@
+// RUN: not %clang_cc1 -fsyntax-only %s 2>&1 | FileCheck %s
+
+struct Foo { int member; };
+
+void f(Foo foo)
+{
+"ideeen" << foo; // CHECK: {{.*[/\\]}}diag-utf8.cpp:7:14: error: invalid operands to binary expression ('const char *' and 'Foo')
+"ideëen" << foo; // CHECK: {{.*[/\\]}}diag-utf8.cpp:8:14: error: invalid operands to binary expression ('const char *' and 'Foo')
+"idez̈en" << foo; // CHECK: {{.*[/\\]}}diag-utf8.cpp:9:14: error: invalid operands to binary expression ('const char *' and 'Foo')
+}
Index: lib/Frontend/TextDiagnostic.cpp
===
--- lib/Frontend/TextDiagnostic.cpp
+++ lib/Frontend/TextDiagnostic.cpp
@@ -19,6 +19,7 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Locale.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/Unicode.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
 
@@ -818,6 +819,28 @@
   if (DiagOpts->ShowColumn)
 // Compute the column number.
 if (unsigned ColNo = PLoc.getColumn()) {
+  // Correct the column number for multi-byte UTF-8 code-points.
+  bool Invalid = false;
+  StringRef BufData = Loc.getBufferData();
+  if (!Invalid) {
+const char *BufStart = BufData.data();
+const char *BufEnd = BufStart + BufData.size();
+
+// Decompose the location into a FID/Offset pair.
+std::pair LocInfo = Loc.getDecomposedLoc();
+FileID FID = LocInfo.first;
+const SourceManager  = Loc.getManager();
+const char *LineStart =
+BufStart +
+SM.getDecomposedLoc(SM.translateLineCol(FID, LineNo, 1)).second;
+if (LineStart + ColNo < BufEnd) {
+  StringRef SourceLine(LineStart, ColNo);
+  int CorrectedColNo = llvm::sys::unicode::columnWidthUTF8(SourceLine);
+  if (CorrectedColNo != -1)
+ColNo = unsigned(CorrectedColNo);
+}
+  }
+
   if (DiagOpts->getFormat() == DiagnosticOptions::MSVC) {
 OS << ',';
 // Visual Studio 2010 or earlier expects column number to be off by one
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D40643: [libclang] Add function to get the buffer for a file

2017-11-30 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv created this revision.

This can be used by clients in conjunction with an offset returned by
e.g. clang_getFileLocation. Now those clients do not need to also
open/read the file.


https://reviews.llvm.org/D40643

Files:
  include/clang-c/Index.h
  tools/libclang/CIndex.cpp


Index: tools/libclang/CIndex.cpp
===
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -4151,6 +4151,27 @@
   return const_cast(FMgr.getFile(file_name));
 }
 
+const char *clang_getFileContents(CXTranslationUnit TU, CXFile file,
+  size_t *size) {
+  if (isNotUsableTU(TU)) {
+LOG_BAD_TU(TU);
+return nullptr;
+  }
+
+  const SourceManager  = cxtu::getASTUnit(TU)->getSourceManager();
+  FileID fid = SM.translateFile(static_cast(file));
+  bool Invalid = true;
+  llvm::MemoryBuffer *buf = SM.getBuffer(fid, );
+  if (Invalid) {
+if (size)
+  *size = 0;
+return nullptr;
+  }
+  if (size)
+*size = buf->getBufferSize();
+  return buf->getBufferStart();
+}
+
 unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit TU,
 CXFile file) {
   if (isNotUsableTU(TU)) {
Index: include/clang-c/Index.h
===
--- include/clang-c/Index.h
+++ include/clang-c/Index.h
@@ -394,6 +394,21 @@
 const char *file_name);
 
 /**
+ * \brief Retrieve the buffer associated with the given file.
+ *
+ * \param tu the translation unit
+ *
+ * \param file the file for which to retrieve the buffer.
+ *
+ * \param size [out] if non-NULL, will be set to the size of the buffer.
+ *
+ * \returns a pointer to the buffer in memory that holds the contents of
+ * \p file, or a NULL pointer when the file is not loaded.
+ */
+CINDEX_LINKAGE const char *clang_getFileContents(CXTranslationUnit tu,
+ CXFile file, size_t *size);
+
+/**
  * \brief Returns non-zero if the \c file1 and \c file2 point to the same file,
  * or they are both NULL.
  */


Index: tools/libclang/CIndex.cpp
===
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -4151,6 +4151,27 @@
   return const_cast(FMgr.getFile(file_name));
 }
 
+const char *clang_getFileContents(CXTranslationUnit TU, CXFile file,
+  size_t *size) {
+  if (isNotUsableTU(TU)) {
+LOG_BAD_TU(TU);
+return nullptr;
+  }
+
+  const SourceManager  = cxtu::getASTUnit(TU)->getSourceManager();
+  FileID fid = SM.translateFile(static_cast(file));
+  bool Invalid = true;
+  llvm::MemoryBuffer *buf = SM.getBuffer(fid, );
+  if (Invalid) {
+if (size)
+  *size = 0;
+return nullptr;
+  }
+  if (size)
+*size = buf->getBufferSize();
+  return buf->getBufferStart();
+}
+
 unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit TU,
 CXFile file) {
   if (isNotUsableTU(TU)) {
Index: include/clang-c/Index.h
===
--- include/clang-c/Index.h
+++ include/clang-c/Index.h
@@ -394,6 +394,21 @@
 const char *file_name);
 
 /**
+ * \brief Retrieve the buffer associated with the given file.
+ *
+ * \param tu the translation unit
+ *
+ * \param file the file for which to retrieve the buffer.
+ *
+ * \param size [out] if non-NULL, will be set to the size of the buffer.
+ *
+ * \returns a pointer to the buffer in memory that holds the contents of
+ * \p file, or a NULL pointer when the file is not loaded.
+ */
+CINDEX_LINKAGE const char *clang_getFileContents(CXTranslationUnit tu,
+ CXFile file, size_t *size);
+
+/**
  * \brief Returns non-zero if the \c file1 and \c file2 point to the same file,
  * or they are both NULL.
  */
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D40640: Fix code completion crash with unresolved member expr and explicit base

2017-11-30 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv created this revision.

This is actually a failing assert. When doing object argument
initialization, it is valid to have e.g. 'this' as a base in a member
access expression (which is a prvalue). It's also possible to have a
scope specifier as part of the member expression, in which case a base
that is an actual lvalue gets wrapped in an ImplicitCastExpr, which in
turn is an rvalue.


https://reviews.llvm.org/D40640

Files:
  lib/Sema/SemaOverload.cpp
  test/CodeCompletion/member-access.cpp

Index: test/CodeCompletion/member-access.cpp
===
--- test/CodeCompletion/member-access.cpp
+++ test/CodeCompletion/member-access.cpp
@@ -42,10 +42,19 @@
   static void foo(bool);
 };
 
-struct Bar {
+struct Bar: Foo {
   void foo(bool param) {
 Foo::foo(  );// unresolved member expression with an implicit base
   }
+
+  void mooze(bool param) {
+this->Foo::foo(  );// unresolved member expression with an explicit base
+  }
+
+  void mooze(bool param, int anotherParam) {
+Bar *that = new Bar;
+that->Foo::foo(  );// unresolved member expression with an explicit base wrapped in a ImplicitCastExpr
+  }
 };
 
   // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:29:6 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
@@ -66,6 +75,8 @@
 
 // Make sure this also doesn't crash
 // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:47:14 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:51:21 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:56:21 %s
 
 
 template
@@ -100,8 +111,8 @@
 // CHECK-CC2: overload1 : [#void#]overload1(<#const T 

[PATCH] D38578: [preamble] Also record the "skipping" state of the preprocessor

2017-11-28 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv closed this revision.
erikjv added a comment.

Submitted as r317308.


https://reviews.llvm.org/D38578



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-11-28 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

Maybe something like this works:

  --- a/tools/libclang/CIndex.cpp
  +++ b/tools/libclang/CIndex.cpp
  @@ -8090,6 +8090,7 @@ CXSourceRangeList 
*clang_getSkippedRanges(CXTranslationUnit TU, CXFile file) {
 SourceManager  = Ctx.getSourceManager();
 FileEntry *fileEntry = static_cast(file);
 FileID wantedFileID = sm.translateFile(fileEntry);
  +  bool isMainFile = wantedFileID == sm.getMainFileID();
   
 const std::vector  = ppRec->getSkippedRanges();
 std::vector wantedRanges;
  @@ -8097,6 +8098,8 @@ CXSourceRangeList 
*clang_getSkippedRanges(CXTranslationUnit TU, CXFile file) {
  i != ei; ++i) {
   if (sm.getFileID(i->getBegin()) == wantedFileID || 
sm.getFileID(i->getEnd()) == wantedFileID)
 wantedRanges.push_back(*i);
  +else if (isMainFile && (astUnit->isInPreambleFileID(i->getBegin()) || 
astUnit->isInPreambleFileID(i->getEnd(
  +  wantedRanges.push_back(*i);
 }
   
 skipped->count = wantedRanges.size();


https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D37554: [libclang] Allow crash recovery with LIBCLANG_NOTHREADS

2017-11-14 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv closed this revision.
erikjv added a comment.

Committed as r318142.


https://reviews.llvm.org/D37554



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-11-03 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

The patch has aged a bit since upload, so does it still apply? And, can you add 
a testcase please?


Repository:
  rL LLVM

https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D38618: Do not add a colon chunk to the code completion of class inheritance access modifiers

2017-10-24 Thread Erik Verbruggen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL316436: Do not add a colon chunk to the code completion of 
class inheritance access… (authored by erikjv).

Changed prior to commit:
  https://reviews.llvm.org/D38618?vs=119273=120067#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D38618

Files:
  cfe/trunk/include/clang/Sema/Scope.h
  cfe/trunk/lib/Parse/ParseDeclCXX.cpp
  cfe/trunk/lib/Sema/SemaCodeComplete.cpp
  cfe/trunk/test/Index/complete-super.cpp


Index: cfe/trunk/include/clang/Sema/Scope.h
===
--- cfe/trunk/include/clang/Sema/Scope.h
+++ cfe/trunk/include/clang/Sema/Scope.h
@@ -127,6 +127,9 @@
 
 /// This is a compound statement scope.
 CompoundStmtScope = 0x40,
+
+/// We are between inheritance colon and the real class/struct definition 
scope.
+ClassInheritanceScope = 0x80,
   };
 private:
   /// The parent scope for this scope.  This is null for the translation-unit
Index: cfe/trunk/test/Index/complete-super.cpp
===
--- cfe/trunk/test/Index/complete-super.cpp
+++ cfe/trunk/test/Index/complete-super.cpp
@@ -40,3 +40,8 @@
 // CHECK-ACCESS-PATTERN: NotImplemented:{TypedText private}{Colon :} (40)
 // CHECK-ACCESS-PATTERN: NotImplemented:{TypedText protected}{Colon :} (40)
 // CHECK-ACCESS-PATTERN: NotImplemented:{TypedText public}{Colon :} (40)
+
+// RUN: env CINDEXTEST_CODE_COMPLETE_PATTERNS=1 c-index-test 
-code-completion-at=%s:10:12 %s | FileCheck 
-check-prefix=CHECK-INHERITANCE-PATTERN %s
+// CHECK-INHERITANCE-PATTERN: NotImplemented:{TypedText private} (40)
+// CHECK-INHERITANCE-PATTERN: NotImplemented:{TypedText protected} (40)
+// CHECK-INHERITANCE-PATTERN: NotImplemented:{TypedText public} (40)
Index: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
===
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp
@@ -1658,21 +1658,23 @@
   if (CCC == Sema::PCC_Class) {
 AddTypedefResult(Results);
 
+bool IsNotInheritanceScope =
+!(S->getFlags() & Scope::ClassInheritanceScope);
 // public:
 Builder.AddTypedTextChunk("public");
-if (Results.includeCodePatterns())
+if (IsNotInheritanceScope && Results.includeCodePatterns())
   Builder.AddChunk(CodeCompletionString::CK_Colon);
 Results.AddResult(Result(Builder.TakeString()));
 
 // protected:
 Builder.AddTypedTextChunk("protected");
-if (Results.includeCodePatterns())
+if (IsNotInheritanceScope && Results.includeCodePatterns())
   Builder.AddChunk(CodeCompletionString::CK_Colon);
 Results.AddResult(Result(Builder.TakeString()));
 
 // private:
 Builder.AddTypedTextChunk("private");
-if (Results.includeCodePatterns())
+if (IsNotInheritanceScope && Results.includeCodePatterns())
   Builder.AddChunk(CodeCompletionString::CK_Colon);
 Results.AddResult(Result(Builder.TakeString()));
   }
Index: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
===
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp
@@ -3195,6 +3195,9 @@
   }
 
   if (Tok.is(tok::colon)) {
+ParseScope InheritanceScope(this, getCurScope()->getFlags() |
+  Scope::ClassInheritanceScope);
+
 ParseBaseClause(TagDecl);
 if (!Tok.is(tok::l_brace)) {
   bool SuggestFixIt = false;


Index: cfe/trunk/include/clang/Sema/Scope.h
===
--- cfe/trunk/include/clang/Sema/Scope.h
+++ cfe/trunk/include/clang/Sema/Scope.h
@@ -127,6 +127,9 @@
 
 /// This is a compound statement scope.
 CompoundStmtScope = 0x40,
+
+/// We are between inheritance colon and the real class/struct definition scope.
+ClassInheritanceScope = 0x80,
   };
 private:
   /// The parent scope for this scope.  This is null for the translation-unit
Index: cfe/trunk/test/Index/complete-super.cpp
===
--- cfe/trunk/test/Index/complete-super.cpp
+++ cfe/trunk/test/Index/complete-super.cpp
@@ -40,3 +40,8 @@
 // CHECK-ACCESS-PATTERN: NotImplemented:{TypedText private}{Colon :} (40)
 // CHECK-ACCESS-PATTERN: NotImplemented:{TypedText protected}{Colon :} (40)
 // CHECK-ACCESS-PATTERN: NotImplemented:{TypedText public}{Colon :} (40)
+
+// RUN: env CINDEXTEST_CODE_COMPLETE_PATTERNS=1 c-index-test -code-completion-at=%s:10:12 %s | FileCheck -check-prefix=CHECK-INHERITANCE-PATTERN %s
+// CHECK-INHERITANCE-PATTERN: NotImplemented:{TypedText private} (40)
+// CHECK-INHERITANCE-PATTERN: NotImplemented:{TypedText protected} (40)
+// CHECK-INHERITANCE-PATTERN: NotImplemented:{TypedText public} (40)
Index: 

[PATCH] D38578: [preamble] Also record the "skipping" state of the preprocessor

2017-10-06 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv updated this revision to Diff 117986.

https://reviews.llvm.org/D38578

Files:
  include/clang/Lex/Preprocessor.h
  lib/Lex/PPDirectives.cpp
  lib/Lex/Preprocessor.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTWriter.cpp
  test/Index/preamble-conditionals-inverted.cpp
  test/Index/preamble-conditionals-skipping.cpp

Index: test/Index/preamble-conditionals-skipping.cpp
===
--- /dev/null
+++ test/Index/preamble-conditionals-skipping.cpp
@@ -0,0 +1,16 @@
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 \
+// RUN:   local -std=c++14 %s 2>&1 \
+// RUN: | FileCheck %s --implicit-check-not "error:"
+
+#ifdef MYCPLUSPLUS
+extern "C" {
+#endif
+
+#ifdef MYCPLUSPLUS
+}
+#endif
+
+int main()
+{
+return 0;
+}
Index: test/Index/preamble-conditionals-inverted.cpp
===
--- test/Index/preamble-conditionals-inverted.cpp
+++ test/Index/preamble-conditionals-inverted.cpp
@@ -3,6 +3,8 @@
 // RUN: | FileCheck %s --implicit-check-not "error:"
 #ifdef FOO_H
 
-void foo();
+void foo() {}
 
 #endif
+
+int foo() { return 0; }
Index: lib/Serialization/ASTWriter.cpp
===
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -2407,6 +2407,17 @@
 
   if (PP.isRecordingPreamble() && PP.hasRecordedPreamble()) {
 assert(!IsModule);
+auto SkipInfo = PP.getPreambleSkipInfo();
+if (SkipInfo.hasValue()) {
+  Record.push_back(true);
+  AddSourceLocation(SkipInfo->HashTokenLoc, Record);
+  AddSourceLocation(SkipInfo->IfTokenLoc, Record);
+  Record.push_back(SkipInfo->FoundNonSkipPortion);
+  Record.push_back(SkipInfo->FoundElse);
+  AddSourceLocation(SkipInfo->ElseLoc, Record);
+} else {
+  Record.push_back(false);
+}
 for (const auto  : PP.getPreambleConditionalStack()) {
   AddSourceLocation(Cond.IfLoc, Record);
   Record.push_back(Cond.WasSkipping);
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -2995,16 +2995,28 @@
 
 case PP_CONDITIONAL_STACK:
   if (!Record.empty()) {
+unsigned Idx = 0, End = Record.size() - 1;
+bool ReachedEOFWhileSkipping = Record[Idx++];
+llvm::Optional SkipInfo;
+if (ReachedEOFWhileSkipping) {
+  SourceLocation HashToken = ReadSourceLocation(F, Record, Idx);
+  SourceLocation IfTokenLoc = ReadSourceLocation(F, Record, Idx);
+  bool FoundNonSkipPortion = Record[Idx++];
+  bool FoundElse = Record[Idx++];
+  SourceLocation ElseLoc = ReadSourceLocation(F, Record, Idx);
+  SkipInfo.emplace(HashToken, IfTokenLoc, FoundNonSkipPortion,
+   FoundElse, ElseLoc);
+}
 SmallVector ConditionalStack;
-for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) {
+while (Idx < End) {
   auto Loc = ReadSourceLocation(F, Record, Idx);
   bool WasSkipping = Record[Idx++];
   bool FoundNonSkip = Record[Idx++];
   bool FoundElse = Record[Idx++];
   ConditionalStack.push_back(
   {Loc, WasSkipping, FoundNonSkip, FoundElse});
 }
-PP.setReplayablePreambleConditionalStack(ConditionalStack);
+PP.setReplayablePreambleConditionalStack(ConditionalStack, SkipInfo);
   }
   break;
 
Index: lib/Lex/Preprocessor.cpp
===
--- lib/Lex/Preprocessor.cpp
+++ lib/Lex/Preprocessor.cpp
@@ -544,6 +544,13 @@
"CurPPLexer is null when calling replayPreambleConditionalStack.");
 CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack());
 PreambleConditionalStack.doneReplaying();
+if (PreambleConditionalStack.reachedEOFWhileSkipping())
+  SkipExcludedConditionalBlock(
+  PreambleConditionalStack.SkipInfo->HashTokenLoc,
+  PreambleConditionalStack.SkipInfo->IfTokenLoc,
+  PreambleConditionalStack.SkipInfo->FoundNonSkipPortion,
+  PreambleConditionalStack.SkipInfo->FoundElse,
+  PreambleConditionalStack.SkipInfo->ElseLoc);
   }
 }
 
Index: lib/Lex/PPDirectives.cpp
===
--- lib/Lex/PPDirectives.cpp
+++ lib/Lex/PPDirectives.cpp
@@ -350,16 +350,19 @@
 /// If ElseOk is true, then \#else directives are ok, if not, then we have
 /// already seen one so a \#else directive is a duplicate.  When this returns,
 /// the caller can lex the first valid token.
-void Preprocessor::SkipExcludedConditionalBlock(const Token ,
+void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,

[PATCH] D38615: [libclang] Only mark CXCursors for explicit attributes with a type

2017-10-06 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv updated this revision to Diff 117975.
erikjv added a comment.

Added more context to the diff


https://reviews.llvm.org/D38615

Files:
  test/Index/annotate-tokens-unexposed.cpp
  tools/libclang/CIndex.cpp


Index: tools/libclang/CIndex.cpp
===
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -1772,7 +1772,7 @@
 
 bool CursorVisitor::VisitAttributes(Decl *D) {
   for (const auto *I : D->attrs())
-if (Visit(MakeCXCursor(I, D, TU)))
+if (!I->isImplicit() && Visit(MakeCXCursor(I, D, TU)))
 return true;
 
   return false;
Index: test/Index/annotate-tokens-unexposed.cpp
===
--- /dev/null
+++ test/Index/annotate-tokens-unexposed.cpp
@@ -0,0 +1,20 @@
+// RUN: c-index-test -test-annotate-tokens=%s:1:1:16:1 %s -target 
x86_64-pc-windows-msvc | FileCheck %s
+class Foo
+{
+public:
+void step(int v);
+Foo();
+};
+
+void bar()
+{
+// Introduce a MSInheritanceAttr node on the CXXRecordDecl for Foo. The
+// existance of this attribute should not mark all cursors for tokens in
+// Foo as UnexposedAttr.
+::step;
+}
+
+Foo::Foo()
+{}
+
+// CHECK-NOT: UnexposedAttr=


Index: tools/libclang/CIndex.cpp
===
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -1772,7 +1772,7 @@
 
 bool CursorVisitor::VisitAttributes(Decl *D) {
   for (const auto *I : D->attrs())
-if (Visit(MakeCXCursor(I, D, TU)))
+if (!I->isImplicit() && Visit(MakeCXCursor(I, D, TU)))
 return true;
 
   return false;
Index: test/Index/annotate-tokens-unexposed.cpp
===
--- /dev/null
+++ test/Index/annotate-tokens-unexposed.cpp
@@ -0,0 +1,20 @@
+// RUN: c-index-test -test-annotate-tokens=%s:1:1:16:1 %s -target x86_64-pc-windows-msvc | FileCheck %s
+class Foo
+{
+public:
+void step(int v);
+Foo();
+};
+
+void bar()
+{
+// Introduce a MSInheritanceAttr node on the CXXRecordDecl for Foo. The
+// existance of this attribute should not mark all cursors for tokens in
+// Foo as UnexposedAttr.
+::step;
+}
+
+Foo::Foo()
+{}
+
+// CHECK-NOT: UnexposedAttr=
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D38615: [libclang] Only mark CXCursors for explicit attributes with a type

2017-10-06 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv created this revision.

All attributes have a source range associated with it. However, implicit
attributes are added by the compiler, and not added because the user
wrote something in the input. So no token type should be set to
CXCursor_*Attr.

The problem was visible when a class gets marked by e.g.
MSInheritanceAttr, which has the full CXXRecordDecl's range as its
own range. The effect of marking that range as CXCursor_UnexposedAttr
was that all cursors for the record decl, including all child decls,
would become CXCursor_UnexposedAttr.


https://reviews.llvm.org/D38615

Files:
  test/Index/annotate-tokens-unexposed.cpp
  tools/libclang/CIndex.cpp


Index: tools/libclang/CIndex.cpp
===
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -1772,7 +1772,7 @@
 
 bool CursorVisitor::VisitAttributes(Decl *D) {
   for (const auto *I : D->attrs())
-if (Visit(MakeCXCursor(I, D, TU)))
+if (!I->isImplicit() && Visit(MakeCXCursor(I, D, TU)))
 return true;
 
   return false;
Index: test/Index/annotate-tokens-unexposed.cpp
===
--- /dev/null
+++ test/Index/annotate-tokens-unexposed.cpp
@@ -0,0 +1,20 @@
+// RUN: c-index-test -test-annotate-tokens=%s:1:1:16:1 %s -target 
x86_64-pc-windows-msvc | FileCheck %s
+class Foo
+{
+public:
+void step(int v);
+Foo();
+};
+
+void bar()
+{
+// Introduce a MSInheritanceAttr node on the CXXRecordDecl for Foo. The
+// existance of this attribute should not mark all cursors for tokens in
+// Foo as UnexposedAttr.
+::step;
+}
+
+Foo::Foo()
+{}
+
+// CHECK-NOT: UnexposedAttr=


Index: tools/libclang/CIndex.cpp
===
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -1772,7 +1772,7 @@
 
 bool CursorVisitor::VisitAttributes(Decl *D) {
   for (const auto *I : D->attrs())
-if (Visit(MakeCXCursor(I, D, TU)))
+if (!I->isImplicit() && Visit(MakeCXCursor(I, D, TU)))
 return true;
 
   return false;
Index: test/Index/annotate-tokens-unexposed.cpp
===
--- /dev/null
+++ test/Index/annotate-tokens-unexposed.cpp
@@ -0,0 +1,20 @@
+// RUN: c-index-test -test-annotate-tokens=%s:1:1:16:1 %s -target x86_64-pc-windows-msvc | FileCheck %s
+class Foo
+{
+public:
+void step(int v);
+Foo();
+};
+
+void bar()
+{
+// Introduce a MSInheritanceAttr node on the CXXRecordDecl for Foo. The
+// existance of this attribute should not mark all cursors for tokens in
+// Foo as UnexposedAttr.
+::step;
+}
+
+Foo::Foo()
+{}
+
+// CHECK-NOT: UnexposedAttr=
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D38578: [preamble] Also record the "skipping" state of the preprocessor

2017-10-05 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv created this revision.

When a preamble ends in a conditional preprocessor block that is being
skipped, the preprocessor needs to continue skipping that block when
the preamble is used.

This fixes PR34570.


https://reviews.llvm.org/D38578

Files:
  include/clang/Lex/Preprocessor.h
  lib/Lex/PPDirectives.cpp
  lib/Lex/Preprocessor.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTWriter.cpp
  test/Index/preamble-conditionals-inverted.cpp
  test/Index/preamble-conditionals-skipping.cpp

Index: test/Index/preamble-conditionals-skipping.cpp
===
--- /dev/null
+++ test/Index/preamble-conditionals-skipping.cpp
@@ -0,0 +1,16 @@
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 \
+// RUN:   local -std=c++14 %s 2>&1 \
+// RUN: | FileCheck %s --implicit-check-not "error:"
+
+#ifdef MYCPLUSPLUS
+extern "C" {
+#endif
+
+#ifdef MYCPLUSPLUS
+}
+#endif
+
+int main()
+{
+return 0;
+}
Index: test/Index/preamble-conditionals-inverted.cpp
===
--- test/Index/preamble-conditionals-inverted.cpp
+++ test/Index/preamble-conditionals-inverted.cpp
@@ -3,6 +3,8 @@
 // RUN: | FileCheck %s --implicit-check-not "error:"
 #ifdef FOO_H
 
-void foo();
+void foo() {}
 
 #endif
+
+int foo() { return 0; }
Index: lib/Serialization/ASTWriter.cpp
===
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -2407,6 +2407,13 @@
 
   if (PP.isRecordingPreamble() && PP.hasRecordedPreamble()) {
 assert(!IsModule);
+const Preprocessor::PreambleSkipInfo  = PP.getPreambleSkipInfo();
+Record.push_back(SkipInfo.ReachedEOFWhileSkipping);
+AddSourceLocation(SkipInfo.HashToken, Record);
+AddSourceLocation(SkipInfo.IfTokenLoc, Record);
+Record.push_back(SkipInfo.FoundNonSkipPortion);
+Record.push_back(SkipInfo.FoundElse);
+AddSourceLocation(SkipInfo.ElseLoc, Record);
 for (const auto  : PP.getPreambleConditionalStack()) {
   AddSourceLocation(Cond.IfLoc, Record);
   Record.push_back(Cond.WasSkipping);
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -2995,16 +2995,24 @@
 
 case PP_CONDITIONAL_STACK:
   if (!Record.empty()) {
+unsigned Idx = 0, End = Record.size() - 1;
+Preprocessor::PreambleSkipInfo SkipInfo;
+SkipInfo.ReachedEOFWhileSkipping = Record[Idx++];
+SkipInfo.HashToken = ReadSourceLocation(F, Record, Idx);
+SkipInfo.IfTokenLoc = ReadSourceLocation(F, Record, Idx);
+SkipInfo.FoundNonSkipPortion = Record[Idx++];
+SkipInfo.FoundElse = Record[Idx++];
+SkipInfo.ElseLoc = ReadSourceLocation(F, Record, Idx);
 SmallVector ConditionalStack;
-for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) {
+while (Idx < End) {
   auto Loc = ReadSourceLocation(F, Record, Idx);
   bool WasSkipping = Record[Idx++];
   bool FoundNonSkip = Record[Idx++];
   bool FoundElse = Record[Idx++];
   ConditionalStack.push_back(
   {Loc, WasSkipping, FoundNonSkip, FoundElse});
 }
-PP.setReplayablePreambleConditionalStack(ConditionalStack);
+PP.setReplayablePreambleConditionalStack(ConditionalStack, SkipInfo);
   }
   break;
 
Index: lib/Lex/Preprocessor.cpp
===
--- lib/Lex/Preprocessor.cpp
+++ lib/Lex/Preprocessor.cpp
@@ -544,6 +544,13 @@
"CurPPLexer is null when calling replayPreambleConditionalStack.");
 CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack());
 PreambleConditionalStack.doneReplaying();
+if (PreambleConditionalStack.reachedEOFWhileSkipping())
+  SkipExcludedConditionalBlock(
+  PreambleConditionalStack.SkipInfo.HashToken,
+  PreambleConditionalStack.SkipInfo.IfTokenLoc,
+  PreambleConditionalStack.SkipInfo.FoundNonSkipPortion,
+  PreambleConditionalStack.SkipInfo.FoundElse,
+  PreambleConditionalStack.SkipInfo.ElseLoc);
   }
 }
 
Index: lib/Lex/PPDirectives.cpp
===
--- lib/Lex/PPDirectives.cpp
+++ lib/Lex/PPDirectives.cpp
@@ -350,16 +350,19 @@
 /// If ElseOk is true, then \#else directives are ok, if not, then we have
 /// already seen one so a \#else directive is a duplicate.  When this returns,
 /// the caller can lex the first valid token.
-void Preprocessor::SkipExcludedConditionalBlock(const Token ,
+void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashToken,
 SourceLocation IfTokenLoc,
  

[PATCH] D33765: Show correct column nr. when multi-byte utf8 chars are used.

2017-10-04 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv updated this revision to Diff 117660.
erikjv edited the summary of this revision.

https://reviews.llvm.org/D33765

Files:
  include/clang/Basic/SourceManager.h
  lib/Basic/SourceManager.cpp
  test/Misc/diag-utf8.cpp

Index: test/Misc/diag-utf8.cpp
===
--- /dev/null
+++ test/Misc/diag-utf8.cpp
@@ -0,0 +1,10 @@
+// RUN: not %clang_cc1 -fsyntax-only %s 2>&1 | FileCheck %s
+
+struct Foo { int member; };
+
+void f(Foo foo)
+{
+"ideeen" << foo; // CHECK: {{.*[/\\]}}diag-utf8.cpp:7:14: error: invalid operands to binary expression ('const char *' and 'Foo')
+"ideëen" << foo; // CHECK: {{.*[/\\]}}diag-utf8.cpp:8:14: error: invalid operands to binary expression ('const char *' and 'Foo')
+"idez̈en" << foo; // CHECK: {{.*[/\\]}}diag-utf8.cpp:9:14: error: invalid operands to binary expression ('const char *' and 'Foo')
+}
Index: lib/Basic/SourceManager.cpp
===
--- lib/Basic/SourceManager.cpp
+++ lib/Basic/SourceManager.cpp
@@ -1084,11 +1084,50 @@
   return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second);
 }
 
+static unsigned correctForMultiByteChars(const char *Buf, unsigned LineStart,
+ unsigned Column) {
+  auto isDiacriticMark = [Buf, LineStart, Column](unsigned I) -> bool {
+if (I + 1 >= Column)
+  return false;
+unsigned char FirstByte = static_cast(Buf[LineStart + I]);
+unsigned char SecondByte =
+static_cast(Buf[LineStart + I + 1]);
+if (FirstByte == 0xcc) {
+  return SecondByte >= 0x80;
+} else if (FirstByte == 0xcd) {
+  return SecondByte < 0xaf;
+}
+return false;
+  };
+
+  unsigned CorrectedColumn = Column;
+  unsigned char FirstByte;
+  for (unsigned I = 0; I < Column; ++I) {
+FirstByte = static_cast(Buf[LineStart + I]);
+if (FirstByte < 0xc0)
+  continue;
+if (isDiacriticMark(I)) {
+  CorrectedColumn -= 2;
+  ++I;
+} else if (FirstByte < 0xe0) {
+  --CorrectedColumn;
+  ++I;
+} else if (FirstByte < 0xf0) {
+  CorrectedColumn -= 2;
+  I += 2;
+} else {
+  CorrectedColumn -= 3;
+  I += 3;
+}
+  }
+  return CorrectedColumn;
+}
 
 /// getColumnNumber - Return the column # for the specified file position.
 /// this is significantly cheaper to compute than the line number.
 unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
-bool *Invalid) const {
+bool *Invalid,
+bool BytePosition) const {
   bool MyInvalid = false;
   llvm::MemoryBuffer *MemBuf = getBuffer(FID, );
   if (Invalid)
@@ -1122,14 +1161,18 @@
 if (Buf[FilePos - 1] == '\r' || Buf[FilePos - 1] == '\n')
   --FilePos;
   }
-  return FilePos - LineStart + 1;
+  unsigned Column = FilePos - LineStart + 1;
+  return BytePosition ? Column
+  : correctForMultiByteChars(Buf, LineStart, Column);
 }
   }
 
   unsigned LineStart = FilePos;
   while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
 --LineStart;
-  return FilePos-LineStart+1;
+  unsigned Column = FilePos - LineStart + 1;
+  return BytePosition ? Column
+  : correctForMultiByteChars(Buf, LineStart, Column);
 }
 
 // isInvalid - Return the result of calling loc.isInvalid(), and
@@ -1454,7 +1497,8 @@
   unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, );
   if (Invalid)
 return PresumedLoc();
-  unsigned ColNo  = getColumnNumber(LocInfo.first, LocInfo.second, );
+  unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, ,
+   /*BytePosition=*/false);
   if (Invalid)
 return PresumedLoc();
   
Index: include/clang/Basic/SourceManager.h
===
--- include/clang/Basic/SourceManager.h
+++ include/clang/Basic/SourceManager.h
@@ -1300,7 +1300,8 @@
   /// on a file sloc, so you must choose a spelling or expansion location
   /// before calling this method.
   unsigned getColumnNumber(FileID FID, unsigned FilePos,
-   bool *Invalid = nullptr) const;
+   bool *Invalid = nullptr,
+   bool BytePosition = true) const;
   unsigned getSpellingColumnNumber(SourceLocation Loc,
bool *Invalid = nullptr) const;
   unsigned getExpansionColumnNumber(SourceLocation Loc,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D37700: Fix recording preamble's conditional stack in skipped PP branches.

2017-09-12 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

I'd put/fix Nik's issue in a separate patch.


https://reviews.llvm.org/D37700



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D37491: [Preamble] Fixed preamble breaking with BOM presence (and particularly, fluctuating BOM presence)

2017-09-08 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

Will this fix PR25023 and PR21144?


https://reviews.llvm.org/D37491



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36821: [libclang]: Honor LIBCLANG_NOTHREADS for clang_parseTranslationUnit*

2017-08-29 Thread Erik Verbruggen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL311990: [libclang]: Honor LIBCLANG_NOTHREADS for 
clang_parseTranslationUnit* (authored by erikjv).

Changed prior to commit:
  https://reviews.llvm.org/D36821?vs=111472=113041#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D36821

Files:
  cfe/trunk/tools/libclang/CIndex.cpp


Index: cfe/trunk/tools/libclang/CIndex.cpp
===
--- cfe/trunk/tools/libclang/CIndex.cpp
+++ cfe/trunk/tools/libclang/CIndex.cpp
@@ -3504,6 +3504,12 @@
 CIdx, source_filename, command_line_args, num_command_line_args,
 llvm::makeArrayRef(unsaved_files, num_unsaved_files), options, out_TU);
   };
+
+  if (getenv("LIBCLANG_NOTHREADS")) {
+ParseTranslationUnitImpl();
+return result;
+  }
+
   llvm::CrashRecoveryContext CRC;
 
   if (!RunSafely(CRC, ParseTranslationUnitImpl)) {


Index: cfe/trunk/tools/libclang/CIndex.cpp
===
--- cfe/trunk/tools/libclang/CIndex.cpp
+++ cfe/trunk/tools/libclang/CIndex.cpp
@@ -3504,6 +3504,12 @@
 CIdx, source_filename, command_line_args, num_command_line_args,
 llvm::makeArrayRef(unsaved_files, num_unsaved_files), options, out_TU);
   };
+
+  if (getenv("LIBCLANG_NOTHREADS")) {
+ParseTranslationUnitImpl();
+return result;
+  }
+
   llvm::CrashRecoveryContext CRC;
 
   if (!RunSafely(CRC, ParseTranslationUnitImpl)) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D35355: Fix templated type alias completion when using global completion cache

2017-08-22 Thread Erik Verbruggen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL311442: Fix templated type alias completion when using 
global completion cache (authored by erikjv).

Changed prior to commit:
  https://reviews.llvm.org/D35355?vs=109968=112144#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D35355

Files:
  cfe/trunk/lib/Frontend/ASTUnit.cpp
  cfe/trunk/lib/Parse/ParseTemplate.cpp
  cfe/trunk/test/Index/code-completion.cpp


Index: cfe/trunk/test/Index/code-completion.cpp
===
--- cfe/trunk/test/Index/code-completion.cpp
+++ cfe/trunk/test/Index/code-completion.cpp
@@ -37,6 +37,16 @@
   return 0;
 }
 
+template 
+struct Foo { T member; };
+
+template using Bar = Foo;
+
+void test_template_alias() {
+  // RUN: env CINDEXTEST_COMPLETION_CACHING=1 c-index-test 
-code-completion-at=%s:47:1 %s | FileCheck -check-prefix=CHECK-TEMPLATE-ALIAS %s
+
+}
+
 // CHECK-MEMBER: FieldDecl:{ResultType double}{TypedText member}
 // CHECK-MEMBER: FieldDecl:{ResultType int}{Text X::}{TypedText member}
 // CHECK-MEMBER: FieldDecl:{ResultType float}{Text Y::}{TypedText member}
@@ -88,3 +98,5 @@
 // CHECK-EXPR-NEXT: Class name
 // CHECK-EXPR-NEXT: Nested name specifier
 // CHECK-EXPR-NEXT: Objective-C interface
+
+// CHECK-TEMPLATE-ALIAS: AliasTemplateDecl:{TypedText Bar}{LeftAngle 
<}{Placeholder typename T}{RightAngle >} (50)
Index: cfe/trunk/lib/Frontend/ASTUnit.cpp
===
--- cfe/trunk/lib/Frontend/ASTUnit.cpp
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp
@@ -243,7 +243,8 @@
   
   uint64_t Contexts = 0;
   if (isa(ND) || isa(ND) || 
-  isa(ND) || isa(ND)) {
+  isa(ND) || isa(ND) ||
+  isa(ND)) {
 // Types can appear in these contexts.
 if (LangOpts.CPlusPlus || !isa(ND))
   Contexts |= (1LL << CodeCompletionContext::CCC_TopLevel)
Index: cfe/trunk/lib/Parse/ParseTemplate.cpp
===
--- cfe/trunk/lib/Parse/ParseTemplate.cpp
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp
@@ -198,9 +198,11 @@
 
   if (Tok.is(tok::kw_using)) {
 // FIXME: We should return the DeclGroup to the caller.
-ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
- prefixAttrs);
-return nullptr;
+auto usingDeclPtr = ParseUsingDirectiveOrDeclaration(Context, 
TemplateInfo, DeclEnd,
+ prefixAttrs);
+if (!usingDeclPtr)
+  return nullptr;
+return usingDeclPtr.get().getSingleDecl();
   }
 
   // Parse the declaration specifiers, stealing any diagnostics from
@@ -1023,8 +1025,8 @@
 ? OO_None
 : TemplateName.OperatorFunctionId.Operator;
 
-TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
-  SS, TemplateKWLoc, TemplateNameLoc, TemplateII, OpKind, Template, TNK,
+TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
+  SS, TemplateKWLoc, TemplateNameLoc, TemplateII, OpKind, Template, TNK,
   LAngleLoc, RAngleLoc, TemplateArgs, TemplateIds);
 
 Tok.setAnnotationValue(TemplateId);


Index: cfe/trunk/test/Index/code-completion.cpp
===
--- cfe/trunk/test/Index/code-completion.cpp
+++ cfe/trunk/test/Index/code-completion.cpp
@@ -37,6 +37,16 @@
   return 0;
 }
 
+template 
+struct Foo { T member; };
+
+template using Bar = Foo;
+
+void test_template_alias() {
+  // RUN: env CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:47:1 %s | FileCheck -check-prefix=CHECK-TEMPLATE-ALIAS %s
+
+}
+
 // CHECK-MEMBER: FieldDecl:{ResultType double}{TypedText member}
 // CHECK-MEMBER: FieldDecl:{ResultType int}{Text X::}{TypedText member}
 // CHECK-MEMBER: FieldDecl:{ResultType float}{Text Y::}{TypedText member}
@@ -88,3 +98,5 @@
 // CHECK-EXPR-NEXT: Class name
 // CHECK-EXPR-NEXT: Nested name specifier
 // CHECK-EXPR-NEXT: Objective-C interface
+
+// CHECK-TEMPLATE-ALIAS: AliasTemplateDecl:{TypedText Bar}{LeftAngle <}{Placeholder typename T}{RightAngle >} (50)
Index: cfe/trunk/lib/Frontend/ASTUnit.cpp
===
--- cfe/trunk/lib/Frontend/ASTUnit.cpp
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp
@@ -243,7 +243,8 @@
   
   uint64_t Contexts = 0;
   if (isa(ND) || isa(ND) || 
-  isa(ND) || isa(ND)) {
+  isa(ND) || isa(ND) ||
+  isa(ND)) {
 // Types can appear in these contexts.
 if (LangOpts.CPlusPlus || !isa(ND))
   Contexts |= (1LL << CodeCompletionContext::CCC_TopLevel)
Index: cfe/trunk/lib/Parse/ParseTemplate.cpp
===
--- cfe/trunk/lib/Parse/ParseTemplate.cpp
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp
@@ -198,9 +198,11 @@
 
   if (Tok.is(tok::kw_using)) {
 // FIXME: We should return the DeclGroup to the caller.
-

[PATCH] D35355: Fix templated type alias completion when using global completion cache

2017-08-18 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

I'll commit it, probably next Tuesday.


https://reviews.llvm.org/D35355



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36872: Fixed a crash on replaying Preamble's PP conditional stack.

2017-08-18 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

Can you check if the example in https://bugs.llvm.org/show_bug.cgi?id=33574 
works correctly?




Comment at: include/clang/Lex/Preprocessor.h:2029
+
 private:
   // Macro handling.

Duplicate "private:"


https://reviews.llvm.org/D36872



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33644: Add default values for function parameter chunks

2017-07-19 Thread Erik Verbruggen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL308433: Add default values for function parameter chunks 
(authored by erikjv).

Changed prior to commit:
  https://reviews.llvm.org/D33644?vs=107077=107276#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D33644

Files:
  cfe/trunk/lib/Sema/SemaCodeComplete.cpp
  cfe/trunk/test/CodeCompletion/functions.cpp
  cfe/trunk/test/Index/code-completion.cpp
  cfe/trunk/test/Index/complete-optional-params.cpp

Index: cfe/trunk/test/Index/code-completion.cpp
===
--- cfe/trunk/test/Index/code-completion.cpp
+++ cfe/trunk/test/Index/code-completion.cpp
@@ -40,7 +40,7 @@
 // CHECK-MEMBER: FieldDecl:{ResultType double}{TypedText member}
 // CHECK-MEMBER: FieldDecl:{ResultType int}{Text X::}{TypedText member}
 // CHECK-MEMBER: FieldDecl:{ResultType float}{Text Y::}{TypedText member}
-// CHECK-MEMBER: CXXMethod:{ResultType void}{Informative Y::}{TypedText memfunc}{LeftParen (}{Optional {Placeholder int i}}{RightParen )}
+// CHECK-MEMBER: CXXMethod:{ResultType void}{Informative Y::}{TypedText memfunc}{LeftParen (}{Optional {Placeholder int i = 17}}{RightParen )}
 // CHECK-MEMBER: CXXConversion:{TypedText operator int}{LeftParen (}{RightParen )}{Informative  const}
 // CHECK-MEMBER: CXXMethod:{ResultType Z &}{TypedText operator=}{LeftParen (}{Placeholder const Z &}{RightParen )}
 // CHECK-MEMBER: CXXMethod:{ResultType X &}{Text X::}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )}
@@ -77,7 +77,7 @@
 // CHECK-EXPR: FieldDecl:{ResultType double}{TypedText member} (17)
 // CHECK-EXPR: FieldDecl:{ResultType int}{Text X::}{TypedText member} (9)
 // CHECK-EXPR: FieldDecl:{ResultType float}{Text Y::}{TypedText member} (18)
-// CHECK-EXPR: CXXMethod:{ResultType void}{TypedText memfunc}{LeftParen (}{Optional {Placeholder int i}}{RightParen )} (37)
+// CHECK-EXPR: CXXMethod:{ResultType void}{TypedText memfunc}{LeftParen (}{Optional {Placeholder int i = 17}}{RightParen )} (37)
 // CHECK-EXPR: Namespace:{TypedText N}{Text ::} (75)
 // CHECK-EXPR: Completion contexts:
 // CHECK-EXPR-NEXT: Any type
Index: cfe/trunk/test/Index/complete-optional-params.cpp
===
--- cfe/trunk/test/Index/complete-optional-params.cpp
+++ cfe/trunk/test/Index/complete-optional-params.cpp
@@ -6,15 +6,19 @@
 void baz(int a = 42, ...);
 struct S{ S(int a = 42, int = 42) {} };
 
+class Bar1 { public: Bar1() {} }; class Bar2;
+void foo_2(Bar1 b1 = Bar1(), Bar2 b2 = Bar2());
+
 int main() {
 foo(42, 42);
 bar(42, 42, 42);
 baz(42, 42, 42);
 S s(42, 42);
+foo_2();
 }
 
-// RUN: c-index-test -code-completion-at=%s:10:9 %s | FileCheck -check-prefix=CHECK-CC1 %s
-// CHECK-CC1: OverloadCandidate:{ResultType void}{Text foo}{LeftParen (}{Optional {CurrentParameter int a}{Optional {Comma , }{Placeholder int}}}{RightParen )} (1)
+// RUN: c-index-test -code-completion-at=%s:13:9 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: OverloadCandidate:{ResultType void}{Text foo}{LeftParen (}{Optional {CurrentParameter int a = 42}{Optional {Comma , }{Placeholder int = 42}}}{RightParen )} (1)
 // CHECK-CC1: Completion contexts:
 // CHECK-CC1-NEXT: Any type
 // CHECK-CC1-NEXT: Any value
@@ -25,8 +29,8 @@
 // CHECK-CC1-NEXT: Nested name specifier
 // CHECK-CC1-NEXT: Objective-C interface
 
-// RUN: c-index-test -code-completion-at=%s:11:9 %s | FileCheck -check-prefix=CHECK-CC2 %s
-// CHECK-CC2: OverloadCandidate:{ResultType void}{Text bar}{LeftParen (}{CurrentParameter int a}{Optional {Comma , }{Placeholder int b}{Optional {Comma , }{Placeholder int c}}}{RightParen )} (1)
+// RUN: c-index-test -code-completion-at=%s:14:9 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: OverloadCandidate:{ResultType void}{Text bar}{LeftParen (}{CurrentParameter int a}{Optional {Comma , }{Placeholder int b = 42}{Optional {Comma , }{Placeholder int c = 42}}}{RightParen )} (1)
 // CHECK-CC2: Completion contexts:
 // CHECK-CC2-NEXT: Any type
 // CHECK-CC2-NEXT: Any value
@@ -37,8 +41,8 @@
 // CHECK-CC2-NEXT: Nested name specifier
 // CHECK-CC2-NEXT: Objective-C interface
 
-// RUN: c-index-test -code-completion-at=%s:11:16 %s | FileCheck -check-prefix=CHECK-CC3 %s
-// CHECK-CC3: OverloadCandidate:{ResultType void}{Text bar}{LeftParen (}{Placeholder int a}{Optional {Comma , }{Placeholder int b}{Optional {Comma , }{CurrentParameter int c}}}{RightParen )} (1)
+// RUN: c-index-test -code-completion-at=%s:14:16 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: OverloadCandidate:{ResultType void}{Text bar}{LeftParen (}{Placeholder int a}{Optional {Comma , }{Placeholder int b = 42}{Optional {Comma , }{CurrentParameter int c = 42}}}{RightParen )} (1)
 // CHECK-CC3: Completion contexts:
 // CHECK-CC3-NEXT: Any type
 // CHECK-CC3-NEXT: Any value
@@ -49,8 +53,8 @@
 // CHECK-CC3-NEXT: Nested name specifier
 // CHECK-CC3-NEXT: 

[PATCH] D35186: [analyzer] Add annotation for functions taking user-facing strings

2017-07-14 Thread Erik Verbruggen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL308012: [analyzer] Add annotation for functions taking 
user-facing strings (authored by erikjv).

Changed prior to commit:
  https://reviews.llvm.org/D35186?vs=105792=106605#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D35186

Files:
  cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
  cfe/trunk/test/Analysis/localization-aggressive.m

Index: cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
===
--- cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
@@ -57,7 +57,7 @@
 };
 
 class NonLocalizedStringChecker
-: public Checker {
 
@@ -79,9 +79,10 @@
   void setNonLocalizedState(SVal S, CheckerContext ) const;
   void setLocalizedState(SVal S, CheckerContext ) const;
 
-  bool isAnnotatedAsLocalized(const Decl *D) const;
-  void reportLocalizationError(SVal S, const ObjCMethodCall ,
-   CheckerContext , int argumentNumber = 0) const;
+  bool isAnnotatedAsReturningLocalized(const Decl *D) const;
+  bool isAnnotatedAsTakingLocalized(const Decl *D) const;
+  void reportLocalizationError(SVal S, const CallEvent , CheckerContext ,
+   int argumentNumber = 0) const;
 
   int getLocalizedArgumentForSelector(const IdentifierInfo *Receiver,
   Selector S) const;
@@ -97,6 +98,7 @@
   void checkPreObjCMessage(const ObjCMethodCall , CheckerContext ) const;
   void checkPostObjCMessage(const ObjCMethodCall , CheckerContext ) const;
   void checkPostStmt(const ObjCStringLiteral *SL, CheckerContext ) const;
+  void checkPreCall(const CallEvent , CheckerContext ) const;
   void checkPostCall(const CallEvent , CheckerContext ) const;
 };
 
@@ -644,7 +646,8 @@
 
 /// Checks to see if the method / function declaration includes
 /// __attribute__((annotate("returns_localized_nsstring")))
-bool NonLocalizedStringChecker::isAnnotatedAsLocalized(const Decl *D) const {
+bool NonLocalizedStringChecker::isAnnotatedAsReturningLocalized(
+const Decl *D) const {
   if (!D)
 return false;
   return std::any_of(
@@ -654,6 +657,19 @@
   });
 }
 
+/// Checks to see if the method / function declaration includes
+/// __attribute__((annotate("takes_localized_nsstring")))
+bool NonLocalizedStringChecker::isAnnotatedAsTakingLocalized(
+const Decl *D) const {
+  if (!D)
+return false;
+  return std::any_of(
+  D->specific_attr_begin(),
+  D->specific_attr_end(), [](const AnnotateAttr *Ann) {
+return Ann->getAnnotation() == "takes_localized_nsstring";
+  });
+}
+
 /// Returns true if the given SVal is marked as Localized in the program state
 bool NonLocalizedStringChecker::hasLocalizedState(SVal S,
   CheckerContext ) const {
@@ -733,8 +749,7 @@
 
 /// Reports a localization error for the passed in method call and SVal
 void NonLocalizedStringChecker::reportLocalizationError(
-SVal S, const ObjCMethodCall , CheckerContext ,
-int argumentNumber) const {
+SVal S, const CallEvent , CheckerContext , int argumentNumber) const {
 
   // Don't warn about localization errors in classes and methods that
   // may be debug code.
@@ -832,7 +847,21 @@
 }
   }
 
-  if (argumentNumber < 0) // There was no match in UIMethods
+  if (argumentNumber < 0) { // There was no match in UIMethods
+if (const Decl *D = msg.getDecl()) {
+  if (const ObjCMethodDecl *OMD = dyn_cast_or_null(D)) {
+auto formals = OMD->parameters();
+for (unsigned i = 0, ei = formals.size(); i != ei; ++i) {
+  if (isAnnotatedAsTakingLocalized(formals[i])) {
+argumentNumber = i;
+break;
+  }
+}
+  }
+}
+  }
+
+  if (argumentNumber < 0) // Still no match
 return;
 
   SVal svTitle = msg.getArgSVal(argumentNumber);
@@ -855,6 +884,25 @@
   }
 }
 
+void NonLocalizedStringChecker::checkPreCall(const CallEvent ,
+ CheckerContext ) const {
+  const Decl *D = Call.getDecl();
+  if (D && isa(D)) {
+const FunctionDecl *FD = dyn_cast(D);
+auto formals = FD->parameters();
+for (unsigned i = 0,
+  ei = std::min(unsigned(formals.size()), Call.getNumArgs());
+ i != ei; ++i) {
+  if (isAnnotatedAsTakingLocalized(formals[i])) {
+auto actual = Call.getArgSVal(i);
+if (hasNonLocalizedState(actual, C)) {
+  reportLocalizationError(actual, Call, C, i + 1);
+}
+  }
+}
+  }
+}
+
 static inline bool isNSStringType(QualType T, ASTContext ) {
 
   const 

[PATCH] D35186: [analyzer] Add annotation for functions taking user-facing strings

2017-07-09 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv updated this revision to Diff 105792.
erikjv added a comment.

Sorry, now with more context in the diff.


https://reviews.llvm.org/D35186

Files:
  lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
  test/Analysis/localization-aggressive.m

Index: test/Analysis/localization-aggressive.m
===
--- test/Analysis/localization-aggressive.m
+++ test/Analysis/localization-aggressive.m
@@ -61,8 +61,16 @@
 NSString *CFNumberFormatterCreateStringWithNumber(float x);
 + (NSString *)forceLocalized:(NSString *)str
 __attribute__((annotate("returns_localized_nsstring")));
++ (NSString *)takesLocalizedString:
+(NSString *)__attribute__((annotate("takes_localized_nsstring")))str;
 @end
 
+NSString *
+takesLocalizedString(NSString *str
+ __attribute__((annotate("takes_localized_nsstring" {
+  return str;
+}
+
 // Test cases begin here
 @implementation LocalizationTestSuite
 
@@ -75,6 +83,8 @@
   return str;
 }
 
++ (NSString *) takesLocalizedString:(NSString *)str { return str; }
+
 // An ObjC method that returns a localized string
 + (NSString *)unLocalizedStringMethod {
   return @"UnlocalizedString";
@@ -269,4 +279,13 @@
   NSString *string2 = POSSIBLE_FALSE_POSITIVE(@"Hello", @"Hello"); // no-warning
 }
 
+- (void)testTakesLocalizedString {
+  NSString *localized = NSLocalizedString(@"Hello", @"World");
+  NSString *alsoLocalized = [LocalizationTestSuite takesLocalizedString:localized]; // no-warning
+  NSString *stillLocalized = [LocalizationTestSuite takesLocalizedString:alsoLocalized]; // no-warning
+  takesLocalizedString(stillLocalized); // no-warning
+
+  [LocalizationTestSuite takesLocalizedString:@"not localized"]; // expected-warning {{User-facing text should use localized string macro}}
+  takesLocalizedString(@"not localized"); // expected-warning {{User-facing text should use localized string macro}}
+}
 @end
Index: lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
+++ lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
@@ -57,7 +57,7 @@
 };
 
 class NonLocalizedStringChecker
-: public Checker {
 
@@ -80,8 +80,9 @@
   void setLocalizedState(SVal S, CheckerContext ) const;
 
   bool isAnnotatedAsLocalized(const Decl *D) const;
-  void reportLocalizationError(SVal S, const ObjCMethodCall ,
-   CheckerContext , int argumentNumber = 0) const;
+  bool isAnnotatedTakingLocalized(const Decl *D) const;
+  void reportLocalizationError(SVal S, const CallEvent , CheckerContext ,
+   int argumentNumber = 0) const;
 
   int getLocalizedArgumentForSelector(const IdentifierInfo *Receiver,
   Selector S) const;
@@ -97,6 +98,7 @@
   void checkPreObjCMessage(const ObjCMethodCall , CheckerContext ) const;
   void checkPostObjCMessage(const ObjCMethodCall , CheckerContext ) const;
   void checkPostStmt(const ObjCStringLiteral *SL, CheckerContext ) const;
+  void checkPreCall(const CallEvent , CheckerContext ) const;
   void checkPostCall(const CallEvent , CheckerContext ) const;
 };
 
@@ -654,6 +656,18 @@
   });
 }
 
+/// Checks to see if the method / function declaration includes
+/// __attribute__((annotate("takes_localized_nsstring")))
+bool NonLocalizedStringChecker::isAnnotatedTakingLocalized(const Decl *D) const {
+  if (!D)
+return false;
+  return std::any_of(
+  D->specific_attr_begin(),
+  D->specific_attr_end(), [](const AnnotateAttr *Ann) {
+return Ann->getAnnotation() == "takes_localized_nsstring";
+  });
+}
+
 /// Returns true if the given SVal is marked as Localized in the program state
 bool NonLocalizedStringChecker::hasLocalizedState(SVal S,
   CheckerContext ) const {
@@ -733,8 +747,7 @@
 
 /// Reports a localization error for the passed in method call and SVal
 void NonLocalizedStringChecker::reportLocalizationError(
-SVal S, const ObjCMethodCall , CheckerContext ,
-int argumentNumber) const {
+SVal S, const CallEvent , CheckerContext , int argumentNumber) const {
 
   // Don't warn about localization errors in classes and methods that
   // may be debug code.
@@ -832,7 +845,21 @@
 }
   }
 
-  if (argumentNumber < 0) // There was no match in UIMethods
+  if (argumentNumber < 0) { // There was no match in UIMethods
+if (const Decl *D = msg.getDecl()) {
+  if (const ObjCMethodDecl *OMD = dyn_cast_or_null(D)) {
+auto formals = OMD->parameters();
+for (unsigned i = 0, ei = formals.size(); i != ei; ++i) {
+  if (isAnnotatedTakingLocalized(formals[i])) {
+

[PATCH] D35186: [analyzer] Add annotation for functions taking user-facing strings

2017-07-09 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv created this revision.
Herald added a subscriber: xazax.hun.

There was already a returns_localized_nsstring annotation to indicate
that the return value could be passed to UIKit methods that would
display them. However, those UIKit methods were hard-coded, and it was
not possible to indicate that other classes/methods in a code-base would
do the same.

The takes_localized_nsstring annotation can be put on function
parameters and selector parameters to indicate that those will also show
the string to the user.


https://reviews.llvm.org/D35186

Files:
  lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
  test/Analysis/localization-aggressive.m

Index: test/Analysis/localization-aggressive.m
===
--- test/Analysis/localization-aggressive.m
+++ test/Analysis/localization-aggressive.m
@@ -61,8 +61,16 @@
 NSString *CFNumberFormatterCreateStringWithNumber(float x);
 + (NSString *)forceLocalized:(NSString *)str
 __attribute__((annotate("returns_localized_nsstring")));
++ (NSString *)takesLocalizedString:
+(NSString *)__attribute__((annotate("takes_localized_nsstring")))str;
 @end
 
+NSString *
+takesLocalizedString(NSString *str
+ __attribute__((annotate("takes_localized_nsstring" {
+  return str;
+}
+
 // Test cases begin here
 @implementation LocalizationTestSuite
 
@@ -75,6 +83,8 @@
   return str;
 }
 
++ (NSString *) takesLocalizedString:(NSString *)str { return str; }
+
 // An ObjC method that returns a localized string
 + (NSString *)unLocalizedStringMethod {
   return @"UnlocalizedString";
@@ -269,4 +279,13 @@
   NSString *string2 = POSSIBLE_FALSE_POSITIVE(@"Hello", @"Hello"); // no-warning
 }
 
+- (void)testTakesLocalizedString {
+  NSString *localized = NSLocalizedString(@"Hello", @"World");
+  NSString *alsoLocalized = [LocalizationTestSuite takesLocalizedString:localized]; // no-warning
+  NSString *stillLocalized = [LocalizationTestSuite takesLocalizedString:alsoLocalized]; // no-warning
+  takesLocalizedString(stillLocalized); // no-warning
+
+  [LocalizationTestSuite takesLocalizedString:@"not localized"]; // expected-warning {{User-facing text should use localized string macro}}
+  takesLocalizedString(@"not localized"); // expected-warning {{User-facing text should use localized string macro}}
+}
 @end
Index: lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
+++ lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
@@ -57,7 +57,7 @@
 };
 
 class NonLocalizedStringChecker
-: public Checker {
 
@@ -80,8 +80,9 @@
   void setLocalizedState(SVal S, CheckerContext ) const;
 
   bool isAnnotatedAsLocalized(const Decl *D) const;
-  void reportLocalizationError(SVal S, const ObjCMethodCall ,
-   CheckerContext , int argumentNumber = 0) const;
+  bool isAnnotatedTakingLocalized(const Decl *D) const;
+  void reportLocalizationError(SVal S, const CallEvent , CheckerContext ,
+   int argumentNumber = 0) const;
 
   int getLocalizedArgumentForSelector(const IdentifierInfo *Receiver,
   Selector S) const;
@@ -97,6 +98,7 @@
   void checkPreObjCMessage(const ObjCMethodCall , CheckerContext ) const;
   void checkPostObjCMessage(const ObjCMethodCall , CheckerContext ) const;
   void checkPostStmt(const ObjCStringLiteral *SL, CheckerContext ) const;
+  void checkPreCall(const CallEvent , CheckerContext ) const;
   void checkPostCall(const CallEvent , CheckerContext ) const;
 };
 
@@ -654,6 +656,18 @@
   });
 }
 
+/// Checks to see if the method / function declaration includes
+/// __attribute__((annotate("takes_localized_nsstring")))
+bool NonLocalizedStringChecker::isAnnotatedTakingLocalized(const Decl *D) const {
+  if (!D)
+return false;
+  return std::any_of(
+  D->specific_attr_begin(),
+  D->specific_attr_end(), [](const AnnotateAttr *Ann) {
+return Ann->getAnnotation() == "takes_localized_nsstring";
+  });
+}
+
 /// Returns true if the given SVal is marked as Localized in the program state
 bool NonLocalizedStringChecker::hasLocalizedState(SVal S,
   CheckerContext ) const {
@@ -733,8 +747,7 @@
 
 /// Reports a localization error for the passed in method call and SVal
 void NonLocalizedStringChecker::reportLocalizationError(
-SVal S, const ObjCMethodCall , CheckerContext ,
-int argumentNumber) const {
+SVal S, const CallEvent , CheckerContext , int argumentNumber) const {
 
   // Don't warn about localization errors in classes and methods that
   // may be debug code.
@@ -832,7 +845,21 @@
 }
   }
 
-  

[PATCH] D33493: Speed up preamble loading

2017-06-09 Thread Erik Verbruggen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL305061: Speed up preamble loading (authored by erikjv).

Changed prior to commit:
  https://reviews.llvm.org/D33493?vs=101995=102003#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D33493

Files:
  cfe/trunk/include/clang/Frontend/ASTUnit.h
  cfe/trunk/lib/Frontend/ASTUnit.cpp


Index: cfe/trunk/lib/Frontend/ASTUnit.cpp
===
--- cfe/trunk/lib/Frontend/ASTUnit.cpp
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp
@@ -1159,6 +1159,8 @@
   if (SavedMainFileBuffer)
 TranslateStoredDiagnostics(getFileManager(), getSourceManager(),
PreambleDiagnostics, StoredDiagnostics);
+  else
+PreambleSrcLocCache.clear();
 
   if (!Act->Execute())
 goto error;
@@ -2602,23 +2604,26 @@
   // remap all the locations to the new view. This includes the diag location,
   // any associated source ranges, and the source ranges of associated fix-its.
   // FIXME: There should be a cleaner way to do this.
-
   SmallVector Result;
   Result.reserve(Diags.size());
-  const FileEntry *PreviousFE = nullptr;
-  FileID FID;
+
   for (const StandaloneDiagnostic  : Diags) {
 // Rebuild the StoredDiagnostic.
 if (SD.Filename.empty())
   continue;
 const FileEntry *FE = FileMgr.getFile(SD.Filename);
 if (!FE)
   continue;
-if (FE != PreviousFE) {
-  FID = SrcMgr.translateFile(FE);
-  PreviousFE = FE;
+SourceLocation FileLoc;
+auto ItFileID = PreambleSrcLocCache.find(SD.Filename);
+if (ItFileID == PreambleSrcLocCache.end()) {
+  FileID FID = SrcMgr.translateFile(FE);
+  FileLoc = SrcMgr.getLocForStartOfFile(FID);
+  PreambleSrcLocCache[SD.Filename] = FileLoc;
+} else {
+  FileLoc = ItFileID->getValue();
 }
-SourceLocation FileLoc = SrcMgr.getLocForStartOfFile(FID);
+
 if (FileLoc.isInvalid())
   continue;
 SourceLocation L = FileLoc.getLocWithOffset(SD.LocOffset);
Index: cfe/trunk/include/clang/Frontend/ASTUnit.h
===
--- cfe/trunk/include/clang/Frontend/ASTUnit.h
+++ cfe/trunk/include/clang/Frontend/ASTUnit.h
@@ -188,6 +188,14 @@
   /// some number of calls.
   unsigned PreambleRebuildCounter;
 
+  /// \brief Cache pairs "filename - source location"
+  ///
+  /// Cache contains only source locations from preamble so it is
+  /// guaranteed that they stay valid when the SourceManager is recreated.
+  /// This cache is used when loading preambule to increase performance
+  /// of that loading. It must be cleared when preamble is recreated.
+  llvm::StringMap PreambleSrcLocCache;
+
 public:
   class PreambleData {
 const FileEntry *File;


Index: cfe/trunk/lib/Frontend/ASTUnit.cpp
===
--- cfe/trunk/lib/Frontend/ASTUnit.cpp
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp
@@ -1159,6 +1159,8 @@
   if (SavedMainFileBuffer)
 TranslateStoredDiagnostics(getFileManager(), getSourceManager(),
PreambleDiagnostics, StoredDiagnostics);
+  else
+PreambleSrcLocCache.clear();
 
   if (!Act->Execute())
 goto error;
@@ -2602,23 +2604,26 @@
   // remap all the locations to the new view. This includes the diag location,
   // any associated source ranges, and the source ranges of associated fix-its.
   // FIXME: There should be a cleaner way to do this.
-
   SmallVector Result;
   Result.reserve(Diags.size());
-  const FileEntry *PreviousFE = nullptr;
-  FileID FID;
+
   for (const StandaloneDiagnostic  : Diags) {
 // Rebuild the StoredDiagnostic.
 if (SD.Filename.empty())
   continue;
 const FileEntry *FE = FileMgr.getFile(SD.Filename);
 if (!FE)
   continue;
-if (FE != PreviousFE) {
-  FID = SrcMgr.translateFile(FE);
-  PreviousFE = FE;
+SourceLocation FileLoc;
+auto ItFileID = PreambleSrcLocCache.find(SD.Filename);
+if (ItFileID == PreambleSrcLocCache.end()) {
+  FileID FID = SrcMgr.translateFile(FE);
+  FileLoc = SrcMgr.getLocForStartOfFile(FID);
+  PreambleSrcLocCache[SD.Filename] = FileLoc;
+} else {
+  FileLoc = ItFileID->getValue();
 }
-SourceLocation FileLoc = SrcMgr.getLocForStartOfFile(FID);
+
 if (FileLoc.isInvalid())
   continue;
 SourceLocation L = FileLoc.getLocWithOffset(SD.LocOffset);
Index: cfe/trunk/include/clang/Frontend/ASTUnit.h
===
--- cfe/trunk/include/clang/Frontend/ASTUnit.h
+++ cfe/trunk/include/clang/Frontend/ASTUnit.h
@@ -188,6 +188,14 @@
   /// some number of calls.
   unsigned PreambleRebuildCounter;
 
+  /// \brief Cache pairs "filename - source location"
+  ///
+  /// Cache contains only source locations from preamble so it is
+  /// guaranteed that they stay valid when the SourceManager is recreated.
+ 

[PATCH] D33765: Show correct column nr. when multi-byte utf8 chars are used.

2017-06-01 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv created this revision.

Previously, the column number in a diagnostic would be the byte position
in the line. This results in incorrect column numbers when a multi-byte
UTF-8 character would be present in the input. By ignoring all bytes
starting with 0b10 the correct column number is created.

This fixes PR21144.


https://reviews.llvm.org/D33765

Files:
  include/clang/Basic/SourceManager.h
  lib/Basic/SourceManager.cpp
  test/Misc/diag-utf8.cpp


Index: test/Misc/diag-utf8.cpp
===
--- /dev/null
+++ test/Misc/diag-utf8.cpp
@@ -0,0 +1,11 @@
+// RUN: not %clang_cc1 -fsyntax-only %s 2>&1 | FileCheck %s
+
+struct Foo { int member; };
+
+void f(Foo foo)
+{
+"ideeen" << foo; // CHECK: {{.*[/\\]}}diag-utf8.cpp:7:14: error: invalid 
operands to binary expression ('const char *' and 'Foo')
+"ideëen" << foo; // CHECK: {{.*[/\\]}}diag-utf8.cpp:8:14: error: invalid 
operands to binary expression ('const char *' and 'Foo')
+}
+
+
Index: lib/Basic/SourceManager.cpp
===
--- lib/Basic/SourceManager.cpp
+++ lib/Basic/SourceManager.cpp
@@ -1055,11 +1055,22 @@
   return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second);
 }
 
+static unsigned correctForMultiByteChars(const char *Buf, unsigned LineStart,
+ unsigned Column)
+{
+unsigned CorrectedColumn = Column;
+for (unsigned I = 0; I < Column; ++I) {
+if ((Buf[LineStart + I] & 0xc0) == 0x80)
+--CorrectedColumn;
+}
+return CorrectedColumn;
+}
 
 /// getColumnNumber - Return the column # for the specified file position.
 /// this is significantly cheaper to compute than the line number.
 unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
-bool *Invalid) const {
+bool *Invalid,
+bool BytePosition) const {
   bool MyInvalid = false;
   llvm::MemoryBuffer *MemBuf = getBuffer(FID, );
   if (Invalid)
@@ -1093,14 +1104,18 @@
 if (Buf[FilePos - 1] == '\r' || Buf[FilePos - 1] == '\n')
   --FilePos;
   }
-  return FilePos - LineStart + 1;
+  unsigned Column = FilePos - LineStart + 1;
+  return BytePosition ? Column : correctForMultiByteChars(Buf, LineStart,
+  Column);
 }
   }
 
   unsigned LineStart = FilePos;
   while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
 --LineStart;
-  return FilePos-LineStart+1;
+  unsigned Column = FilePos - LineStart + 1;
+  return BytePosition ? Column : correctForMultiByteChars(Buf, LineStart,
+  Column);
 }
 
 // isInvalid - Return the result of calling loc.isInvalid(), and
@@ -1425,7 +1440,8 @@
   unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, );
   if (Invalid)
 return PresumedLoc();
-  unsigned ColNo  = getColumnNumber(LocInfo.first, LocInfo.second, );
+  unsigned ColNo  = getColumnNumber(LocInfo.first, LocInfo.second, ,
+false);
   if (Invalid)
 return PresumedLoc();
   
Index: include/clang/Basic/SourceManager.h
===
--- include/clang/Basic/SourceManager.h
+++ include/clang/Basic/SourceManager.h
@@ -1275,7 +1275,8 @@
   /// on a file sloc, so you must choose a spelling or expansion location
   /// before calling this method.
   unsigned getColumnNumber(FileID FID, unsigned FilePos,
-   bool *Invalid = nullptr) const;
+   bool *Invalid = nullptr,
+   bool BytePosition = true) const;
   unsigned getSpellingColumnNumber(SourceLocation Loc,
bool *Invalid = nullptr) const;
   unsigned getExpansionColumnNumber(SourceLocation Loc,


Index: test/Misc/diag-utf8.cpp
===
--- /dev/null
+++ test/Misc/diag-utf8.cpp
@@ -0,0 +1,11 @@
+// RUN: not %clang_cc1 -fsyntax-only %s 2>&1 | FileCheck %s
+
+struct Foo { int member; };
+
+void f(Foo foo)
+{
+"ideeen" << foo; // CHECK: {{.*[/\\]}}diag-utf8.cpp:7:14: error: invalid operands to binary expression ('const char *' and 'Foo')
+"ideëen" << foo; // CHECK: {{.*[/\\]}}diag-utf8.cpp:8:14: error: invalid operands to binary expression ('const char *' and 'Foo')
+}
+
+
Index: lib/Basic/SourceManager.cpp
===
--- lib/Basic/SourceManager.cpp
+++ lib/Basic/SourceManager.cpp
@@ -1055,11 +1055,22 @@
   return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second);
 }
 
+static unsigned correctForMultiByteChars(const char *Buf, unsigned LineStart,
+ unsigned Column)
+{
+   

[PATCH] D33042: [libclang] Allow to suspend a translation unit.

2017-05-30 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv closed this revision.
erikjv added a comment.

Committed as r304212.


https://reviews.llvm.org/D33042



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33405: Mark all ARCMT test files as binary files in git, just like with svn

2017-05-30 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

Ping?


https://reviews.llvm.org/D33405



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D15994: Allow for unfinished #if blocks in preambles.

2017-05-30 Thread Erik Verbruggen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
erikjv marked 3 inline comments as done.
Closed by commit rL304207: Allow for unfinished #if blocks in preambles 
(authored by erikjv).

Changed prior to commit:
  https://reviews.llvm.org/D15994?vs=98757=100691#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D15994

Files:
  cfe/trunk/include/clang/Lex/Preprocessor.h
  cfe/trunk/include/clang/Lex/PreprocessorLexer.h
  cfe/trunk/include/clang/Lex/PreprocessorOptions.h
  cfe/trunk/include/clang/Serialization/ASTBitCodes.h
  cfe/trunk/lib/Frontend/ASTUnit.cpp
  cfe/trunk/lib/Lex/Lexer.cpp
  cfe/trunk/lib/Lex/PPLexerChange.cpp
  cfe/trunk/lib/Lex/Preprocessor.cpp
  cfe/trunk/lib/Serialization/ASTReader.cpp
  cfe/trunk/lib/Serialization/ASTWriter.cpp
  cfe/trunk/test/Lexer/preamble.c
  cfe/trunk/test/Lexer/preamble2.c

Index: cfe/trunk/lib/Lex/Preprocessor.cpp
===
--- cfe/trunk/lib/Lex/Preprocessor.cpp
+++ cfe/trunk/lib/Lex/Preprocessor.cpp
@@ -150,6 +150,9 @@
 Ident_GetExceptionInfo = Ident_GetExceptionCode = nullptr;
 Ident_AbnormalTermination = nullptr;
   }
+
+  if (this->PPOpts->GeneratePreamble)
+PreambleConditionalStack.startRecording();
 }
 
 Preprocessor::~Preprocessor() {
@@ -532,6 +535,12 @@
 
   // Start parsing the predefines.
   EnterSourceFile(FID, nullptr, SourceLocation());
+
+  // Restore the conditional stack from the preamble, if there is one.
+  if (PreambleConditionalStack.isReplaying()) {
+CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack());
+PreambleConditionalStack.doneReplaying();
+  }
 }
 
 void Preprocessor::EndSourceFile() {
Index: cfe/trunk/lib/Lex/PPLexerChange.cpp
===
--- cfe/trunk/lib/Lex/PPLexerChange.cpp
+++ cfe/trunk/lib/Lex/PPLexerChange.cpp
@@ -46,6 +46,12 @@
   });
 }
 
+bool Preprocessor::isInMainFile() const {
+  if (IsFileLexer())
+return IncludeMacroStack.size() == 0;
+  return true;
+}
+
 /// getCurrentLexer - Return the current file lexer being lexed from.  Note
 /// that this ignores any potentially active macro expansions and _Pragma
 /// expansions going on at the time.
Index: cfe/trunk/lib/Lex/Lexer.cpp
===
--- cfe/trunk/lib/Lex/Lexer.cpp
+++ cfe/trunk/lib/Lex/Lexer.cpp
@@ -550,8 +550,6 @@
 
   enum PreambleDirectiveKind {
 PDK_Skipped,
-PDK_StartIf,
-PDK_EndIf,
 PDK_Unknown
   };
 
@@ -574,8 +572,6 @@
 
   bool InPreprocessorDirective = false;
   Token TheTok;
-  Token IfStartTok;
-  unsigned IfCount = 0;
   SourceLocation ActiveCommentLoc;
 
   unsigned MaxLineOffset = 0;
@@ -658,33 +654,18 @@
   .Case("sccs", PDK_Skipped)
   .Case("assert", PDK_Skipped)
   .Case("unassert", PDK_Skipped)
-  .Case("if", PDK_StartIf)
-  .Case("ifdef", PDK_StartIf)
-  .Case("ifndef", PDK_StartIf)
+  .Case("if", PDK_Skipped)
+  .Case("ifdef", PDK_Skipped)
+  .Case("ifndef", PDK_Skipped)
   .Case("elif", PDK_Skipped)
   .Case("else", PDK_Skipped)
-  .Case("endif", PDK_EndIf)
+  .Case("endif", PDK_Skipped)
   .Default(PDK_Unknown);
 
 switch (PDK) {
 case PDK_Skipped:
   continue;
 
-case PDK_StartIf:
-  if (IfCount == 0)
-IfStartTok = HashTok;
-
-  ++IfCount;
-  continue;
-
-case PDK_EndIf:
-  // Mismatched #endif. The preamble ends here.
-  if (IfCount == 0)
-break;
-
-  --IfCount;
-  continue;
-
 case PDK_Unknown:
   // We don't know what this directive is; stop at the '#'.
   break;
@@ -705,16 +686,13 @@
   } while (true);
   
   SourceLocation End;
-  if (IfCount)
-End = IfStartTok.getLocation();
-  else if (ActiveCommentLoc.isValid())
+  if (ActiveCommentLoc.isValid())
 End = ActiveCommentLoc; // don't truncate a decl comment.
   else
 End = TheTok.getLocation();
 
   return std::make_pair(End.getRawEncoding() - StartLoc.getRawEncoding(),
-IfCount? IfStartTok.isAtStartOfLine()
-   : TheTok.isAtStartOfLine());
+TheTok.isAtStartOfLine());
 }
 
 /// AdvanceToTokenCharacter - Given a location that specifies the start of a
@@ -2570,6 +2548,11 @@
 return true;
   }
   
+  if (PP->isRecordingPreamble() && !PP->isInMainFile()) {
+PP->setRecordedPreambleConditionalStack(ConditionalStack);
+ConditionalStack.clear();
+  }
+
   // Issue diagnostics for unterminated #if and missing newline.
 
   // If we are in a #if directive, emit an error.
Index: cfe/trunk/lib/Frontend/ASTUnit.cpp
===
--- 

[PATCH] D33405: Mark all ARCMT test files as binary files in git, just like with svn

2017-05-22 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv created this revision.
Herald added a subscriber: javed.absar.

This is a work-around for ARCMT's inability to handle Windows-style line
terminators (\r\n) correctly. The underlying problem seems to be that
line terminators are assumed to be 1 character long. So with files
ending with \r\n the rewritten files end with \r\r\n. See also PR33124.


https://reviews.llvm.org/D33405

Files:
  .gitattributes


Index: .gitattributes
===
--- /dev/null
+++ .gitattributes
@@ -0,0 +1,6 @@
+# Default behaviour
+* text=auto
+
+# ARCMT test files
+test/ARCMT/* binary
+test/ARCMT/*/* binary


Index: .gitattributes
===
--- /dev/null
+++ .gitattributes
@@ -0,0 +1,6 @@
+# Default behaviour
+* text=auto
+
+# ARCMT test files
+test/ARCMT/* binary
+test/ARCMT/*/* binary
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D15994: Allow for unfinished #if blocks in preambles.

2017-05-12 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv updated this revision to Diff 98757.

https://reviews.llvm.org/D15994

Files:
  include/clang/Lex/Preprocessor.h
  include/clang/Lex/PreprocessorLexer.h
  include/clang/Lex/PreprocessorOptions.h
  include/clang/Serialization/ASTBitCodes.h
  lib/Frontend/ASTUnit.cpp
  lib/Lex/Lexer.cpp
  lib/Lex/PPLexerChange.cpp
  lib/Lex/Preprocessor.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTWriter.cpp
  test/Lexer/preamble.c
  test/Lexer/preamble2.c

Index: test/Lexer/preamble2.c
===
--- /dev/null
+++ test/Lexer/preamble2.c
@@ -0,0 +1,19 @@
+// Preamble detection test: header with an include guard.
+#ifndef HEADER_H
+#define HEADER_H
+#include "foo"
+int bar;
+#endif
+
+// This test checks for detection of the preamble of a file, which
+// includes all of the starting comments and #includes.
+
+// RUN: %clang_cc1 -print-preamble %s > %t
+// RUN: echo END. >> %t
+// RUN: FileCheck < %t %s
+
+// CHECK: // Preamble detection test: header with an include guard.
+// CHECK-NEXT: #ifndef HEADER_H
+// CHECK-NEXT: #define HEADER_H
+// CHECK-NEXT: #include "foo"
+// CHECK-NEXT: END.
Index: test/Lexer/preamble.c
===
--- test/Lexer/preamble.c
+++ test/Lexer/preamble.c
@@ -9,15 +9,12 @@
 #pragma unknown
 #endif
 #ifdef WIBBLE
-#include "honk"
-#else
-int foo();
+#include "foo"
+int bar;
 #endif
 
 // This test checks for detection of the preamble of a file, which
-// includes all of the starting comments and #includes. Note that any
-// changes to the preamble part of this file must be mirrored in
-// Inputs/preamble.txt, since we diff against it.
+// includes all of the starting comments and #includes.
 
 // RUN: %clang_cc1 -print-preamble %s > %t
 // RUN: echo END. >> %t
@@ -33,4 +30,6 @@
 // CHECK-NEXT: #endif
 // CHECK-NEXT: #pragma unknown
 // CHECK-NEXT: #endif
+// CHECK-NEXT: #ifdef WIBBLE
+// CHECK-NEXT: #include "foo"
 // CHECK-NEXT: END.
Index: lib/Serialization/ASTWriter.cpp
===
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -1093,6 +1093,7 @@
   RECORD(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES);
   RECORD(DELETE_EXPRS_TO_ANALYZE);
   RECORD(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH);
+  RECORD(PP_CONDITIONAL_STACK);
 
   // SourceManager Block.
   BLOCK(SOURCE_MANAGER_BLOCK);
@@ -2302,6 +2303,18 @@
 Stream.EmitRecord(PP_COUNTER_VALUE, Record);
   }
 
+  if (PP.isRecordingPreamble() && PP.hasRecordedPreamble()) {
+assert(!IsModule);
+for (const auto  : PP.getPreambleConditionalStack()) {
+  AddSourceLocation(Cond.IfLoc, Record);
+  Record.push_back(Cond.WasSkipping);
+  Record.push_back(Cond.FoundNonSkip);
+  Record.push_back(Cond.FoundElse);
+}
+Stream.EmitRecord(PP_CONDITIONAL_STACK, Record);
+Record.clear();
+  }
+
   // Enter the preprocessor block.
   Stream.EnterSubblock(PREPROCESSOR_BLOCK_ID, 3);
 
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -2925,6 +2925,21 @@
   }
   break;
 
+case PP_CONDITIONAL_STACK:
+  if (!Record.empty()) {
+SmallVector ConditionalStack;
+for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) {
+  auto Loc = ReadSourceLocation(F, Record, Idx);
+  bool WasSkipping = Record[Idx++];
+  bool FoundNonSkip = Record[Idx++];
+  bool FoundElse = Record[Idx++];
+  ConditionalStack.push_back(
+  {Loc, WasSkipping, FoundNonSkip, FoundElse});
+}
+PP.setReplayablePreambleConditionalStack(ConditionalStack);
+  }
+  break;
+
 case PP_COUNTER_VALUE:
   if (!Record.empty() && Listener)
 Listener->ReadCounter(F, Record[0]);
Index: lib/Lex/Preprocessor.cpp
===
--- lib/Lex/Preprocessor.cpp
+++ lib/Lex/Preprocessor.cpp
@@ -150,6 +150,9 @@
 Ident_GetExceptionInfo = Ident_GetExceptionCode = nullptr;
 Ident_AbnormalTermination = nullptr;
   }
+
+  if (this->PPOpts->GeneratePreamble)
+PreambleConditionalStack.startRecording();
 }
 
 Preprocessor::~Preprocessor() {
@@ -537,6 +540,12 @@
 
   // Start parsing the predefines.
   EnterSourceFile(FID, nullptr, SourceLocation());
+
+  // Restore the conditional stack from the preamble, if there is one.
+  if (PreambleConditionalStack.isReplaying()) {
+CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack());
+PreambleConditionalStack.doneReplaying();
+  }
 }
 
 void Preprocessor::EndSourceFile() {
Index: lib/Lex/PPLexerChange.cpp
===
--- lib/Lex/PPLexerChange.cpp
+++ lib/Lex/PPLexerChange.cpp
@@ -46,6 +46,12 @@
   });
 }
 
+bool 

[PATCH] D15994: Allow for unfinished #if blocks in preambles.

2017-05-12 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv marked 8 inline comments as done.
erikjv added a comment.

Fixed with the next patch.


https://reviews.llvm.org/D15994



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27810: FileManager: mark virtual file entries as valid entries

2017-03-28 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv closed this revision.
erikjv added a comment.

Committed as r298905.


https://reviews.llvm.org/D27810



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27810: FileManager: mark virtual file entries as valid entries

2017-03-28 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv updated this revision to Diff 93221.
erikjv added a comment.

Added a test for the specific scenario, and added asserts for validity of UFEs 
returned by getVirtualFile.


https://reviews.llvm.org/D27810

Files:
  lib/Basic/FileManager.cpp
  unittests/Basic/FileManagerTest.cpp

Index: unittests/Basic/FileManagerTest.cpp
===
--- unittests/Basic/FileManagerTest.cpp
+++ unittests/Basic/FileManagerTest.cpp
@@ -12,6 +12,7 @@
 #include "clang/Basic/FileSystemStatCache.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Path.h"
 #include "gtest/gtest.h"
 
 using namespace llvm;
@@ -29,6 +30,12 @@
   llvm::StringMap StatCalls;
 
   void InjectFileOrDirectory(const char *Path, ino_t INode, bool IsFile) {
+#ifndef LLVM_ON_WIN32
+SmallString<128> NormalizedPath(Path);
+llvm::sys::path::native(NormalizedPath);
+Path = NormalizedPath.c_str();
+#endif
+
 FileData Data;
 Data.Name = Path;
 Data.Size = 0;
@@ -55,6 +62,12 @@
   LookupResult getStat(StringRef Path, FileData , bool isFile,
std::unique_ptr *F,
vfs::FileSystem ) override {
+#ifndef LLVM_ON_WIN32
+SmallString<128> NormalizedPath(Path);
+llvm::sys::path::native(NormalizedPath);
+Path = NormalizedPath.c_str();
+#endif
+
 if (StatCalls.count(Path) != 0) {
   Data = StatCalls[Path];
   return CacheExists;
@@ -140,6 +153,7 @@
 
   const FileEntry *file = manager.getFile("/tmp/test");
   ASSERT_TRUE(file != nullptr);
+  ASSERT_TRUE(file->isValid());
   EXPECT_EQ("/tmp/test", file->getName());
 
   const DirectoryEntry *dir = file->getDir();
@@ -164,6 +178,7 @@
   manager.getVirtualFile("virtual/dir/bar.h", 100, 0);
   const FileEntry *file = manager.getFile("virtual/dir/bar.h");
   ASSERT_TRUE(file != nullptr);
+  ASSERT_TRUE(file->isValid());
   EXPECT_EQ("virtual/dir/bar.h", file->getName());
 
   const DirectoryEntry *dir = file->getDir();
@@ -185,7 +200,9 @@
   const FileEntry *fileFoo = manager.getFile("foo.cpp");
   const FileEntry *fileBar = manager.getFile("bar.cpp");
   ASSERT_TRUE(fileFoo != nullptr);
+  ASSERT_TRUE(fileFoo->isValid());
   ASSERT_TRUE(fileBar != nullptr);
+  ASSERT_TRUE(fileBar->isValid());
   EXPECT_NE(fileFoo, fileBar);
 }
 
@@ -231,8 +248,8 @@
   statCache->InjectFile("abc/bar.cpp", 42);
   manager.addStatCache(std::move(statCache));
 
-  manager.getVirtualFile("abc/foo.cpp", 100, 0);
-  manager.getVirtualFile("abc/bar.cpp", 200, 0);
+  ASSERT_TRUE(manager.getVirtualFile("abc/foo.cpp", 100, 0)->isValid());
+  ASSERT_TRUE(manager.getVirtualFile("abc/bar.cpp", 200, 0)->isValid());
 
   EXPECT_EQ(manager.getFile("abc/foo.cpp"), manager.getFile("abc/bar.cpp"));
 }
@@ -246,6 +263,37 @@
   manager.removeStatCache(statCache);
 }
 
+// getFile() Should return the same entry as getVirtualFile if the file actually
+// is a virtual file, even if the name is not exactly the same (but is after
+// normalisation done by the file system, like on Windows). This can be checked
+// here by checkng the size.
+TEST_F(FileManagerTest, getVirtualFileWithDifferentName) {
+  // Inject fake files into the file system.
+  auto statCache = llvm::make_unique();
+  statCache->InjectDirectory("c:\\tmp", 42);
+  statCache->InjectFile("c:\\tmp\\test", 43);
+
+  manager.addStatCache(std::move(statCache));
+
+  // Inject the virtual file:
+  const FileEntry *file1 = manager.getVirtualFile("c:\\tmp\\test", 123, 1);
+  ASSERT_TRUE(file1 != nullptr);
+  ASSERT_TRUE(file1->isValid());
+  EXPECT_EQ(43U, file1->getUniqueID().getFile());
+  EXPECT_EQ(123, file1->getSize());
+
+  // Lookup the virtual file with a different name:
+  const FileEntry *file2 = manager.getFile("c:/tmp/test", 100, 1);
+  ASSERT_TRUE(file2 != nullptr);
+  ASSERT_TRUE(file2->isValid());
+  // Check that it's the same UFE:
+  EXPECT_EQ(file1, file2);
+  EXPECT_EQ(43U, file2->getUniqueID().getFile());
+  // Check that the contents of the UFE are not overwritten by the entry in the
+  // filesystem:
+  EXPECT_EQ(123, file2->getSize());
+}
+
 #endif  // !LLVM_ON_WIN32
 
 } // anonymous namespace
Index: lib/Basic/FileManager.cpp
===
--- lib/Basic/FileManager.cpp
+++ lib/Basic/FileManager.cpp
@@ -386,6 +386,7 @@
   UFE->ModTime = ModificationTime;
   UFE->Dir = DirInfo;
   UFE->UID = NextFileUID++;
+  UFE->IsValid = true;
   UFE->File.reset();
   return UFE;
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30248: [libclang] Fix crash in member access code completion with implicit base

2017-03-28 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv closed this revision.
erikjv added a comment.

Landed as r298903.


https://reviews.llvm.org/D30248



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27810: FileManager: mark virtual file entries as valid entries

2017-03-08 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

@klimek no, it's a 1 line fix. The rest was the previous version of the patch.


https://reviews.llvm.org/D27810



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27810: FileManager: mark virtual file entries as valid entries

2017-03-08 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

@kfunk yes and yes, so @bkramer or @klimek : ping?


https://reviews.llvm.org/D27810



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30248: [libclang] Fix crash in member access code completion with implicit base

2017-02-22 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv created this revision.

If there is an unresolved member access AST node, and the base is
implicit, do not access/use it for generating candidate overloads for
code completion results (because the base is a nullptr).

Fixes PR31093.


https://reviews.llvm.org/D30248

Files:
  lib/Sema/SemaCodeComplete.cpp
  lib/Sema/SemaOverload.cpp
  test/CodeCompletion/member-access.cpp

Index: test/CodeCompletion/member-access.cpp
===
--- test/CodeCompletion/member-access.cpp
+++ test/CodeCompletion/member-access.cpp
@@ -37,6 +37,17 @@
   }
 };
 
+struct Foo {
+  void foo() const;
+  static void foo(bool);
+};
+
+struct Bar {
+  void foo(bool param) {
+Foo::foo(  );// unresolved member expression with an implicit base
+  }
+};
+
   // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:29:6 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
   // CHECK-CC1: Base1 : Base1::
   // CHECK-CC1: member1 : [#int#][#Base1::#]member1
@@ -52,3 +63,6 @@
 
 // Make sure this doesn't crash
 // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:36:7 %s -verify
+
+// Make sure this also doesn't crash
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:47:14 %s
Index: lib/Sema/SemaOverload.cpp
===
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -6307,30 +6307,43 @@
   for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
 NamedDecl *D = F.getDecl()->getUnderlyingDecl();
 if (FunctionDecl *FD = dyn_cast(D)) {
-  if (isa(FD) && !cast(FD)->isStatic())
+  if (isa(FD) && !cast(FD)->isStatic()) {
+QualType ObjectType;
+Expr::Classification ObjectClassification;
+if (Expr *E = Args[0]) {
+  ObjectType = E->getType();
+  ObjectClassification = E->Classify(Context);
+}
 AddMethodCandidate(cast(FD), F.getPair(),
-   cast(FD)->getParent(),
-   Args[0]->getType(), Args[0]->Classify(Context),
-   Args.slice(1), CandidateSet, SuppressUserConversions,
-   PartialOverloading);
-  else
+   cast(FD)->getParent(), ObjectType,
+   ObjectClassification, Args.slice(1), CandidateSet,
+   SuppressUserConversions, PartialOverloading);
+  } else {
 AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet,
  SuppressUserConversions, PartialOverloading);
+  }
 } else {
   FunctionTemplateDecl *FunTmpl = cast(D);
   if (isa(FunTmpl->getTemplatedDecl()) &&
-  !cast(FunTmpl->getTemplatedDecl())->isStatic())
+  !cast(FunTmpl->getTemplatedDecl())->isStatic()) {
+QualType ObjectType;
+Expr::Classification ObjectClassification;
+if (Expr *E = Args[0]) {
+  ObjectType = E->getType();
+  ObjectClassification = E->Classify(Context);
+}
 AddMethodTemplateCandidate(
 FunTmpl, F.getPair(),
 cast(FunTmpl->getDeclContext()),
-ExplicitTemplateArgs, Args[0]->getType(),
-Args[0]->Classify(Context), Args.slice(1), CandidateSet,
-SuppressUserConversions, PartialOverloading);
-  else
+ExplicitTemplateArgs, ObjectType, ObjectClassification,
+Args.slice(1), CandidateSet, SuppressUserConversions,
+PartialOverloading);
+  } else {
 AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
  ExplicitTemplateArgs, Args,
  CandidateSet, SuppressUserConversions,
  PartialOverloading);
+  }
 }
   }
 }
Index: lib/Sema/SemaCodeComplete.cpp
===
--- lib/Sema/SemaCodeComplete.cpp
+++ lib/Sema/SemaCodeComplete.cpp
@@ -4309,7 +4309,8 @@
   UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
   TemplateArgs = 
 }
-SmallVector ArgExprs(1, UME->getBase());
+SmallVector ArgExprs(
+1, UME->isImplicitAccess() ? nullptr : UME->getBase());
 ArgExprs.append(Args.begin(), Args.end());
 UnresolvedSet<8> Decls;
 Decls.append(UME->decls_begin(), UME->decls_end());
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27810: FileManager: mark virtual file entries as valid entries

2017-02-17 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv updated this revision to Diff 88874.
erikjv retitled this revision from "Normalize all filenames before searching 
FileManager caches" to "FileManager: mark virtual file entries as valid 
entries".
erikjv edited the summary of this revision.

https://reviews.llvm.org/D27810

Files:
  lib/Basic/FileManager.cpp


Index: lib/Basic/FileManager.cpp
===
--- lib/Basic/FileManager.cpp
+++ lib/Basic/FileManager.cpp
@@ -386,6 +386,7 @@
   UFE->ModTime = ModificationTime;
   UFE->Dir = DirInfo;
   UFE->UID = NextFileUID++;
+  UFE->IsValid = true;
   UFE->File.reset();
   return UFE;
 }


Index: lib/Basic/FileManager.cpp
===
--- lib/Basic/FileManager.cpp
+++ lib/Basic/FileManager.cpp
@@ -386,6 +386,7 @@
   UFE->ModTime = ModificationTime;
   UFE->Dir = DirInfo;
   UFE->UID = NextFileUID++;
+  UFE->IsValid = true;
   UFE->File.reset();
   return UFE;
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29755: Cache FileID when translating diagnostics in PCH files

2017-02-16 Thread Erik Verbruggen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL295301: Cache FileID when translating diagnostics in PCH 
files (authored by erikjv).

Changed prior to commit:
  https://reviews.llvm.org/D29755?vs=88366=88701#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D29755

Files:
  cfe/trunk/lib/Frontend/ASTUnit.cpp


Index: cfe/trunk/lib/Frontend/ASTUnit.cpp
===
--- cfe/trunk/lib/Frontend/ASTUnit.cpp
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp
@@ -2541,14 +2541,19 @@
 
   SmallVector Result;
   Result.reserve(Diags.size());
+  const FileEntry *PreviousFE = nullptr;
+  FileID FID;
   for (const StandaloneDiagnostic  : Diags) {
 // Rebuild the StoredDiagnostic.
 if (SD.Filename.empty())
   continue;
 const FileEntry *FE = FileMgr.getFile(SD.Filename);
 if (!FE)
   continue;
-FileID FID = SrcMgr.translateFile(FE);
+if (FE != PreviousFE) {
+  FID = SrcMgr.translateFile(FE);
+  PreviousFE = FE;
+}
 SourceLocation FileLoc = SrcMgr.getLocForStartOfFile(FID);
 if (FileLoc.isInvalid())
   continue;


Index: cfe/trunk/lib/Frontend/ASTUnit.cpp
===
--- cfe/trunk/lib/Frontend/ASTUnit.cpp
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp
@@ -2541,14 +2541,19 @@
 
   SmallVector Result;
   Result.reserve(Diags.size());
+  const FileEntry *PreviousFE = nullptr;
+  FileID FID;
   for (const StandaloneDiagnostic  : Diags) {
 // Rebuild the StoredDiagnostic.
 if (SD.Filename.empty())
   continue;
 const FileEntry *FE = FileMgr.getFile(SD.Filename);
 if (!FE)
   continue;
-FileID FID = SrcMgr.translateFile(FE);
+if (FE != PreviousFE) {
+  FID = SrcMgr.translateFile(FE);
+  PreviousFE = FE;
+}
 SourceLocation FileLoc = SrcMgr.getLocForStartOfFile(FID);
 if (FileLoc.isInvalid())
   continue;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29755: Cache FileID when translating diagnostics in PCH files

2017-02-14 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv updated this revision to Diff 88366.

https://reviews.llvm.org/D29755

Files:
  lib/Frontend/ASTUnit.cpp


Index: lib/Frontend/ASTUnit.cpp
===
--- lib/Frontend/ASTUnit.cpp
+++ lib/Frontend/ASTUnit.cpp
@@ -2539,14 +2539,19 @@
 
   SmallVector Result;
   Result.reserve(Diags.size());
+  const FileEntry *PreviousFE = nullptr;
+  FileID FID;
   for (const StandaloneDiagnostic  : Diags) {
 // Rebuild the StoredDiagnostic.
 if (SD.Filename.empty())
   continue;
 const FileEntry *FE = FileMgr.getFile(SD.Filename);
 if (!FE)
   continue;
-FileID FID = SrcMgr.translateFile(FE);
+if (FE != PreviousFE) {
+  FID = SrcMgr.translateFile(FE);
+  PreviousFE = FE;
+}
 SourceLocation FileLoc = SrcMgr.getLocForStartOfFile(FID);
 if (FileLoc.isInvalid())
   continue;


Index: lib/Frontend/ASTUnit.cpp
===
--- lib/Frontend/ASTUnit.cpp
+++ lib/Frontend/ASTUnit.cpp
@@ -2539,14 +2539,19 @@
 
   SmallVector Result;
   Result.reserve(Diags.size());
+  const FileEntry *PreviousFE = nullptr;
+  FileID FID;
   for (const StandaloneDiagnostic  : Diags) {
 // Rebuild the StoredDiagnostic.
 if (SD.Filename.empty())
   continue;
 const FileEntry *FE = FileMgr.getFile(SD.Filename);
 if (!FE)
   continue;
-FileID FID = SrcMgr.translateFile(FE);
+if (FE != PreviousFE) {
+  FID = SrcMgr.translateFile(FE);
+  PreviousFE = FE;
+}
 SourceLocation FileLoc = SrcMgr.getLocForStartOfFile(FID);
 if (FileLoc.isInvalid())
   continue;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D15994: Allow for unfinished #if blocks in preambles.

2017-02-09 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv updated this revision to Diff 87792.

https://reviews.llvm.org/D15994

Files:
  include/clang/Lex/Preprocessor.h
  include/clang/Lex/PreprocessorLexer.h
  include/clang/Lex/PreprocessorOptions.h
  include/clang/Serialization/ASTBitCodes.h
  lib/Frontend/ASTUnit.cpp
  lib/Lex/Lexer.cpp
  lib/Lex/PPLexerChange.cpp
  lib/Lex/Preprocessor.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTWriter.cpp
  test/Lexer/preamble.c
  test/Lexer/preamble2.c

Index: test/Lexer/preamble2.c
===
--- /dev/null
+++ test/Lexer/preamble2.c
@@ -0,0 +1,19 @@
+// Preamble detection test: header with an include guard.
+#ifndef HEADER_H
+#define HEADER_H
+#include "foo"
+int bar;
+#endif
+
+// This test checks for detection of the preamble of a file, which
+// includes all of the starting comments and #includes.
+
+// RUN: %clang_cc1 -print-preamble %s > %t
+// RUN: echo END. >> %t
+// RUN: FileCheck < %t %s
+
+// CHECK: // Preamble detection test: header with an include guard.
+// CHECK-NEXT: #ifndef HEADER_H
+// CHECK-NEXT: #define HEADER_H
+// CHECK-NEXT: #include "foo"
+// CHECK-NEXT: END.
Index: test/Lexer/preamble.c
===
--- test/Lexer/preamble.c
+++ test/Lexer/preamble.c
@@ -9,15 +9,12 @@
 #pragma unknown
 #endif
 #ifdef WIBBLE
-#include "honk"
-#else
-int foo();
+#include "foo"
+int bar;
 #endif
 
 // This test checks for detection of the preamble of a file, which
-// includes all of the starting comments and #includes. Note that any
-// changes to the preamble part of this file must be mirrored in
-// Inputs/preamble.txt, since we diff against it.
+// includes all of the starting comments and #includes.
 
 // RUN: %clang_cc1 -print-preamble %s > %t
 // RUN: echo END. >> %t
@@ -33,4 +30,6 @@
 // CHECK-NEXT: #endif
 // CHECK-NEXT: #pragma unknown
 // CHECK-NEXT: #endif
+// CHECK-NEXT: #ifdef WIBBLE
+// CHECK-NEXT: #include "foo"
 // CHECK-NEXT: END.
Index: lib/Serialization/ASTWriter.cpp
===
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -1090,6 +1090,7 @@
   RECORD(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES);
   RECORD(DELETE_EXPRS_TO_ANALYZE);
   RECORD(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH);
+  RECORD(PP_CONDITIONAL_STACK);
 
   // SourceManager Block.
   BLOCK(SOURCE_MANAGER_BLOCK);
@@ -2264,6 +2265,17 @@
 Stream.EmitRecord(PP_COUNTER_VALUE, Record);
   }
 
+  if (PP.isRecordingPreamble() && PP.hasRecordedPreamble()) {
+for (const auto  : PP.getPreambleConditionalStack()) {
+  AddSourceLocation(Cond.IfLoc, Record);
+  Record.push_back(Cond.WasSkipping);
+  Record.push_back(Cond.FoundNonSkip);
+  Record.push_back(Cond.FoundElse);
+}
+Stream.EmitRecord(PP_CONDITIONAL_STACK, Record);
+Record.clear();
+  }
+
   // Enter the preprocessor block.
   Stream.EnterSubblock(PREPROCESSOR_BLOCK_ID, 3);
 
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -2889,6 +2889,20 @@
   }
   break;
 
+case PP_CONDITIONAL_STACK:
+  if (!Record.empty()) {
+SmallVector ConditionalStack;
+for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) {
+  auto loc = ReadSourceLocation(F, Record, Idx);
+  bool WasSkipping = Record[Idx++];
+  bool FoundNonSkip = Record[Idx++];
+  bool FoundElse = Record[Idx++];
+  ConditionalStack.push_back({ loc, WasSkipping, FoundNonSkip, FoundElse });
+}
+PP.setReplayablePreambleConditionalStack(ConditionalStack);
+  }
+  break;
+
 case PP_COUNTER_VALUE:
   if (!Record.empty() && Listener)
 Listener->ReadCounter(F, Record[0]);
Index: lib/Lex/Preprocessor.cpp
===
--- lib/Lex/Preprocessor.cpp
+++ lib/Lex/Preprocessor.cpp
@@ -150,6 +150,9 @@
 Ident_GetExceptionInfo = Ident_GetExceptionCode = nullptr;
 Ident_AbnormalTermination = nullptr;
   }
+
+  if (this->PPOpts->GeneratePreamble)
+PreambleConditionalStack.startRecording();
 }
 
 Preprocessor::~Preprocessor() {
@@ -537,6 +540,12 @@
 
   // Start parsing the predefines.
   EnterSourceFile(FID, nullptr, SourceLocation());
+
+  // Restore the conditional stack from the preamble, if there is one.
+  if (PreambleConditionalStack.isReplaying()) {
+CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack());
+PreambleConditionalStack.doneReplaying();
+  }
 }
 
 void Preprocessor::EndSourceFile() {
Index: lib/Lex/PPLexerChange.cpp
===
--- lib/Lex/PPLexerChange.cpp
+++ lib/Lex/PPLexerChange.cpp
@@ -46,6 +46,12 @@
   });
 }
 
+bool Preprocessor::isInPreamble() const {
+  if (IsFileLexer())
+   

[PATCH] D29755: Cache FileID when translating diagnostics in PCH files

2017-02-09 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv created this revision.

Modules/preambles/PCH files can contain diagnostics, which, when used,
are added to the current ASTUnit. For that to work, they are translated
to use the current FileManager's FileIDs. When the entry is not the
main file, all local source locations will be checked by a linear
search. Now this is a problem, when there are lots of diagnostics (say,

25000. and lots of local source locations (say, 44), and end up

taking seconds when using such a preamble.

The fix is to cache the last FileID, because many subsequent diagnostics
refer to the same file. This reduces the time spent in
ASTUnit::TranslateStoredDiagnostics from seconds to a few milliseconds
for files with many slocs/diagnostics.

This fixes PR31353.


https://reviews.llvm.org/D29755

Files:
  lib/Frontend/ASTUnit.cpp


Index: lib/Frontend/ASTUnit.cpp
===
--- lib/Frontend/ASTUnit.cpp
+++ lib/Frontend/ASTUnit.cpp
@@ -2539,14 +2539,22 @@
 
   SmallVector Result;
   Result.reserve(Diags.size());
+  const FileEntry *CachedFE = nullptr;
+  FileID CachedFID;
   for (const StandaloneDiagnostic  : Diags) {
 // Rebuild the StoredDiagnostic.
 if (SD.Filename.empty())
   continue;
 const FileEntry *FE = FileMgr.getFile(SD.Filename);
 if (!FE)
   continue;
-FileID FID = SrcMgr.translateFile(FE);
+FileID FID;
+if (FE == CachedFE) {
+  FID = CachedFID;
+} else {
+  CachedFID = FID = SrcMgr.translateFile(FE);
+  CachedFE = FE;
+}
 SourceLocation FileLoc = SrcMgr.getLocForStartOfFile(FID);
 if (FileLoc.isInvalid())
   continue;


Index: lib/Frontend/ASTUnit.cpp
===
--- lib/Frontend/ASTUnit.cpp
+++ lib/Frontend/ASTUnit.cpp
@@ -2539,14 +2539,22 @@
 
   SmallVector Result;
   Result.reserve(Diags.size());
+  const FileEntry *CachedFE = nullptr;
+  FileID CachedFID;
   for (const StandaloneDiagnostic  : Diags) {
 // Rebuild the StoredDiagnostic.
 if (SD.Filename.empty())
   continue;
 const FileEntry *FE = FileMgr.getFile(SD.Filename);
 if (!FE)
   continue;
-FileID FID = SrcMgr.translateFile(FE);
+FileID FID;
+if (FE == CachedFE) {
+  FID = CachedFID;
+} else {
+  CachedFID = FID = SrcMgr.translateFile(FE);
+  CachedFE = FE;
+}
 SourceLocation FileLoc = SrcMgr.getLocForStartOfFile(FID);
 if (FileLoc.isInvalid())
   continue;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27810: Normalize all filenames before searching FileManager caches

2017-02-07 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv updated this revision to Diff 87376.
erikjv added a comment.

Fixed all failing tests on Windows.


https://reviews.llvm.org/D27810

Files:
  lib/Basic/FileManager.cpp
  lib/Basic/VirtualFileSystem.cpp
  lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
  test/CodeGen/debug-prefix-map.c
  test/Driver/ps4-header-search.c
  test/Frontend/dependency-gen.c
  test/Frontend/include-duplicate-removal.c
  test/Index/annotate-module.m
  test/Index/index-module.m
  test/Index/skip-parsed-bodies/compile_commands.json
  test/Modules/filename.cpp
  test/Modules/malformed.cpp
  test/Modules/relative-dep-gen.cpp
  test/Preprocessor/headermap-rel2.c
  test/Preprocessor/iwithprefix.c
  unittests/Basic/FileManagerTest.cpp

Index: unittests/Basic/FileManagerTest.cpp
===
--- unittests/Basic/FileManagerTest.cpp
+++ unittests/Basic/FileManagerTest.cpp
@@ -12,6 +12,7 @@
 #include "clang/Basic/FileSystemStatCache.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Path.h"
 #include "gtest/gtest.h"
 
 using namespace llvm;
@@ -29,15 +30,17 @@
   llvm::StringMap StatCalls;
 
   void InjectFileOrDirectory(const char *Path, ino_t INode, bool IsFile) {
+SmallString<128> NativePath(Path);
+llvm::sys::path::native(NativePath);
 FileData Data;
-Data.Name = Path;
+Data.Name = NativePath.c_str();
 Data.Size = 0;
 Data.ModTime = 0;
 Data.UniqueID = llvm::sys::fs::UniqueID(1, INode);
 Data.IsDirectory = !IsFile;
 Data.IsNamedPipe = false;
 Data.InPCH = false;
-StatCalls[Path] = Data;
+StatCalls[NativePath] = Data;
   }
 
 public:
@@ -89,7 +92,11 @@
 
   dir = file->getDir();
   ASSERT_TRUE(dir != nullptr);
+#ifdef LLVM_ON_WIN32
+  EXPECT_EQ("x\\y", dir->getName());
+#else
   EXPECT_EQ("x/y", dir->getName());
+#endif
 }
 
 // Before any virtual file is added, no virtual directory exists.
@@ -115,7 +122,9 @@
 
   const DirectoryEntry *dir = manager.getDirectory("virtual/dir");
   ASSERT_TRUE(dir != nullptr);
-  EXPECT_EQ("virtual/dir", dir->getName());
+  SmallString<10> ExpectedName("virtual/dir");
+  llvm::sys::path::native(ExpectedName);
+  EXPECT_EQ(ExpectedName, dir->getName());
 
   dir = manager.getDirectory("virtual");
   ASSERT_TRUE(dir != nullptr);
@@ -140,11 +149,15 @@
 
   const FileEntry *file = manager.getFile("/tmp/test");
   ASSERT_TRUE(file != nullptr);
-  EXPECT_EQ("/tmp/test", file->getName());
+  SmallString<10> ExpectedName("/tmp/test");
+  llvm::sys::path::native(ExpectedName);
+  EXPECT_EQ(ExpectedName, file->getName());
 
   const DirectoryEntry *dir = file->getDir();
   ASSERT_TRUE(dir != nullptr);
-  EXPECT_EQ("/tmp", dir->getName());
+  ExpectedName = "/tmp";
+  llvm::sys::path::native(ExpectedName);
+  EXPECT_EQ(ExpectedName, dir->getName());
 
 #ifdef LLVM_ON_WIN32
   file = manager.getFile(FileName);
@@ -164,11 +177,15 @@
   manager.getVirtualFile("virtual/dir/bar.h", 100, 0);
   const FileEntry *file = manager.getFile("virtual/dir/bar.h");
   ASSERT_TRUE(file != nullptr);
-  EXPECT_EQ("virtual/dir/bar.h", file->getName());
+  SmallString<10> ExpectedName("virtual/dir/bar.h");
+  llvm::sys::path::native(ExpectedName);
+  EXPECT_EQ(ExpectedName, file->getName());
 
   const DirectoryEntry *dir = file->getDir();
   ASSERT_TRUE(dir != nullptr);
-  EXPECT_EQ("virtual/dir", dir->getName());
+  ExpectedName = "virtual/dir";
+  llvm::sys::path::native(ExpectedName);
+  EXPECT_EQ(ExpectedName, dir->getName());
 }
 
 // getFile() returns different FileEntries for different paths when
Index: test/Preprocessor/iwithprefix.c
===
--- test/Preprocessor/iwithprefix.c
+++ test/Preprocessor/iwithprefix.c
@@ -8,9 +8,9 @@
 // RUN: FileCheck %s < %t.out
 
 // CHECK: #include <...> search starts here:
-// CHECK: {{.*}}.tmps/first
+// CHECK: {{.*}}.tmps{{/|\\}}first
 // CHECK: {{/|\\}}lib{{(32|64)?}}{{/|\\}}clang{{/|\\}}{{[.0-9]+}}{{/|\\}}include
-// CHECK: {{.*}}.tmps/second
+// CHECK: {{.*}}.tmps{{/|\\}}second
 // CHECK-NOT: {{.*}}.tmps
 
 
Index: test/Preprocessor/headermap-rel2.c
===
--- test/Preprocessor/headermap-rel2.c
+++ test/Preprocessor/headermap-rel2.c
@@ -5,9 +5,9 @@
 // RUN: %clang_cc1 -fsyntax-only %s -iquote %S/Inputs/headermap-rel2/project-headers.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out
 // RUN: FileCheck %s -input-file %t.out
 
-// CHECK: Product/someheader.h
-// CHECK: system/usr/include{{[/\\]+}}someheader.h
-// CHECK: system/usr/include{{[/\\]+}}someheader.h
+// CHECK: Product{{/|}}someheader.h
+// CHECK: system{{/|}}usr{{/|}}include{{/|}}someheader.h
+// CHECK: system{{/|}}usr{{/|}}include{{/|}}someheader.h
 
 #include "someheader.h"
 #include 
Index: test/Modules/relative-dep-gen.cpp

[PATCH] D27810: Normalize all filenames before searching FileManager caches

2017-01-27 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added inline comments.



Comment at: lib/Basic/FileManager.cpp:218
+#ifdef LLVM_ON_WIN32
+  SmallString<128> NormalizedPath(Filename.str());
+  llvm::sys::path::native(NormalizedPath);

yaron.keren wrote:
> I'd use a larger SmallString<256>, with large projects 128 bytes are 
> frequently not enough.
Well, the calling sides often use 128, so that's why I stuck with it.


https://reviews.llvm.org/D27810



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27810: Normalize all filenames before searching FileManager caches

2017-01-27 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

besc: I can't reproduce any crash. I tried trunk and the release_39 branch with 
msvc2015.


https://reviews.llvm.org/D27810



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27810: Normalize all filenames before searching FileManager caches

2016-12-15 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv created this revision.
erikjv added reviewers: bkramer, klimek.
erikjv added a subscriber: cfe-commits.

The problem on windows is that both forward-slashes and back-slashes are
accepted as path separators. However, the FileManager stores the path as
reported by the OS after opening the file. For example: d:\dev/foo.cc
will be stored with the key d:\dev\foo.cc. Subsequent lookups for the
case with the forward slash then miss that cache entry, and clang ends
up doing many more file accesses than needed.

It also had the nasty side-effect of not closing the file the second
time it was loaded (until the FileManager was destroyed): the lexer
would create a buffer by file-id, and the buffer cache would return the
buffer created the previous time the file was opened. And because
creating the buffer also closes the file, this would not happen. As long
as the FileManager was around (i.e. as long as the translation unit for
e.g. libclang was around), and IDE couldn't save that file.


https://reviews.llvm.org/D27810

Files:
  lib/Basic/FileManager.cpp


Index: lib/Basic/FileManager.cpp
===
--- lib/Basic/FileManager.cpp
+++ lib/Basic/FileManager.cpp
@@ -214,6 +214,12 @@
 
 const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
   bool CacheFailure) {
+#ifdef LLVM_ON_WIN32
+  SmallString<128> NormalizedPath(Filename.str());
+  llvm::sys::path::native(NormalizedPath);
+  Filename = NormalizedPath;
+#endif // LLVM_ON_WIN32
+
   ++NumFileLookups;
 
   // See if there is already an entry in the map.


Index: lib/Basic/FileManager.cpp
===
--- lib/Basic/FileManager.cpp
+++ lib/Basic/FileManager.cpp
@@ -214,6 +214,12 @@
 
 const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
   bool CacheFailure) {
+#ifdef LLVM_ON_WIN32
+  SmallString<128> NormalizedPath(Filename.str());
+  llvm::sys::path::native(NormalizedPath);
+  Filename = NormalizedPath;
+#endif // LLVM_ON_WIN32
+
   ++NumFileLookups;
 
   // See if there is already an entry in the map.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D21075: Correct invalid end location in diagnostics for some identifiers.

2016-12-08 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv updated this revision to Diff 80735.

https://reviews.llvm.org/D21075

Files:
  lib/Parse/ParseDecl.cpp
  lib/Sema/SemaExpr.cpp
  test/Index/diagnostic-ranges.cpp


Index: test/Index/diagnostic-ranges.cpp
===
--- /dev/null
+++ test/Index/diagnostic-ranges.cpp
@@ -0,0 +1,23 @@
+// RUN: c-index-test -test-load-source all %s > /dev/null 2> %t.err
+// RUN: FileCheck < %t.err -check-prefix=CHECK-RANGE %s
+
+struct Foo {
+  someIdentifierLeadingToAnInvalidRange;
+};
+
+template 
+struct Bar {
+  Bar(const T&) {}
+};
+  
+void f()
+{
+  for (Bar<__typeof__(v.x)> container(v.x); true; )
+return;
+}
+
+// CHECK-RANGE: diagnostic-ranges.cpp:5:3: error: C++ requires a type 
specifier for all declarations
+// CHECK-RANGE: diagnostic-ranges.cpp:15:39: error: use of undeclared 
identifier 'v'
+// CHECK-RANGE: diagnostic-ranges.cpp:5:3:{5:3-5:40}: error: C++ requires a 
type specifier for all declarations
+// CHECK-RANGE: diagnostic-ranges.cpp:15:23:{15:23-15:24}: error: use of 
undeclared identifier 'v'
+
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -2042,7 +2042,9 @@
   }
 
   // Give up, we can't recover.
-  Diag(R.getNameLoc(), diagnostic) << Name;
+  auto Builder = Diag(R.getNameLoc(), diagnostic) << Name;
+  if (Name.isIdentifier())
+Builder << SourceRange(R.getNameLoc());
   return true;
 }
 
Index: lib/Parse/ParseDecl.cpp
===
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -2697,12 +2697,9 @@
 AccessSpecifier AS,
 DeclSpecContext DSContext,
 LateParsedAttrList *LateAttrs) {
-  if (DS.getSourceRange().isInvalid()) {
-// Start the range at the current token but make the end of the range
-// invalid.  This will make the entire range invalid unless we successfully
-// consume a token.
+  if (DS.getSourceRange().isInvalid() && !Tok.is(tok::eof)) {
 DS.SetRangeStart(Tok.getLocation());
-DS.SetRangeEnd(SourceLocation());
+DS.SetRangeEnd(Tok.getLocation());
   }
 
   bool EnteringContext = (DSContext == DSC_class || DSContext == 
DSC_top_level);


Index: test/Index/diagnostic-ranges.cpp
===
--- /dev/null
+++ test/Index/diagnostic-ranges.cpp
@@ -0,0 +1,23 @@
+// RUN: c-index-test -test-load-source all %s > /dev/null 2> %t.err
+// RUN: FileCheck < %t.err -check-prefix=CHECK-RANGE %s
+
+struct Foo {
+  someIdentifierLeadingToAnInvalidRange;
+};
+
+template 
+struct Bar {
+  Bar(const T&) {}
+};
+  
+void f()
+{
+  for (Bar<__typeof__(v.x)> container(v.x); true; )
+return;
+}
+
+// CHECK-RANGE: diagnostic-ranges.cpp:5:3: error: C++ requires a type specifier for all declarations
+// CHECK-RANGE: diagnostic-ranges.cpp:15:39: error: use of undeclared identifier 'v'
+// CHECK-RANGE: diagnostic-ranges.cpp:5:3:{5:3-5:40}: error: C++ requires a type specifier for all declarations
+// CHECK-RANGE: diagnostic-ranges.cpp:15:23:{15:23-15:24}: error: use of undeclared identifier 'v'
+
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -2042,7 +2042,9 @@
   }
 
   // Give up, we can't recover.
-  Diag(R.getNameLoc(), diagnostic) << Name;
+  auto Builder = Diag(R.getNameLoc(), diagnostic) << Name;
+  if (Name.isIdentifier())
+Builder << SourceRange(R.getNameLoc());
   return true;
 }
 
Index: lib/Parse/ParseDecl.cpp
===
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -2697,12 +2697,9 @@
 AccessSpecifier AS,
 DeclSpecContext DSContext,
 LateParsedAttrList *LateAttrs) {
-  if (DS.getSourceRange().isInvalid()) {
-// Start the range at the current token but make the end of the range
-// invalid.  This will make the entire range invalid unless we successfully
-// consume a token.
+  if (DS.getSourceRange().isInvalid() && !Tok.is(tok::eof)) {
 DS.SetRangeStart(Tok.getLocation());
-DS.SetRangeEnd(SourceLocation());
+DS.SetRangeEnd(Tok.getLocation());
   }
 
   bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D15994: Allow for unfinished #if blocks in preambles.

2016-12-07 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv updated this revision to Diff 80589.

https://reviews.llvm.org/D15994

Files:
  include/clang/Lex/Preprocessor.h
  include/clang/Lex/PreprocessorLexer.h
  include/clang/Lex/PreprocessorOptions.h
  include/clang/Serialization/ASTBitCodes.h
  lib/Frontend/ASTUnit.cpp
  lib/Lex/Lexer.cpp
  lib/Lex/PPLexerChange.cpp
  lib/Lex/Preprocessor.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTWriter.cpp
  test/Lexer/preamble.c
  test/Lexer/preamble2.c

Index: test/Lexer/preamble2.c
===
--- /dev/null
+++ test/Lexer/preamble2.c
@@ -0,0 +1,19 @@
+// Preamble detection test: header with an include guard.
+#ifndef HEADER_H
+#define HEADER_H
+#include "foo"
+int bar;
+#endif
+
+// This test checks for detection of the preamble of a file, which
+// includes all of the starting comments and #includes.
+
+// RUN: %clang_cc1 -print-preamble %s > %t
+// RUN: echo END. >> %t
+// RUN: FileCheck < %t %s
+
+// CHECK: // Preamble detection test: header with an include guard.
+// CHECK-NEXT: #ifndef HEADER_H
+// CHECK-NEXT: #define HEADER_H
+// CHECK-NEXT: #include "foo"
+// CHECK-NEXT: END.
Index: test/Lexer/preamble.c
===
--- test/Lexer/preamble.c
+++ test/Lexer/preamble.c
@@ -9,15 +9,12 @@
 #pragma unknown
 #endif
 #ifdef WIBBLE
-#include "honk"
-#else
-int foo();
+#include "foo"
+int bar;
 #endif
 
 // This test checks for detection of the preamble of a file, which
-// includes all of the starting comments and #includes. Note that any
-// changes to the preamble part of this file must be mirrored in
-// Inputs/preamble.txt, since we diff against it.
+// includes all of the starting comments and #includes.
 
 // RUN: %clang_cc1 -print-preamble %s > %t
 // RUN: echo END. >> %t
@@ -33,4 +30,6 @@
 // CHECK-NEXT: #endif
 // CHECK-NEXT: #pragma unknown
 // CHECK-NEXT: #endif
+// CHECK-NEXT: #ifdef WIBBLE
+// CHECK-NEXT: #include "foo"
 // CHECK-NEXT: END.
Index: lib/Serialization/ASTWriter.cpp
===
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -1071,6 +1071,7 @@
   RECORD(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES);
   RECORD(DELETE_EXPRS_TO_ANALYZE);
   RECORD(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH);
+  RECORD(PP_CONDITIONAL_STACK);
 
   // SourceManager Block.
   BLOCK(SOURCE_MANAGER_BLOCK);
@@ -2233,6 +2234,17 @@
 Stream.EmitRecord(PP_COUNTER_VALUE, Record);
   }
 
+  if (PP.isRecordingPreamble() && PP.hasRecordedPreamble()) {
+for (const auto  : PP.getPreambleConditionalStack()) {
+  AddSourceLocation(Cond.IfLoc, Record);
+  Record.push_back(Cond.WasSkipping);
+  Record.push_back(Cond.FoundNonSkip);
+  Record.push_back(Cond.FoundElse);
+}
+Stream.EmitRecord(PP_CONDITIONAL_STACK, Record);
+Record.clear();
+  }
+
   // Enter the preprocessor block.
   Stream.EnterSubblock(PREPROCESSOR_BLOCK_ID, 3);
 
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -2870,6 +2870,20 @@
   }
   break;
 
+case PP_CONDITIONAL_STACK:
+  if (!Record.empty()) {
+SmallVector ConditionalStack;
+for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) {
+  auto loc = ReadSourceLocation(F, Record, Idx);
+  bool WasSkipping = Record[Idx++];
+  bool FoundNonSkip = Record[Idx++];
+  bool FoundElse = Record[Idx++];
+  ConditionalStack.push_back({ loc, WasSkipping, FoundNonSkip, FoundElse });
+}
+PP.setReplayablePreambleConditionalStack(ConditionalStack);
+  }
+  break;
+
 case PP_COUNTER_VALUE:
   if (!Record.empty() && Listener)
 Listener->ReadCounter(F, Record[0]);
Index: lib/Lex/Preprocessor.cpp
===
--- lib/Lex/Preprocessor.cpp
+++ lib/Lex/Preprocessor.cpp
@@ -150,6 +150,9 @@
 Ident_GetExceptionInfo = Ident_GetExceptionCode = nullptr;
 Ident_AbnormalTermination = nullptr;
   }
+
+  if (this->PPOpts->PreambleGeneration)
+PreambleConditionalStack.startRecording();
 }
 
 Preprocessor::~Preprocessor() {
Index: lib/Lex/PPLexerChange.cpp
===
--- lib/Lex/PPLexerChange.cpp
+++ lib/Lex/PPLexerChange.cpp
@@ -46,6 +46,12 @@
   });
 }
 
+bool Preprocessor::isInPreamble() const {
+  if (IsFileLexer())
+return IncludeMacroStack.size() == 1;
+  return false;
+}
+
 /// getCurrentLexer - Return the current file lexer being lexed from.  Note
 /// that this ignores any potentially active macro expansions and _Pragma
 /// expansions going on at the time.
@@ -129,6 +135,11 @@
 Callbacks->FileChanged(CurLexer->getFileLoc(),
PPCallbacks::EnterFile, FileType);
   }
+
+  if 

[PATCH] D15994: Allow for unfinished #if blocks in preambles.

2016-12-07 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv marked 7 inline comments as done.
erikjv added inline comments.



Comment at: lib/Serialization/ASTReader.cpp:2816
+}
+PP.setReplayablePreambleConditionalStack(ConditionalStack);
+  }

rsmith wrote:
> Why can't we set the conditional stack on the `PPLexer` directly from here? 
> (Why do we need to store it separately?)
Because there is no PPLexer yet. The deserialization is kicked off by 
ASTUnit::CodeComplete in Act->BeginSourceFile, while the lexer is created in 
Act->Execute.


https://reviews.llvm.org/D15994



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits