[PATCH] D89790: [clangd] Add basic conflict detection for the rename.

2020-10-20 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: sammccall.
Herald added subscribers: usaxena95, kadircet, arphaman.
Herald added a project: clang.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

With this patch, we reject the rename if the new name would conflict with
any other decls in the decl context of the renamed decl.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D89790

Files:
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/unittests/RenameTests.cpp

Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -630,6 +630,44 @@
  class Foo {};
)cpp",
"no symbol", !HeaderFile, nullptr},
+
+  {R"cpp(
+namespace {
+int Conflict;
+int Va^r;
+}
+  )cpp",
+   "conflict", !HeaderFile, nullptr, "Conflict"},
+
+  {R"cpp(
+int Conflict;
+int Va^r;
+  )cpp",
+   "conflict", !HeaderFile, nullptr, "Conflict"},
+
+  {R"cpp(
+class Foo {
+  int Conflict;
+  int Va^r;
+};
+  )cpp",
+   "conflict", !HeaderFile, nullptr, "Conflict"},
+
+  {R"cpp(
+enum E {
+  Conflict,
+  Fo^o,
+};
+  )cpp",
+   "conflict", !HeaderFile, nullptr, "Conflict"},
+
+  {R"cpp(// FIXME: detecting local variables is not supported yet.
+void func() {
+  int Conflict;
+  int [[V^ar]];
+}
+  )cpp",
+   nullptr, !HeaderFile, nullptr, "Conflict"},
   };
 
   for (const auto& Case : Cases) {
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -254,6 +254,74 @@
   return Results;
 }
 
+// Lookup the declarations (if any) with the given Name in the given DC.
+NamedDecl *lookup(const ASTContext , const DeclContext *DC,
+  llvm::StringRef Name) {
+  const auto  = Ctx.Idents.get(Name);
+  DeclarationName LookupName();
+  DeclContextLookupResult LookupResult;
+  switch (DC->getDeclKind()) {
+  case Decl::TranslationUnit:
+  case Decl::Namespace:
+  case Decl::Record:
+  case Decl::Enum:
+  case Decl::CXXRecord:
+LookupResult = DC->lookup(LookupName);
+break;
+  default:
+break;
+  }
+  if (!LookupResult.empty())
+return LookupResult.front();
+  return nullptr;
+}
+
+struct InvalidName {
+  enum Kind {
+Keywords,
+Conflict,
+  };
+  Kind K;
+  std::string Details;
+};
+
+llvm::Error makeError(InvalidName Reason) {
+  auto Message = [](InvalidName Reason) {
+switch (Reason.K) {
+case InvalidName::Keywords:
+  return llvm::formatv("the chosen name \"{0}\" is a keyword",
+   Reason.Details);
+case InvalidName::Conflict:
+  return llvm::formatv("conflict with the symbol in {0}", Reason.Details);
+}
+llvm_unreachable("unhandled InvalidName kind");
+  };
+  return error("invalid name: {0}", Message(Reason));
+}
+
+// Check if we can rename the given RenameDecl into NewName.
+// Return details if the rename would produce a conflict.
+llvm::Optional checkName(const NamedDecl ,
+  llvm::StringRef NewName) {
+  auto  = RenameDecl.getASTContext();
+  if (isKeyword(NewName, ASTCtx.getLangOpts()))
+return InvalidName{InvalidName::Keywords, NewName.str()};
+  // FIXME: detecting function conflicts is tricky, e.g. we can have a same name
+  // for two overload functions.
+  if (RenameDecl.getKind() == Decl::Function)
+return llvm::None;
+  // Perform a lookup in the decl context of the RenameDecl, to find out any
+  // conflicts if we perform the rename.
+  // (!) DeclContext::lookup doesn't perform lookup local decls in a
+  // function-kind DeclContext.
+  auto *Conflict = lookup(ASTCtx, RenameDecl.getDeclContext(), NewName);
+  if (!Conflict)
+return llvm::None;
+  return InvalidName{
+  InvalidName::Conflict,
+  Conflict->getLocation().printToString(ASTCtx.getSourceManager())};
+}
+
 // AST-based rename, it renames all occurrences in the main file.
 llvm::Expected
 renameWithinFile(ParsedAST , const NamedDecl ,
@@ -476,11 +544,12 @@
 return makeError(ReasonToReject::NoSymbolFound);
   if (DeclsUnderCursor.size() > 1)
 return makeError(ReasonToReject::AmbiguousSymbol);
-  if (isKeyword(RInputs.NewName, AST.getLangOpts()))
-return makeError(ReasonToReject::RenameToKeywords);
-
   const auto  =
   llvm::cast(*(*DeclsUnderCursor.begin())->getCanonicalDecl());
+  auto Invalid = checkName(RenameDecl, RInputs.NewName);
+  if (Invalid)
+return makeError(*Invalid);
+
   auto Reject = renameable(RenameDecl, RInputs.MainFilePath, RInputs.Index,
  

[PATCH] D89783: [format] foo..h should be the main-header for foo..cc

2020-10-20 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
hokein marked an inline comment as done.
Closed by commit rG84048e234f8f: [format] foo.name.h should be the 
main-header for foo.name.cc (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89783

Files:
  clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
  clang/unittests/Format/SortIncludesTest.cpp


Index: clang/unittests/Format/SortIncludesTest.cpp
===
--- clang/unittests/Format/SortIncludesTest.cpp
+++ clang/unittests/Format/SortIncludesTest.cpp
@@ -151,7 +151,7 @@
   EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), 
"a.cc").empty());
 }
 
-TEST_F(SortIncludesTest, NoMainFileHeader) {
+TEST_F(SortIncludesTest, MainFileHeader) {
   std::string Code = "#include \n"
  "\n"
  "#include \"a/extra_action.proto.h\"\n";
@@ -159,6 +159,13 @@
   EXPECT_TRUE(
   sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a/extra_action.cc")
   .empty());
+
+  EXPECT_EQ("#include \"foo.bar.h\"\n"
+"\n"
+"#include \"a.h\"\n",
+sort("#include \"a.h\"\n"
+ "#include \"foo.bar.h\"\n",
+ "foo.bar.cc"));
 }
 
 TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) {
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -190,7 +190,6 @@
 IncludeCategoryManager::IncludeCategoryManager(const IncludeStyle ,
StringRef FileName)
 : Style(Style), FileName(FileName) {
-  FileStem = matchingStem(FileName);
   for (const auto  : Style.IncludeCategories)
 CategoryRegexs.emplace_back(Category.Regex, llvm::Regex::IgnoreCase);
   IsMainFile = FileName.endswith(".c") || FileName.endswith(".cc") ||
@@ -234,16 +233,30 @@
   if (!IncludeName.startswith("\""))
 return false;
 
+  IncludeName =
+  IncludeName.drop_front(1).drop_back(1); // remove the surrounding "" or 
<>
   // Not matchingStem: implementation files may have compound extensions but
   // headers may not.
-  StringRef HeaderStem =
-  llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(
-  1) /* remove the surrounding "" or <> */);
-  if (FileStem.startswith(HeaderStem) ||
-  FileStem.startswith_lower(HeaderStem)) {
+  StringRef HeaderStem = llvm::sys::path::stem(IncludeName);
+  StringRef FileStem = llvm::sys::path::stem(FileName); // foo.cu for foo.cu.cc
+  StringRef MatchingFileStem = matchingStem(FileName);  // foo for foo.cu.cc
+  // main-header examples:
+  //  1) foo.h => foo.cc
+  //  2) foo.h => foo.cu.cc
+  //  3) foo.proto.h => foo.proto.cc
+  //
+  // non-main-header examples:
+  //  1) foo.h => bar.cc
+  //  2) foo.proto.h => foo.cc
+  StringRef Matching;
+  if (MatchingFileStem.startswith_lower(HeaderStem))
+Matching = MatchingFileStem; // example 1), 2)
+  else if (FileStem.equals_lower(HeaderStem))
+Matching = FileStem; // example 3)
+  if (!Matching.empty()) {
 llvm::Regex MainIncludeRegex(HeaderStem.str() + Style.IncludeIsMainRegex,
  llvm::Regex::IgnoreCase);
-if (MainIncludeRegex.match(FileStem))
+if (MainIncludeRegex.match(Matching))
   return true;
   }
   return false;
Index: clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
===
--- clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
+++ clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -40,8 +40,6 @@
   const IncludeStyle Style;
   bool IsMainFile;
   std::string FileName;
-  // This refers to a substring in FileName.
-  StringRef FileStem;
   SmallVector CategoryRegexs;
 };
 


Index: clang/unittests/Format/SortIncludesTest.cpp
===
--- clang/unittests/Format/SortIncludesTest.cpp
+++ clang/unittests/Format/SortIncludesTest.cpp
@@ -151,7 +151,7 @@
   EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a.cc").empty());
 }
 
-TEST_F(SortIncludesTest, NoMainFileHeader) {
+TEST_F(SortIncludesTest, MainFileHeader) {
   std::string Code = "#include \n"
  "\n"
  "#include \"a/extra_action.proto.h\"\n";
@@ -159,6 +159,13 @@
   EXPECT_TRUE(
   sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a/extra_action.cc")
   .empty());
+
+  EXPECT_EQ("#include \"foo.bar.h\"\n"
+"\n"
+"#include \"a.h\"\n",
+sort("#include \"a.h\"\n"
+ "#include \"foo.bar.h\"\n",
+   

[PATCH] D89783: [format] foo..h should be the main-header for foo..cc

2020-10-20 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 299332.
hokein added a comment.

address comment.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89783

Files:
  clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
  clang/unittests/Format/SortIncludesTest.cpp


Index: clang/unittests/Format/SortIncludesTest.cpp
===
--- clang/unittests/Format/SortIncludesTest.cpp
+++ clang/unittests/Format/SortIncludesTest.cpp
@@ -151,7 +151,7 @@
   EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), 
"a.cc").empty());
 }
 
-TEST_F(SortIncludesTest, NoMainFileHeader) {
+TEST_F(SortIncludesTest, MainFileHeader) {
   std::string Code = "#include \n"
  "\n"
  "#include \"a/extra_action.proto.h\"\n";
@@ -159,6 +159,13 @@
   EXPECT_TRUE(
   sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a/extra_action.cc")
   .empty());
+
+  EXPECT_EQ("#include \"foo.bar.h\"\n"
+"\n"
+"#include \"a.h\"\n",
+sort("#include \"a.h\"\n"
+ "#include \"foo.bar.h\"\n",
+ "foo.bar.cc"));
 }
 
 TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) {
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -190,7 +190,6 @@
 IncludeCategoryManager::IncludeCategoryManager(const IncludeStyle ,
StringRef FileName)
 : Style(Style), FileName(FileName) {
-  FileStem = matchingStem(FileName);
   for (const auto  : Style.IncludeCategories)
 CategoryRegexs.emplace_back(Category.Regex, llvm::Regex::IgnoreCase);
   IsMainFile = FileName.endswith(".c") || FileName.endswith(".cc") ||
@@ -234,16 +233,30 @@
   if (!IncludeName.startswith("\""))
 return false;
 
+  IncludeName =
+  IncludeName.drop_front(1).drop_back(1); // remove the surrounding "" or 
<>
   // Not matchingStem: implementation files may have compound extensions but
   // headers may not.
-  StringRef HeaderStem =
-  llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(
-  1) /* remove the surrounding "" or <> */);
-  if (FileStem.startswith(HeaderStem) ||
-  FileStem.startswith_lower(HeaderStem)) {
+  StringRef HeaderStem = llvm::sys::path::stem(IncludeName);
+  StringRef FileStem = llvm::sys::path::stem(FileName); // foo.cu for foo.cu.cc
+  StringRef MatchingFileStem = matchingStem(FileName);  // foo for foo.cu.cc
+  // main-header examples:
+  //  1) foo.h => foo.cc
+  //  2) foo.h => foo.cu.cc
+  //  3) foo.proto.h => foo.proto.cc
+  //
+  // non-main-header examples:
+  //  1) foo.h => bar.cc
+  //  2) foo.proto.h => foo.cc
+  StringRef Matching;
+  if (MatchingFileStem.startswith_lower(HeaderStem))
+Matching = MatchingFileStem; // example 1), 2)
+  else if (FileStem.equals_lower(HeaderStem))
+Matching = FileStem; // example 3)
+  if (!Matching.empty()) {
 llvm::Regex MainIncludeRegex(HeaderStem.str() + Style.IncludeIsMainRegex,
  llvm::Regex::IgnoreCase);
-if (MainIncludeRegex.match(FileStem))
+if (MainIncludeRegex.match(Matching))
   return true;
   }
   return false;
Index: clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
===
--- clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
+++ clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -40,8 +40,6 @@
   const IncludeStyle Style;
   bool IsMainFile;
   std::string FileName;
-  // This refers to a substring in FileName.
-  StringRef FileStem;
   SmallVector CategoryRegexs;
 };
 


Index: clang/unittests/Format/SortIncludesTest.cpp
===
--- clang/unittests/Format/SortIncludesTest.cpp
+++ clang/unittests/Format/SortIncludesTest.cpp
@@ -151,7 +151,7 @@
   EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a.cc").empty());
 }
 
-TEST_F(SortIncludesTest, NoMainFileHeader) {
+TEST_F(SortIncludesTest, MainFileHeader) {
   std::string Code = "#include \n"
  "\n"
  "#include \"a/extra_action.proto.h\"\n";
@@ -159,6 +159,13 @@
   EXPECT_TRUE(
   sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a/extra_action.cc")
   .empty());
+
+  EXPECT_EQ("#include \"foo.bar.h\"\n"
+"\n"
+"#include \"a.h\"\n",
+sort("#include \"a.h\"\n"
+ "#include \"foo.bar.h\"\n",
+ "foo.bar.cc"));
 }
 
 TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) {
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp

[PATCH] D89743: Support Attr in DynTypedNode and ASTMatchers.

2020-10-20 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

Looks like there are some failing tests in premerge bots, e.g. 
https://reviews.llvm.org/harbormaster/unit/view/185822/

Also run `clang/docs/tools/dump_ast_matchers.py` script to update the 
`LibASTMatchersReference.html` file.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89743

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


[PATCH] D89783: [format] foo..h should be the main-header for foo..cc

2020-10-20 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: adamcz.
Herald added a project: clang.
hokein requested review of this revision.

This fixes a regression introduced in https://reviews.llvm.org/D88640.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D89783

Files:
  clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
  clang/unittests/Format/SortIncludesTest.cpp


Index: clang/unittests/Format/SortIncludesTest.cpp
===
--- clang/unittests/Format/SortIncludesTest.cpp
+++ clang/unittests/Format/SortIncludesTest.cpp
@@ -151,7 +151,7 @@
   EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), 
"a.cc").empty());
 }
 
-TEST_F(SortIncludesTest, NoMainFileHeader) {
+TEST_F(SortIncludesTest, MainFileHeader) {
   std::string Code = "#include \n"
  "\n"
  "#include \"a/extra_action.proto.h\"\n";
@@ -159,6 +159,13 @@
   EXPECT_TRUE(
   sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a/extra_action.cc")
   .empty());
+
+  EXPECT_EQ("#include \"foo.bar.h\"\n"
+"\n"
+"#include \"a.h\"\n",
+sort("#include \"a.h\"\n"
+ "#include \"foo.bar.h\"\n",
+ "foo.bar.cc"));
 }
 
 TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) {
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -190,7 +190,6 @@
 IncludeCategoryManager::IncludeCategoryManager(const IncludeStyle ,
StringRef FileName)
 : Style(Style), FileName(FileName) {
-  FileStem = matchingStem(FileName);
   for (const auto  : Style.IncludeCategories)
 CategoryRegexs.emplace_back(Category.Regex, llvm::Regex::IgnoreCase);
   IsMainFile = FileName.endswith(".c") || FileName.endswith(".cc") ||
@@ -234,16 +233,30 @@
   if (!IncludeName.startswith("\""))
 return false;
 
+  IncludeName =
+  IncludeName.drop_front(1).drop_back(1); // remove the surrounding "" or 
<>
   // Not matchingStem: implementation files may have compound extensions but
   // headers may not.
-  StringRef HeaderStem =
-  llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(
-  1) /* remove the surrounding "" or <> */);
-  if (FileStem.startswith(HeaderStem) ||
-  FileStem.startswith_lower(HeaderStem)) {
+  StringRef HeaderStem = llvm::sys::path::stem(IncludeName);
+  StringRef FileStem = llvm::sys::path::stem(FileName); // foo.cu for foo.cu.cc
+  StringRef MatchingFileStem = matchingStem(FileName);  // foo for foo.cu.cc
+  // main-header examples:
+  //   1) foo.h => foo.cc
+  //   2) foo.h => foo..cc (e.g. foo.cu.cc)
+  //   3) foo..h => foo..cc
+  //
+  // non-main-header examples:
+  //  foo.proto.h => foo.cc
+  //  foo.h => bar.cc
+  StringRef Matching;
+  if (MatchingFileStem.startswith_lower(HeaderStem))
+Matching = MatchingFileStem; // example 1), 2)
+  else if (FileStem.equals_lower(HeaderStem))
+Matching = FileStem; // example 3)
+  if (!Matching.empty()) {
 llvm::Regex MainIncludeRegex(HeaderStem.str() + Style.IncludeIsMainRegex,
  llvm::Regex::IgnoreCase);
-if (MainIncludeRegex.match(FileStem))
+if (MainIncludeRegex.match(Matching))
   return true;
   }
   return false;
Index: clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
===
--- clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
+++ clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -40,8 +40,6 @@
   const IncludeStyle Style;
   bool IsMainFile;
   std::string FileName;
-  // This refers to a substring in FileName.
-  StringRef FileStem;
   SmallVector CategoryRegexs;
 };
 


Index: clang/unittests/Format/SortIncludesTest.cpp
===
--- clang/unittests/Format/SortIncludesTest.cpp
+++ clang/unittests/Format/SortIncludesTest.cpp
@@ -151,7 +151,7 @@
   EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a.cc").empty());
 }
 
-TEST_F(SortIncludesTest, NoMainFileHeader) {
+TEST_F(SortIncludesTest, MainFileHeader) {
   std::string Code = "#include \n"
  "\n"
  "#include \"a/extra_action.proto.h\"\n";
@@ -159,6 +159,13 @@
   EXPECT_TRUE(
   sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a/extra_action.cc")
   .empty());
+
+  EXPECT_EQ("#include \"foo.bar.h\"\n"
+"\n"
+"#include \"a.h\"\n",
+sort("#include \"a.h\"\n"
+ "#include \"foo.bar.h\"\n",
+ "foo.bar.cc"));
 }
 
 TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) {
Index: 

[PATCH] D88640: [Format] Don't treat compound extension headers (foo.proto.h) as foo.cc main file.

2020-10-20 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In D88640#2339349 , @rupprecht wrote:

> It looks like this fix caused a different regression in not accepting 
> `name..h` as the main header for `name..cc`, e.g.:
>
>   $ cat /tmp/foo.bar.cc
>   #include "a.h"
>   #include "z.h"
>   #include "foo.bar.h"
>   
>   $ clang-format /tmp/foo.bar.cc  # Before
>   #include "foo.bar.h"
>   
>   #include "a.h"
>   #include "z.h"
>   
>   $ clang-format /tmp/foo.bar.cc  # After
>   #include "a.h"
>   #include "foo.bar.h"
>   #include "z.h"

oh, sorry for the regression. Will try to fix that, thanks for the example!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88640

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


[PATCH] D89300: [clang-rename] Fix rename on variable templates.

2020-10-19 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG1e32df2f91f1: [clang-rename] Fix rename on variable 
templates. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89300

Files:
  clang/include/clang/AST/DeclTemplate.h
  clang/lib/AST/DeclTemplate.cpp
  clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
  clang/test/clang-rename/VariableTemplate.cpp

Index: clang/test/clang-rename/VariableTemplate.cpp
===
--- /dev/null
+++ clang/test/clang-rename/VariableTemplate.cpp
@@ -0,0 +1,32 @@
+template 
+bool Foo = true;  // CHECK: bool Bar = true;
+
+// explicit template specialization
+template <>
+bool Foo = false; // CHECK: bool Bar = false;
+
+// partial template specialization
+template 
+bool Foo = false; // bool Bar = false;
+
+void k() {
+  // ref to the explicit template specialization
+  Foo;   // CHECK: Bar;
+  // ref to the primary template.
+  Foo;   // CHECK: Bar;
+}
+
+
+// Test 1.
+// RUN: clang-rename -offset=34 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+// Test 2.
+// RUN: clang-rename -offset=128 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+// Test 3.
+// RUN: clang-rename -offset=248 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+// Test 4.
+// RUN: clang-rename -offset=357 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+// Test 5.
+// RUN: clang-rename -offset=431 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+
+// To find offsets after modifying the file, use:
+//   grep -Ubo 'Foo.*' 
Index: clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
===
--- clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -86,6 +86,16 @@
 handleFunctionTemplateDecl(FTD);
 } else if (const auto *FD = dyn_cast(FoundDecl)) {
   handleFunctionTemplateDecl(FD);
+} else if (const auto *VTD = dyn_cast(FoundDecl)) {
+  handleVarTemplateDecl(VTD);
+} else if (const auto *VD =
+   dyn_cast(FoundDecl)) {
+  // FIXME: figure out why FoundDecl can be a VarTemplateSpecializationDecl.
+  handleVarTemplateDecl(VD->getSpecializedTemplate());
+} else if (const auto *VD = dyn_cast(FoundDecl)) {
+  USRSet.insert(getUSRForDecl(VD));
+  if (const auto *VTD = VD->getDescribedVarTemplate())
+handleVarTemplateDecl(VTD);
 } else {
   USRSet.insert(getUSRForDecl(FoundDecl));
 }
@@ -132,6 +142,19 @@
   USRSet.insert(getUSRForDecl(S));
   }
 
+  void handleVarTemplateDecl(const VarTemplateDecl *VTD) {
+USRSet.insert(getUSRForDecl(VTD));
+USRSet.insert(getUSRForDecl(VTD->getTemplatedDecl()));
+llvm::for_each(VTD->specializations(), [&](const auto *Spec) {
+  USRSet.insert(getUSRForDecl(Spec));
+});
+SmallVector PartialSpecs;
+VTD->getPartialSpecializations(PartialSpecs);
+llvm::for_each(PartialSpecs, [&](const auto *Spec) {
+  USRSet.insert(getUSRForDecl(Spec));
+});
+  }
+
   void addUSRsOfCtorDtors(const CXXRecordDecl *RD) {
 const auto* RecordDecl = RD->getDefinition();
 
Index: clang/lib/AST/DeclTemplate.cpp
===
--- clang/lib/AST/DeclTemplate.cpp
+++ clang/lib/AST/DeclTemplate.cpp
@@ -1142,7 +1142,7 @@
 }
 
 llvm::FoldingSetVector &
-VarTemplateDecl::getPartialSpecializations() {
+VarTemplateDecl::getPartialSpecializations() const {
   LoadLazySpecializations();
   return getCommonPtr()->PartialSpecializations;
 }
@@ -1198,7 +1198,7 @@
 }
 
 void VarTemplateDecl::getPartialSpecializations(
-SmallVectorImpl ) {
+SmallVectorImpl ) const {
   llvm::FoldingSetVector  =
   getPartialSpecializations();
   PS.clear();
Index: clang/include/clang/AST/DeclTemplate.h
===
--- clang/include/clang/AST/DeclTemplate.h
+++ clang/include/clang/AST/DeclTemplate.h
@@ -3095,7 +3095,7 @@
   /// Retrieve the set of partial specializations of this class
   /// template.
   llvm::FoldingSetVector &
-  getPartialSpecializations();
+  getPartialSpecializations() const;
 
   VarTemplateDecl(ASTContext , DeclContext *DC, SourceLocation L,
   DeclarationName Name, TemplateParameterList *Params,
@@ -3191,7 +3191,7 @@
 
   /// Retrieve the partial specializations as an ordered list.
   void getPartialSpecializations(
-  SmallVectorImpl );
+  SmallVectorImpl ) const;
 
   /// Find a variable template partial specialization which was
   /// instantiated
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D89221: [clang-rename] Fix rename on function template specializations.

2020-10-19 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG45a15dc682c0: [clang-rename] Fix rename on function template 
specializations. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89221

Files:
  clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
  clang/test/clang-rename/FunctionTemplate.cpp


Index: clang/test/clang-rename/FunctionTemplate.cpp
===
--- /dev/null
+++ clang/test/clang-rename/FunctionTemplate.cpp
@@ -0,0 +1,19 @@
+template 
+void Foo(T t); // CHECK: void Bar(T t);
+
+template <>
+void Foo(int a); // CHECK: void Bar(int a);
+
+void test() {
+  Foo(1); // CHECK: Bar(1);
+}
+
+// Test 1.
+// RUN: clang-rename -offset=28 -new-name=Bar %s -- | sed 's,//.*,,' | 
FileCheck %s
+// Test 2.
+// RUN: clang-rename -offset=81 -new-name=Bar %s -- | sed 's,//.*,,' | 
FileCheck %s
+// Test 3.
+// RUN: clang-rename -offset=137 -new-name=Bar %s -- | sed 's,//.*,,' | 
FileCheck %s
+
+// To find offsets after modifying the file, use:
+//   grep -Ubo 'Foo.*' 
Index: clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
===
--- clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -80,6 +80,12 @@
 } else if (const auto *TemplateDecl =
dyn_cast(FoundDecl)) {
   handleClassTemplateDecl(TemplateDecl);
+} else if (const auto *FD = dyn_cast(FoundDecl)) {
+  USRSet.insert(getUSRForDecl(FD));
+  if (const auto *FTD = FD->getPrimaryTemplate())
+handleFunctionTemplateDecl(FTD);
+} else if (const auto *FD = dyn_cast(FoundDecl)) {
+  handleFunctionTemplateDecl(FD);
 } else {
   USRSet.insert(getUSRForDecl(FoundDecl));
 }
@@ -119,6 +125,13 @@
 addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
   }
 
+  void handleFunctionTemplateDecl(const FunctionTemplateDecl *FTD) {
+USRSet.insert(getUSRForDecl(FTD));
+USRSet.insert(getUSRForDecl(FTD->getTemplatedDecl()));
+for (const auto *S : FTD->specializations())
+  USRSet.insert(getUSRForDecl(S));
+  }
+
   void addUSRsOfCtorDtors(const CXXRecordDecl *RD) {
 const auto* RecordDecl = RD->getDefinition();
 


Index: clang/test/clang-rename/FunctionTemplate.cpp
===
--- /dev/null
+++ clang/test/clang-rename/FunctionTemplate.cpp
@@ -0,0 +1,19 @@
+template 
+void Foo(T t); // CHECK: void Bar(T t);
+
+template <>
+void Foo(int a); // CHECK: void Bar(int a);
+
+void test() {
+  Foo(1); // CHECK: Bar(1);
+}
+
+// Test 1.
+// RUN: clang-rename -offset=28 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+// Test 2.
+// RUN: clang-rename -offset=81 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+// Test 3.
+// RUN: clang-rename -offset=137 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+
+// To find offsets after modifying the file, use:
+//   grep -Ubo 'Foo.*' 
Index: clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
===
--- clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -80,6 +80,12 @@
 } else if (const auto *TemplateDecl =
dyn_cast(FoundDecl)) {
   handleClassTemplateDecl(TemplateDecl);
+} else if (const auto *FD = dyn_cast(FoundDecl)) {
+  USRSet.insert(getUSRForDecl(FD));
+  if (const auto *FTD = FD->getPrimaryTemplate())
+handleFunctionTemplateDecl(FTD);
+} else if (const auto *FD = dyn_cast(FoundDecl)) {
+  handleFunctionTemplateDecl(FD);
 } else {
   USRSet.insert(getUSRForDecl(FoundDecl));
 }
@@ -119,6 +125,13 @@
 addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
   }
 
+  void handleFunctionTemplateDecl(const FunctionTemplateDecl *FTD) {
+USRSet.insert(getUSRForDecl(FTD));
+USRSet.insert(getUSRForDecl(FTD->getTemplatedDecl()));
+for (const auto *S : FTD->specializations())
+  USRSet.insert(getUSRForDecl(S));
+  }
+
   void addUSRsOfCtorDtors(const CXXRecordDecl *RD) {
 const auto* RecordDecl = RD->getDefinition();
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D89220: [clang-rename] Simplify the code of handling class paritial specializations, NFC.

2020-10-14 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp:119
+llvm::for_each(PartialSpecs,
+   [&](const auto *Spec) { addUSRsOfCtorDtors(Spec); });
 addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());

danilaml wrote:
> Btw, this breaks on GCC <= 7.1, due to 
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67274
> Workaround is to use `this->`.
oh, thanks for spotting it!

Fixed in e6b4179c5d282905a8ad17c57153b991c42d1126, instead of adding `this->`, 
I reverted it to the for-range loop. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89220

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


[PATCH] D89233: [clangd] Refine recoveryAST flags in clangd

2020-10-14 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG3fcca804b291: [clangd] Refine recoveryAST flags in clangd 
(authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89233

Files:
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Compiler.cpp
  clang-tools-extra/clangd/tool/ClangdMain.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.cpp
  clang-tools-extra/clangd/unittests/TestTU.cpp

Index: clang-tools-extra/clangd/unittests/TestTU.cpp
===
--- clang-tools-extra/clangd/unittests/TestTU.cpp
+++ clang-tools-extra/clangd/unittests/TestTU.cpp
@@ -59,8 +59,6 @@
 FS.OverlayRealFileSystemForModules = true;
   Inputs.TFS = 
   Inputs.Opts = ParseOptions();
-  Inputs.Opts.BuildRecoveryAST = true;
-  Inputs.Opts.PreserveRecoveryASTType = true;
   Inputs.Opts.ClangTidyOpts.Checks = ClangTidyChecks;
   Inputs.Opts.ClangTidyOpts.WarningsAsErrors = ClangTidyWarningsAsErrors;
   Inputs.Index = ExternalIndex;
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -148,6 +148,17 @@
   EXPECT_DECLS("LabelStmt", "label:");
 }
 
+TEST_F(TargetDeclTest, RecoveryForC) {
+  Flags = {"-xc", "-Xclang", "-frecovery-ast"};
+  Code = R"cpp(
+// error-ok: testing behavior on broken code
+// int f();
+int f(int);
+int x = [[f]]();
+  )cpp";
+  EXPECT_DECLS("DeclRefExpr", "int f(int)");
+}
+
 TEST_F(TargetDeclTest, Recovery) {
   Code = R"cpp(
 // error-ok: testing behavior on broken code
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -111,8 +111,6 @@
 
   MockFS FS;
   auto Inputs = TU.inputs(FS);
-  Inputs.Opts.BuildRecoveryAST = true;
-  Inputs.Opts.PreserveRecoveryASTType = true;
   IgnoreDiagnostics Diags;
   auto CI = buildCompilerInvocation(Inputs, Diags);
   if (!CI) {
@@ -1100,8 +1098,6 @@
   MockFS FS;
   auto Inputs = TU.inputs(FS);
   Inputs.Index = Index.get();
-  Inputs.Opts.BuildRecoveryAST = true;
-  Inputs.Opts.PreserveRecoveryASTType = true;
   IgnoreDiagnostics Diags;
   auto CI = buildCompilerInvocation(Inputs, Diags);
   if (!CI) {
Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -310,7 +310,7 @@
 opt RecoveryAST{
 "recovery-ast",
 cat(Features),
-desc("Preserve expressions in AST for broken code (C++ only)."),
+desc("Preserve expressions in AST for broken code."),
 init(ClangdServer::Options().BuildRecoveryAST),
 };
 
Index: clang-tools-extra/clangd/Compiler.cpp
===
--- clang-tools-extra/clangd/Compiler.cpp
+++ clang-tools-extra/clangd/Compiler.cpp
@@ -81,11 +81,11 @@
   // Don't crash on `#pragma clang __debug parser_crash`
   CI->getPreprocessorOpts().DisablePragmaDebugCrash = true;
 
-  // Recovery expression currently only works for C++.
-  if (CI->getLangOpts()->CPlusPlus) {
-CI->getLangOpts()->RecoveryAST = Inputs.Opts.BuildRecoveryAST;
-CI->getLangOpts()->RecoveryASTType = Inputs.Opts.PreserveRecoveryASTType;
-  }
+  if (Inputs.Opts.BuildRecoveryAST)
+CI->getLangOpts()->RecoveryAST = true;
+  if (Inputs.Opts.PreserveRecoveryASTType)
+CI->getLangOpts()->RecoveryASTType = true;
+
   return CI;
 }
 
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -128,11 +128,13 @@
 /// enabled.
 ClangTidyOptionsBuilder GetClangTidyOptions;
 
-/// If true, turn on the `-frecovery-ast` clang flag.
-bool BuildRecoveryAST = true;
+/// If true, force -frecovery-ast flag.
+/// If false, respect the value in clang.
+bool BuildRecoveryAST = false;
 
-/// If true, turn on the `-frecovery-ast-type` clang flag.
-bool PreserveRecoveryASTType = true;
+/// If true, force -frecovery-ast-type flag.
+/// If false, respect the value in clang.
+bool PreserveRecoveryASTType = false;
 
 /// Clangd's workspace root. Relevant for "workspace" operations not bound
 /// to a particular file.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org

[PATCH] D89233: [clangd] Refine recoveryAST flags in clangd

2020-10-14 Thread Haojian Wu via Phabricator via cfe-commits
hokein marked an inline comment as done.
hokein added inline comments.



Comment at: clang-tools-extra/clangd/Compiler.cpp:84
 
-  // Recovery expression currently only works for C++.
-  if (CI->getLangOpts()->CPlusPlus) {
-CI->getLangOpts()->RecoveryAST = Inputs.Opts.BuildRecoveryAST;
-CI->getLangOpts()->RecoveryASTType = Inputs.Opts.PreserveRecoveryASTType;
-  }
+  if (Inputs.Opts.BuildRecoveryAST)
+CI->getLangOpts()->RecoveryAST = true;

sammccall wrote:
> I don't have any problem with the changes to the flags, but we can also do 
> experiments just with config now:
> 
> ```
> CompileFlags:
>   Add: [-Xclang, -frecovery-ast]
> ```
> 
> in ~/.config/clangd/config.yaml
this sounds a new idea, but it looks like our internal client doesn't fully 
support config (yet?). 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89233

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


[PATCH] D89233: [clangd] Refine recoveryAST flags in clangd

2020-10-14 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 298116.
hokein added a comment.

address comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89233

Files:
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Compiler.cpp
  clang-tools-extra/clangd/tool/ClangdMain.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.cpp
  clang-tools-extra/clangd/unittests/TestTU.cpp

Index: clang-tools-extra/clangd/unittests/TestTU.cpp
===
--- clang-tools-extra/clangd/unittests/TestTU.cpp
+++ clang-tools-extra/clangd/unittests/TestTU.cpp
@@ -59,8 +59,6 @@
 FS.OverlayRealFileSystemForModules = true;
   Inputs.TFS = 
   Inputs.Opts = ParseOptions();
-  Inputs.Opts.BuildRecoveryAST = true;
-  Inputs.Opts.PreserveRecoveryASTType = true;
   Inputs.Opts.ClangTidyOpts.Checks = ClangTidyChecks;
   Inputs.Opts.ClangTidyOpts.WarningsAsErrors = ClangTidyWarningsAsErrors;
   Inputs.Index = ExternalIndex;
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -148,6 +148,17 @@
   EXPECT_DECLS("LabelStmt", "label:");
 }
 
+TEST_F(TargetDeclTest, RecoveryForC) {
+  Flags = {"-xc", "-Xclang", "-frecovery-ast"};
+  Code = R"cpp(
+// error-ok: testing behavior on broken code
+// int f();
+int f(int);
+int x = [[f]]();
+  )cpp";
+  EXPECT_DECLS("DeclRefExpr", "int f(int)");
+}
+
 TEST_F(TargetDeclTest, Recovery) {
   Code = R"cpp(
 // error-ok: testing behavior on broken code
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -111,8 +111,6 @@
 
   MockFS FS;
   auto Inputs = TU.inputs(FS);
-  Inputs.Opts.BuildRecoveryAST = true;
-  Inputs.Opts.PreserveRecoveryASTType = true;
   IgnoreDiagnostics Diags;
   auto CI = buildCompilerInvocation(Inputs, Diags);
   if (!CI) {
@@ -1100,8 +1098,6 @@
   MockFS FS;
   auto Inputs = TU.inputs(FS);
   Inputs.Index = Index.get();
-  Inputs.Opts.BuildRecoveryAST = true;
-  Inputs.Opts.PreserveRecoveryASTType = true;
   IgnoreDiagnostics Diags;
   auto CI = buildCompilerInvocation(Inputs, Diags);
   if (!CI) {
Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -310,7 +310,7 @@
 opt RecoveryAST{
 "recovery-ast",
 cat(Features),
-desc("Preserve expressions in AST for broken code (C++ only)."),
+desc("Preserve expressions in AST for broken code."),
 init(ClangdServer::Options().BuildRecoveryAST),
 };
 
Index: clang-tools-extra/clangd/Compiler.cpp
===
--- clang-tools-extra/clangd/Compiler.cpp
+++ clang-tools-extra/clangd/Compiler.cpp
@@ -81,11 +81,11 @@
   // Don't crash on `#pragma clang __debug parser_crash`
   CI->getPreprocessorOpts().DisablePragmaDebugCrash = true;
 
-  // Recovery expression currently only works for C++.
-  if (CI->getLangOpts()->CPlusPlus) {
-CI->getLangOpts()->RecoveryAST = Inputs.Opts.BuildRecoveryAST;
-CI->getLangOpts()->RecoveryASTType = Inputs.Opts.PreserveRecoveryASTType;
-  }
+  if (Inputs.Opts.BuildRecoveryAST)
+CI->getLangOpts()->RecoveryAST = true;
+  if (Inputs.Opts.PreserveRecoveryASTType)
+CI->getLangOpts()->RecoveryASTType = true;
+
   return CI;
 }
 
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -128,11 +128,13 @@
 /// enabled.
 ClangTidyOptionsBuilder GetClangTidyOptions;
 
-/// If true, turn on the `-frecovery-ast` clang flag.
-bool BuildRecoveryAST = true;
+/// If true, force -frecovery-ast flag.
+/// If false, respect the value in clang.
+bool BuildRecoveryAST = false;
 
-/// If true, turn on the `-frecovery-ast-type` clang flag.
-bool PreserveRecoveryASTType = true;
+/// If true, force -frecovery-ast-type flag.
+/// If false, respect the value in clang.
+bool PreserveRecoveryASTType = false;
 
 /// Clangd's workspace root. Relevant for "workspace" operations not bound
 /// to a particular file.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D89300: [clang-rename] Fix rename on variable templates.

2020-10-14 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang/include/clang/AST/DeclTemplate.h:3098
   llvm::FoldingSetVector &
-  getPartialSpecializations();
+  getPartialSpecializations() const;
 

kbobyrev wrote:
> I believe these are from https://reviews.llvm.org/D89221, so probably rebase 
> on top of it?
I think you mean the change in D89220? they are different, this is for 
`VarTemplateDecl`, while that one is for `ClassTemplateDecl`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89300

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


[PATCH] D89221: [clang-rename] Fix rename on function template specializations.

2020-10-14 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

@kbobyrev you may miss this patch, this is a separate patch from D89300 
.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89221

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


[PATCH] D89221: [clang-rename] Fix rename on function template specializations.

2020-10-14 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 298061.
hokein added a comment.

update


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89221

Files:
  clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
  clang/test/clang-rename/FunctionTemplate.cpp


Index: clang/test/clang-rename/FunctionTemplate.cpp
===
--- /dev/null
+++ clang/test/clang-rename/FunctionTemplate.cpp
@@ -0,0 +1,19 @@
+template 
+void Foo(T t); // CHECK: void Bar(T t);
+
+template <>
+void Foo(int a); // CHECK: void Bar(int a);
+
+void test() {
+  Foo(1); // CHECK: Bar(1);
+}
+
+// Test 1.
+// RUN: clang-rename -offset=28 -new-name=Bar %s -- | sed 's,//.*,,' | 
FileCheck %s
+// Test 2.
+// RUN: clang-rename -offset=81 -new-name=Bar %s -- | sed 's,//.*,,' | 
FileCheck %s
+// Test 3.
+// RUN: clang-rename -offset=137 -new-name=Bar %s -- | sed 's,//.*,,' | 
FileCheck %s
+
+// To find offsets after modifying the file, use:
+//   grep -Ubo 'Foo.*' 
Index: clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
===
--- clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -81,6 +81,12 @@
 } else if (const auto *TemplateDecl =
dyn_cast(FoundDecl)) {
   handleClassTemplateDecl(TemplateDecl);
+} else if (const auto *FD = dyn_cast(FoundDecl)) {
+  USRSet.insert(getUSRForDecl(FD));
+  if (const auto *FTD = FD->getPrimaryTemplate())
+handleFunctionTemplateDecl(FTD);
+} else if (const auto *FD = dyn_cast(FoundDecl)) {
+  handleFunctionTemplateDecl(FD);
 } else {
   USRSet.insert(getUSRForDecl(FoundDecl));
 }
@@ -120,6 +126,13 @@
 addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
   }
 
+  void handleFunctionTemplateDecl(const FunctionTemplateDecl *FTD) {
+USRSet.insert(getUSRForDecl(FTD));
+USRSet.insert(getUSRForDecl(FTD->getTemplatedDecl()));
+for (const auto *S : FTD->specializations())
+  USRSet.insert(getUSRForDecl(S));
+  }
+
   void addUSRsOfCtorDtors(const CXXRecordDecl *RD) {
 const auto* RecordDecl = RD->getDefinition();
 


Index: clang/test/clang-rename/FunctionTemplate.cpp
===
--- /dev/null
+++ clang/test/clang-rename/FunctionTemplate.cpp
@@ -0,0 +1,19 @@
+template 
+void Foo(T t); // CHECK: void Bar(T t);
+
+template <>
+void Foo(int a); // CHECK: void Bar(int a);
+
+void test() {
+  Foo(1); // CHECK: Bar(1);
+}
+
+// Test 1.
+// RUN: clang-rename -offset=28 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+// Test 2.
+// RUN: clang-rename -offset=81 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+// Test 3.
+// RUN: clang-rename -offset=137 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+
+// To find offsets after modifying the file, use:
+//   grep -Ubo 'Foo.*' 
Index: clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
===
--- clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -81,6 +81,12 @@
 } else if (const auto *TemplateDecl =
dyn_cast(FoundDecl)) {
   handleClassTemplateDecl(TemplateDecl);
+} else if (const auto *FD = dyn_cast(FoundDecl)) {
+  USRSet.insert(getUSRForDecl(FD));
+  if (const auto *FTD = FD->getPrimaryTemplate())
+handleFunctionTemplateDecl(FTD);
+} else if (const auto *FD = dyn_cast(FoundDecl)) {
+  handleFunctionTemplateDecl(FD);
 } else {
   USRSet.insert(getUSRForDecl(FoundDecl));
 }
@@ -120,6 +126,13 @@
 addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
   }
 
+  void handleFunctionTemplateDecl(const FunctionTemplateDecl *FTD) {
+USRSet.insert(getUSRForDecl(FTD));
+USRSet.insert(getUSRForDecl(FTD->getTemplatedDecl()));
+for (const auto *S : FTD->specializations())
+  USRSet.insert(getUSRForDecl(S));
+  }
+
   void addUSRsOfCtorDtors(const CXXRecordDecl *RD) {
 const auto* RecordDecl = RD->getDefinition();
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D89220: [clang-rename] Simplify the code of handling class paritial specializations, NFC.

2020-10-14 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG27c691cf62a9: [clang-rename] Simplify the code of handling 
class paritial specializations… (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89220

Files:
  clang/include/clang/AST/DeclTemplate.h
  clang/lib/AST/DeclTemplate.cpp
  clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp


Index: clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
===
--- clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -27,6 +27,7 @@
 #include "clang/Tooling/Refactoring.h"
 #include "clang/Tooling/Refactoring/Rename/USRFinder.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/STLExtras.h"
 
 #include 
 #include 
@@ -96,12 +97,6 @@
 return true;
   }
 
-  bool VisitClassTemplatePartialSpecializationDecl(
-  const ClassTemplatePartialSpecializationDecl *PartialSpec) {
-PartialSpecs.push_back(PartialSpec);
-return true;
-  }
-
 private:
   void handleCXXRecordDecl(const CXXRecordDecl *RecordDecl) {
 if (!RecordDecl->getDefinition()) {
@@ -118,11 +113,10 @@
   void handleClassTemplateDecl(const ClassTemplateDecl *TemplateDecl) {
 for (const auto *Specialization : TemplateDecl->specializations())
   addUSRsOfCtorDtors(Specialization);
-
-for (const auto *PartialSpec : PartialSpecs) {
-  if (PartialSpec->getSpecializedTemplate() == TemplateDecl)
-addUSRsOfCtorDtors(PartialSpec);
-}
+SmallVector PartialSpecs;
+TemplateDecl->getPartialSpecializations(PartialSpecs);
+llvm::for_each(PartialSpecs,
+   [&](const auto *Spec) { addUSRsOfCtorDtors(Spec); });
 addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
   }
 
@@ -184,7 +178,6 @@
   std::set USRSet;
   std::vector OverriddenMethods;
   std::vector InstantiatedMethods;
-  std::vector PartialSpecs;
 };
 } // namespace
 
Index: clang/lib/AST/DeclTemplate.cpp
===
--- clang/lib/AST/DeclTemplate.cpp
+++ clang/lib/AST/DeclTemplate.cpp
@@ -440,7 +440,7 @@
 }
 
 llvm::FoldingSetVector &
-ClassTemplateDecl::getPartialSpecializations() {
+ClassTemplateDecl::getPartialSpecializations() const {
   LoadLazySpecializations();
   return getCommonPtr()->PartialSpecializations;
 }
@@ -528,7 +528,7 @@
 }
 
 void ClassTemplateDecl::getPartialSpecializations(
-  SmallVectorImpl ) {
+SmallVectorImpl ) const {
   llvm::FoldingSetVector 
 = getPartialSpecializations();
   PS.clear();
Index: clang/include/clang/AST/DeclTemplate.h
===
--- clang/include/clang/AST/DeclTemplate.h
+++ clang/include/clang/AST/DeclTemplate.h
@@ -2266,7 +2266,7 @@
   /// Retrieve the set of partial specializations of this class
   /// template.
   llvm::FoldingSetVector &
-  getPartialSpecializations();
+  getPartialSpecializations() const;
 
   ClassTemplateDecl(ASTContext , DeclContext *DC, SourceLocation L,
 DeclarationName Name, TemplateParameterList *Params,
@@ -2363,7 +2363,7 @@
 
   /// Retrieve the partial specializations as an ordered list.
   void getPartialSpecializations(
-  SmallVectorImpl );
+  SmallVectorImpl ) const;
 
   /// Find a class template partial specialization with the given
   /// type T.


Index: clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
===
--- clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -27,6 +27,7 @@
 #include "clang/Tooling/Refactoring.h"
 #include "clang/Tooling/Refactoring/Rename/USRFinder.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/STLExtras.h"
 
 #include 
 #include 
@@ -96,12 +97,6 @@
 return true;
   }
 
-  bool VisitClassTemplatePartialSpecializationDecl(
-  const ClassTemplatePartialSpecializationDecl *PartialSpec) {
-PartialSpecs.push_back(PartialSpec);
-return true;
-  }
-
 private:
   void handleCXXRecordDecl(const CXXRecordDecl *RecordDecl) {
 if (!RecordDecl->getDefinition()) {
@@ -118,11 +113,10 @@
   void handleClassTemplateDecl(const ClassTemplateDecl *TemplateDecl) {
 for (const auto *Specialization : TemplateDecl->specializations())
   addUSRsOfCtorDtors(Specialization);
-
-for (const auto *PartialSpec : PartialSpecs) {
-  if (PartialSpec->getSpecializedTemplate() == TemplateDecl)
-addUSRsOfCtorDtors(PartialSpec);
-}
+SmallVector PartialSpecs;
+TemplateDecl->getPartialSpecializations(PartialSpecs);
+llvm::for_each(PartialSpecs,
+   [&](const auto *Spec) { addUSRsOfCtorDtors(Spec); 

[PATCH] D89300: [clang-rename] Fix rename on variable templates.

2020-10-13 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: kbobyrev.
Herald added a project: clang.
hokein requested review of this revision.

This patch adds support for renaming variable templates.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D89300

Files:
  clang/include/clang/AST/DeclTemplate.h
  clang/lib/AST/DeclTemplate.cpp
  clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
  clang/test/clang-rename/VariableTemplate.cpp

Index: clang/test/clang-rename/VariableTemplate.cpp
===
--- /dev/null
+++ clang/test/clang-rename/VariableTemplate.cpp
@@ -0,0 +1,32 @@
+template 
+bool Foo = true;  // CHECK: bool Bar = true;
+
+// explicit template specialization
+template <>
+bool Foo = false; // CHECK: bool Bar = false;
+
+// partial template specialization
+template 
+bool Foo = false; // bool Bar = false;
+
+void k() {
+  // ref to the explicit template specialization
+  Foo;   // CHECK: Bar;
+  // ref to the primary template.
+  Foo;   // CHECK: Bar;
+}
+
+
+// Test 1.
+// RUN: clang-rename -offset=34 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+// Test 2.
+// RUN: clang-rename -offset=128 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+// Test 3.
+// RUN: clang-rename -offset=248 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+// Test 4.
+// RUN: clang-rename -offset=357 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+// Test 5.
+// RUN: clang-rename -offset=431 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+
+// To find offsets after modifying the file, use:
+//   grep -Ubo 'Foo.*' 
Index: clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
===
--- clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -87,6 +87,16 @@
 handleFunctionTemplateDecl(FTD);
 } else if (const auto *FD = dyn_cast(FoundDecl)) {
   handleFunctionTemplateDecl(FD);
+} else if (const auto *VTD = dyn_cast(FoundDecl)) {
+  handleVarTemplateDecl(VTD);
+} else if (const auto *VD =
+   dyn_cast(FoundDecl)) {
+  // FIXME: figure out why FoundDecl can be a VarTemplateSpecializationDecl.
+  handleVarTemplateDecl(VD->getSpecializedTemplate());
+} else if (const auto *VD = dyn_cast(FoundDecl)) {
+  USRSet.insert(getUSRForDecl(VD));
+  if (const auto *VTD = VD->getDescribedVarTemplate())
+handleVarTemplateDecl(VTD);
 } else {
   USRSet.insert(getUSRForDecl(FoundDecl));
 }
@@ -132,6 +142,19 @@
   USRSet.insert(getUSRForDecl(S));
   }
 
+  void handleVarTemplateDecl(const VarTemplateDecl *VTD) {
+USRSet.insert(getUSRForDecl(VTD));
+USRSet.insert(getUSRForDecl(VTD->getTemplatedDecl()));
+llvm::for_each(VTD->specializations(), [&](const auto *Spec) {
+  USRSet.insert(getUSRForDecl(Spec));
+});
+SmallVector PartialSpecs;
+VTD->getPartialSpecializations(PartialSpecs);
+llvm::for_each(PartialSpecs, [&](const auto *Spec) {
+  USRSet.insert(getUSRForDecl(Spec));
+});
+  }
+
   void addUSRsOfCtorDtors(const CXXRecordDecl *RD) {
 const auto* RecordDecl = RD->getDefinition();
 
Index: clang/lib/AST/DeclTemplate.cpp
===
--- clang/lib/AST/DeclTemplate.cpp
+++ clang/lib/AST/DeclTemplate.cpp
@@ -1142,7 +1142,7 @@
 }
 
 llvm::FoldingSetVector &
-VarTemplateDecl::getPartialSpecializations() {
+VarTemplateDecl::getPartialSpecializations() const {
   LoadLazySpecializations();
   return getCommonPtr()->PartialSpecializations;
 }
@@ -1198,7 +1198,7 @@
 }
 
 void VarTemplateDecl::getPartialSpecializations(
-SmallVectorImpl ) {
+SmallVectorImpl ) const {
   llvm::FoldingSetVector  =
   getPartialSpecializations();
   PS.clear();
Index: clang/include/clang/AST/DeclTemplate.h
===
--- clang/include/clang/AST/DeclTemplate.h
+++ clang/include/clang/AST/DeclTemplate.h
@@ -3095,7 +3095,7 @@
   /// Retrieve the set of partial specializations of this class
   /// template.
   llvm::FoldingSetVector &
-  getPartialSpecializations();
+  getPartialSpecializations() const;
 
   VarTemplateDecl(ASTContext , DeclContext *DC, SourceLocation L,
   DeclarationName Name, TemplateParameterList *Params,
@@ -3191,7 +3191,7 @@
 
   /// Retrieve the partial specializations as an ordered list.
   void getPartialSpecializations(
-  SmallVectorImpl );
+  SmallVectorImpl ) const;
 
   /// Find a variable template partial specialization which was
   /// instantiated
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D89238: [clangd] Go-to-definition from non-renaming alias is unambiguous.

2020-10-13 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

Thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89238

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


[PATCH] D88469: [clangd] Heuristic resolution for dependent type and template names

2020-10-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

thanks.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88469

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


[PATCH] D89098: [clang] Fix returning the underlying VarDecl as top-level decl for VarTemplateDecl.

2020-10-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a subscriber: rsmith.
hokein added a comment.

> Is this https://github.com/clangd/clangd/issues/554 ? :-)

Yeah, the github issue exposes multiple bugs, this is part of the fix.

The AST of `VarTemplateSpeicalizationDecl` is a bit unusual, given the follow 
code,

  template  bool X = true;
  bool Z = X;



  TranslationUnitDecl 0x8a2ec28 <> 
  |-VarTemplateDecl 0x8a6faf8  col:26 X
  | |-TemplateTypeParmDecl 0x8a6f9c0  col:19 typename depth 0 index 0
  | |-VarDecl 0x8a6fa90  col:26 X 'bool' cinit
  | | `-CXXBoolLiteralExpr 0x8a6fb98  'bool' true
  | `-VarTemplateSpecializationDecl 0x8a6fd08  col:26 used X 
'bool' cinit
  |   |-TemplateArgument type 'int'
  |   | `-BuiltinType 0x8a2ed20 'int'
  |   `-CXXBoolLiteralExpr 0x8a6fb98  'bool' true
  |-VarDecl 0x8a6fbb8  col:6 Z 'bool' cinit
  | `-ImplicitCastExpr 0x8a6ff28  'bool' 
  |   `-DeclRefExpr 0x8a6fed8  'bool' lvalue 
VarTemplateSpecialization 0x8a6fd08 'X' 'bool'
  `-VarTemplateSpecializationDecl 0x8a6fd08  col:26 used X 
'bool' cinit   < here
|-TemplateArgument type 'int'
| `-BuiltinType 0x8a2ed20 'int'
`-CXXBoolLiteralExpr 0x8a6fb98  'bool' true

Note that the implicitly-instantiated `VarTemplateSpecializationDecl` is one of 
`TranslationUnitDecl::decls()`, this is different than function/class templates 
-- for function/class templates, only *explicit* template specializations will 
be in the `TranslationUnitDecl::decls()`

Related code is at 
https://github.com/llvm/llvm-project/blob/master/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp#L5015.
 @rsmith do you think this is expected? or we should fix that? like making it 
align with function/class templates?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89098

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


[PATCH] D89131: [clangd] Validate optional fields more strictly.

2020-10-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

ah, I thought I clicked the accepted button.

anyway, LGTM.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89131

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


[PATCH] D89233: [clangd] Refine recoveryAST flags in clangd

2020-10-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: sammccall.
Herald added subscribers: usaxena95, kadircet, arphaman.
Herald added a project: clang.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

so that we could start experiment for C.

Previously, these flags in clangd were only meaningful for C++. We need
to flip them for C, this patch repurpose these flags.

- if true, just set it.
- if false, just respect the value in clang.

this would allow us to keep flags on for C++, and optionally flip them on for C.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D89233

Files:
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Compiler.cpp
  clang-tools-extra/clangd/tool/ClangdMain.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.cpp
  clang-tools-extra/clangd/unittests/TestTU.cpp

Index: clang-tools-extra/clangd/unittests/TestTU.cpp
===
--- clang-tools-extra/clangd/unittests/TestTU.cpp
+++ clang-tools-extra/clangd/unittests/TestTU.cpp
@@ -59,8 +59,6 @@
 FS.OverlayRealFileSystemForModules = true;
   Inputs.TFS = 
   Inputs.Opts = ParseOptions();
-  Inputs.Opts.BuildRecoveryAST = true;
-  Inputs.Opts.PreserveRecoveryASTType = true;
   Inputs.Opts.ClangTidyOpts.Checks = ClangTidyChecks;
   Inputs.Opts.ClangTidyOpts.WarningsAsErrors = ClangTidyWarningsAsErrors;
   Inputs.Index = ExternalIndex;
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -148,6 +148,17 @@
   EXPECT_DECLS("LabelStmt", "label:");
 }
 
+TEST_F(TargetDeclTest, RecoveryForC) {
+  Flags = {"-xc", "-Xclang", "-frecovery-ast"};
+  Code = R"cpp(
+// error-ok: testing behavior on broken code
+// int f();
+int f(int);
+int x = [[f]]();
+  )cpp";
+  EXPECT_DECLS("DeclRefExpr", "int f(int)");
+}
+
 TEST_F(TargetDeclTest, Recovery) {
   Code = R"cpp(
 // error-ok: testing behavior on broken code
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -111,8 +111,6 @@
 
   MockFS FS;
   auto Inputs = TU.inputs(FS);
-  Inputs.Opts.BuildRecoveryAST = true;
-  Inputs.Opts.PreserveRecoveryASTType = true;
   IgnoreDiagnostics Diags;
   auto CI = buildCompilerInvocation(Inputs, Diags);
   if (!CI) {
@@ -1100,8 +1098,6 @@
   MockFS FS;
   auto Inputs = TU.inputs(FS);
   Inputs.Index = Index.get();
-  Inputs.Opts.BuildRecoveryAST = true;
-  Inputs.Opts.PreserveRecoveryASTType = true;
   IgnoreDiagnostics Diags;
   auto CI = buildCompilerInvocation(Inputs, Diags);
   if (!CI) {
Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -310,7 +310,7 @@
 opt RecoveryAST{
 "recovery-ast",
 cat(Features),
-desc("Preserve expressions in AST for broken code (C++ only)."),
+desc("Preserve expressions in AST for broken code."),
 init(ClangdServer::Options().BuildRecoveryAST),
 };
 
Index: clang-tools-extra/clangd/Compiler.cpp
===
--- clang-tools-extra/clangd/Compiler.cpp
+++ clang-tools-extra/clangd/Compiler.cpp
@@ -81,11 +81,11 @@
   // Don't crash on `#pragma clang __debug parser_crash`
   CI->getPreprocessorOpts().DisablePragmaDebugCrash = true;
 
-  // Recovery expression currently only works for C++.
-  if (CI->getLangOpts()->CPlusPlus) {
-CI->getLangOpts()->RecoveryAST = Inputs.Opts.BuildRecoveryAST;
-CI->getLangOpts()->RecoveryASTType = Inputs.Opts.PreserveRecoveryASTType;
-  }
+  if (Inputs.Opts.BuildRecoveryAST)
+CI->getLangOpts()->RecoveryAST = true;
+  if (Inputs.Opts.PreserveRecoveryASTType)
+CI->getLangOpts()->RecoveryASTType = true;
+
   return CI;
 }
 
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -127,11 +127,13 @@
 /// enabled.
 ClangTidyOptionsBuilder GetClangTidyOptions;
 
-/// If true, turn on the `-frecovery-ast` clang flag.
-bool BuildRecoveryAST = true;
+/// If true, turn on the `-frecovery-ast` clang flag;
+/// If false, respect to the value in clang.
+bool BuildRecoveryAST = false;
 
 /// If true, turn on the `-frecovery-ast-type` clang flag.
-bool PreserveRecoveryASTType = true;
+/// If false, respect to the value in clang.
+bool PreserveRecoveryASTType = 

[PATCH] D89045: [AST][RecoveryExpr] Don't perform early typo correction in C.

2020-10-12 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG8852d30b1c1b: [AST][RecoveryExpr] Dont perform early 
typo correction in C. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89045

Files:
  clang/lib/Sema/SemaExpr.cpp
  clang/test/AST/ast-dump-recovery.c


Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -24,14 +24,10 @@
 int unary_address = &(a + 1);
 
 // CHECK:   VarDecl {{.*}} ternary 'int' cinit
-// CHECK-NEXT:  `-RecoveryExpr {{.*}}
+// CHECK-NEXT:  `-ConditionalOperator {{.*}}
 // CHECK-NEXT:|-DeclRefExpr {{.*}} 'a'
-// CHECK-NEXT:|-TypoExpr {{.*}}
+// CHECK-NEXT:|-RecoveryExpr {{.*}}
 // CHECK-NEXT:`-DeclRefExpr {{.*}} 'a'
-// FIXME: The TypoExpr should never be print, and should be downgraded to
-// RecoveryExpr -- typo correction is performed too early in C-only codepath,
-// which makes no correction when clang finishes the full expr 
(Sema::Sema::ActOnFinishFullExpr).
-// this will be fixed when we support dependent mechanism and delayed typo 
correction for C.
 int ternary = a ? undef : a;
 
 void test1() {
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -8494,7 +8494,7 @@
 SourceLocation ColonLoc,
 Expr *CondExpr, Expr *LHSExpr,
 Expr *RHSExpr) {
-  if (!getLangOpts().CPlusPlus) {
+  if (!Context.isDependenceAllowed()) {
 // C cannot handle TypoExpr nodes in the condition because it
 // doesn't handle dependent types properly, so make sure any TypoExprs have
 // been dealt with before checking the operands.


Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -24,14 +24,10 @@
 int unary_address = &(a + 1);
 
 // CHECK:   VarDecl {{.*}} ternary 'int' cinit
-// CHECK-NEXT:  `-RecoveryExpr {{.*}}
+// CHECK-NEXT:  `-ConditionalOperator {{.*}}
 // CHECK-NEXT:|-DeclRefExpr {{.*}} 'a'
-// CHECK-NEXT:|-TypoExpr {{.*}}
+// CHECK-NEXT:|-RecoveryExpr {{.*}}
 // CHECK-NEXT:`-DeclRefExpr {{.*}} 'a'
-// FIXME: The TypoExpr should never be print, and should be downgraded to
-// RecoveryExpr -- typo correction is performed too early in C-only codepath,
-// which makes no correction when clang finishes the full expr (Sema::Sema::ActOnFinishFullExpr).
-// this will be fixed when we support dependent mechanism and delayed typo correction for C.
 int ternary = a ? undef : a;
 
 void test1() {
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -8494,7 +8494,7 @@
 SourceLocation ColonLoc,
 Expr *CondExpr, Expr *LHSExpr,
 Expr *RHSExpr) {
-  if (!getLangOpts().CPlusPlus) {
+  if (!Context.isDependenceAllowed()) {
 // C cannot handle TypoExpr nodes in the condition because it
 // doesn't handle dependent types properly, so make sure any TypoExprs have
 // been dealt with before checking the operands.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D84304: [AST][RecoveryExpr] Part 2: Build dependent callexpr in C for error-recovery.

2020-10-12 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGbb406f36dca3: [AST][RecoveryExpr] Build dependent callexpr 
in C for error-recovery. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84304

Files:
  clang/lib/Sema/SemaExpr.cpp
  clang/test/AST/ast-dump-recovery.c
  clang/test/Sema/error-dependence.c


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -10,6 +10,9 @@
   // verify diagnostic "operand of type '' where arithmetic or
   // pointer type is required" is not emitted.
   (float)call(); // expected-error {{too few arguments to function call}}
+  // verify disgnostic "called object type '' is not a function
+  // or function pointer" is not emitted.
+  (*__builtin_classify_type)(1); // expected-error {{builtin functions must be 
directly called}}
 }
 
 void test2(int* ptr, float f) {
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -87,3 +87,18 @@
   // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
   (float)some_func();
 }
+
+void test3() {
+  // CHECK: CallExpr {{.*}} '' contains-errors
+  // CHECK-NEXT: |-ParenExpr {{.*}} contains-errors lvalue
+  // CHECK-NEXT: | `-RecoveryExpr {{.*}} contains-errors
+  // CHECK-NEXT: |   `-DeclRefExpr {{.*}} '__builtin_classify_type'
+  // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+  (*__builtin_classify_type)(1);
+
+  extern void ext();
+  // CHECK: CallExpr {{.*}} 'void' contains-errors
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'ext'
+  // CHECK-NEXT: `-RecoveryExpr {{.*}} ''
+  ext(undef_var);
+}
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -6375,6 +6375,21 @@
 checkDirectCallValidity(*this, Fn, FD, ArgExprs);
   }
 
+  if (Context.isDependenceAllowed() &&
+  (Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(ArgExprs))) 
{
+assert(!getLangOpts().CPlusPlus);
+assert(Fn->containsErrors() ||
+   llvm::any_of(ArgExprs,
+[](clang::Expr *E) { return E->containsErrors(); }) &&
+   "should only occur in error-recovery path.");
+QualType ReturnType =
+llvm::isa_and_nonnull(NDecl)
+? dyn_cast(NDecl)->getCallResultType()
+: Context.DependentTy;
+return CallExpr::Create(Context, Fn, ArgExprs, ReturnType,
+Expr::getValueKindForType(ReturnType), RParenLoc,
+CurFPFeatureOverrides());
+  }
   return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs, RParenLoc,
ExecConfig, IsExecConfig);
 }
@@ -6515,7 +6530,7 @@
  CurFPFeatureOverrides(), NumParams, UsesADL);
   }
 
-  if (!getLangOpts().CPlusPlus) {
+  if (!Context.isDependenceAllowed()) {
 // Forget about the nulled arguments since typo correction
 // do not handle them well.
 TheCall->shrinkNumArgs(Args.size());
@@ -19052,7 +19067,7 @@
 /// Check for operands with placeholder types and complain if found.
 /// Returns ExprError() if there was an error and no recovery was possible.
 ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
-  if (!getLangOpts().CPlusPlus) {
+  if (!Context.isDependenceAllowed()) {
 // C cannot handle TypoExpr nodes on either side of a binop because it
 // doesn't handle dependent types properly, so make sure any TypoExprs have
 // been dealt with before checking the operands.


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -10,6 +10,9 @@
   // verify diagnostic "operand of type '' where arithmetic or
   // pointer type is required" is not emitted.
   (float)call(); // expected-error {{too few arguments to function call}}
+  // verify disgnostic "called object type '' is not a function
+  // or function pointer" is not emitted.
+  (*__builtin_classify_type)(1); // expected-error {{builtin functions must be directly called}}
 }
 
 void test2(int* ptr, float f) {
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -87,3 +87,18 @@
   // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
   (float)some_func();
 }
+
+void test3() {
+  // CHECK: CallExpr {{.*}} '' contains-errors
+  // CHECK-NEXT: |-ParenExpr {{.*}} contains-errors lvalue
+  // CHECK-NEXT: | `-RecoveryExpr 

[PATCH] D89098: [clang] Fix returning the underlying VarDecl as top-level decl for VarTemplateDecl.

2020-10-12 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG702529d899c8: [clang] Fix returning the underlying VarDecl 
as top-level decl for… (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D89098?vs=297512=297514#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89098

Files:
  clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
  clang/lib/Parse/ParseDecl.cpp


Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -2195,6 +2195,7 @@
 
   // Inform the current actions module that we just parsed this declarator.
   Decl *ThisDecl = nullptr;
+  Decl *OuterDecl = nullptr;
   switch (TemplateInfo.Kind) {
   case ParsedTemplateInfo::NonTemplate:
 ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
@@ -2205,10 +2206,12 @@
 ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
*TemplateInfo.TemplateParams,
D);
-if (VarTemplateDecl *VT = dyn_cast_or_null(ThisDecl))
+if (VarTemplateDecl *VT = dyn_cast_or_null(ThisDecl)) {
   // Re-direct this decl to refer to the templated decl so that we can
   // initialize it.
   ThisDecl = VT->getTemplatedDecl();
+  OuterDecl = VT;
+}
 break;
   }
   case ParsedTemplateInfo::ExplicitInstantiation: {
@@ -2385,8 +2388,7 @@
   }
 
   Actions.FinalizeDeclaration(ThisDecl);
-
-  return ThisDecl;
+  return OuterDecl ? OuterDecl : ThisDecl;
 }
 
 /// ParseSpecifierQualifierList
Index: clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
===
--- clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
@@ -57,6 +57,12 @@
   return false;
 }
 
+MATCHER_P(DeclKind, Kind, "") {
+  if (NamedDecl *ND = dyn_cast(arg))
+return ND->getDeclKindName() == Kind;
+  return false;
+}
+
 // Matches if the Decl has template args equal to ArgName. If the decl is a
 // NamedDecl and ArgName is an empty string it also matches.
 MATCHER_P(WithTemplateArgs, ArgName, "") {
@@ -99,9 +105,15 @@
 int header1();
 int header2;
   )";
-  TU.Code = "int main();";
+  TU.Code = R"cpp(
+int main();
+template  bool X = true;
+  )cpp";
   auto AST = TU.build();
-  EXPECT_THAT(AST.getLocalTopLevelDecls(), ElementsAre(DeclNamed("main")));
+  EXPECT_THAT(
+  AST.getLocalTopLevelDecls(),
+  ElementsAreArray({AllOf(DeclNamed("main"), DeclKind("Function")),
+AllOf(DeclNamed("X"), DeclKind("VarTemplate"))}));
 }
 
 TEST(ParsedASTTest, DoesNotGetIncludedTopDecls) {


Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -2195,6 +2195,7 @@
 
   // Inform the current actions module that we just parsed this declarator.
   Decl *ThisDecl = nullptr;
+  Decl *OuterDecl = nullptr;
   switch (TemplateInfo.Kind) {
   case ParsedTemplateInfo::NonTemplate:
 ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
@@ -2205,10 +2206,12 @@
 ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
*TemplateInfo.TemplateParams,
D);
-if (VarTemplateDecl *VT = dyn_cast_or_null(ThisDecl))
+if (VarTemplateDecl *VT = dyn_cast_or_null(ThisDecl)) {
   // Re-direct this decl to refer to the templated decl so that we can
   // initialize it.
   ThisDecl = VT->getTemplatedDecl();
+  OuterDecl = VT;
+}
 break;
   }
   case ParsedTemplateInfo::ExplicitInstantiation: {
@@ -2385,8 +2388,7 @@
   }
 
   Actions.FinalizeDeclaration(ThisDecl);
-
-  return ThisDecl;
+  return OuterDecl ? OuterDecl : ThisDecl;
 }
 
 /// ParseSpecifierQualifierList
Index: clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
===
--- clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
@@ -57,6 +57,12 @@
   return false;
 }
 
+MATCHER_P(DeclKind, Kind, "") {
+  if (NamedDecl *ND = dyn_cast(arg))
+return ND->getDeclKindName() == Kind;
+  return false;
+}
+
 // Matches if the Decl has template args equal to ArgName. If the decl is a
 // NamedDecl and ArgName is an empty string it also matches.
 MATCHER_P(WithTemplateArgs, ArgName, "") {
@@ -99,9 +105,15 @@
 int header1();
 int header2;
   )";
-  TU.Code = "int main();";
+  TU.Code = R"cpp(
+int main();
+template  bool X = true;
+  )cpp";
   auto AST = TU.build();
-  EXPECT_THAT(AST.getLocalTopLevelDecls(), 

[PATCH] D89131: [clangd] Validate optional fields more strictly.

2020-10-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/Protocol.cpp:800
+  return O && O.map("applied", R.applied) &&
+ O.mapOptional("failureReason", R.failureReason);
 }

R.failureReason's type is `llvm::Optional`, I think we should 
probably use the `O.map` (the overload one for llvm::Optional)?



Comment at: clang-tools-extra/clangd/Protocol.cpp:1130
+ O.mapOptional("compilationDatabasePath",
+   Opts.compilationDatabasePath) &&
+ O.mapOptional("fallbackFlags", Opts.fallbackFlags) &&

And this one.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89131

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


[PATCH] D89098: [clang] Fix returning the underlying VarDecl as top-level decl for VarTemplateDecl.

2020-10-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 297512.
hokein marked 3 inline comments as done.
hokein added a comment.

address review comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89098

Files:
  clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
  clang/lib/Parse/ParseDecl.cpp


Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -2195,6 +2195,7 @@
 
   // Inform the current actions module that we just parsed this declarator.
   Decl *ThisDecl = nullptr;
+  Decl *OuterDecl = nullptr;
   switch (TemplateInfo.Kind) {
   case ParsedTemplateInfo::NonTemplate:
 ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
@@ -2205,10 +2206,12 @@
 ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
*TemplateInfo.TemplateParams,
D);
-if (VarTemplateDecl *VT = dyn_cast_or_null(ThisDecl))
+if (VarTemplateDecl *VT = dyn_cast_or_null(ThisDecl)) {
   // Re-direct this decl to refer to the templated decl so that we can
   // initialize it.
   ThisDecl = VT->getTemplatedDecl();
+  OuterDecl = VT;
+}
 break;
   }
   case ParsedTemplateInfo::ExplicitInstantiation: {
@@ -2385,8 +2388,7 @@
   }
 
   Actions.FinalizeDeclaration(ThisDecl);
-
-  return ThisDecl;
+  return OuterDecl ? OuterDecl : ThisDecl;
 }
 
 /// ParseSpecifierQualifierList
Index: clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
===
--- clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
@@ -57,6 +57,12 @@
   return false;
 }
 
+MATCHER_P(DeclKind, Kind, "") {
+  if (NamedDecl *ND = dyn_cast(arg))
+return ND->getDeclKindName() == Kind;
+  return false;
+}
+
 // Matches if the Decl has template args equal to ArgName. If the decl is a
 // NamedDecl and ArgName is an empty string it also matches.
 MATCHER_P(WithTemplateArgs, ArgName, "") {
@@ -99,9 +105,23 @@
 int header1();
 int header2;
   )";
-  TU.Code = "int main();";
+  TU.Code = R"cpp(
+int main();
+template  bool X = true;
+  )cpp";
   auto AST = TU.build();
-  EXPECT_THAT(AST.getLocalTopLevelDecls(), ElementsAre(DeclNamed("main")));
+  EXPECT_THAT(
+  AST.getLocalTopLevelDecls(),
+  ElementsAreArray({AllOf(DeclNamed("main"), DeclKind("Function")),
+AllOf(DeclNamed("X"), DeclKind("VarTemplate"))}));
+}
+
+TEST(ParsedASTTest, VarTemplateDecl) {
+  TestTU TU;
+  TU.Code = "template  bool X = true;";
+  auto AST = TU.build();
+  EXPECT_THAT(AST.getLocalTopLevelDecls(),
+  ElementsAre(AllOf(DeclNamed("X"), WithTemplateArgs("";
 }
 
 TEST(ParsedASTTest, DoesNotGetIncludedTopDecls) {


Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -2195,6 +2195,7 @@
 
   // Inform the current actions module that we just parsed this declarator.
   Decl *ThisDecl = nullptr;
+  Decl *OuterDecl = nullptr;
   switch (TemplateInfo.Kind) {
   case ParsedTemplateInfo::NonTemplate:
 ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
@@ -2205,10 +2206,12 @@
 ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
*TemplateInfo.TemplateParams,
D);
-if (VarTemplateDecl *VT = dyn_cast_or_null(ThisDecl))
+if (VarTemplateDecl *VT = dyn_cast_or_null(ThisDecl)) {
   // Re-direct this decl to refer to the templated decl so that we can
   // initialize it.
   ThisDecl = VT->getTemplatedDecl();
+  OuterDecl = VT;
+}
 break;
   }
   case ParsedTemplateInfo::ExplicitInstantiation: {
@@ -2385,8 +2388,7 @@
   }
 
   Actions.FinalizeDeclaration(ThisDecl);
-
-  return ThisDecl;
+  return OuterDecl ? OuterDecl : ThisDecl;
 }
 
 /// ParseSpecifierQualifierList
Index: clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
===
--- clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
@@ -57,6 +57,12 @@
   return false;
 }
 
+MATCHER_P(DeclKind, Kind, "") {
+  if (NamedDecl *ND = dyn_cast(arg))
+return ND->getDeclKindName() == Kind;
+  return false;
+}
+
 // Matches if the Decl has template args equal to ArgName. If the decl is a
 // NamedDecl and ArgName is an empty string it also matches.
 MATCHER_P(WithTemplateArgs, ArgName, "") {
@@ -99,9 +105,23 @@
 int header1();
 int header2;
   )";
-  TU.Code = "int main();";
+  TU.Code = R"cpp(
+int main();
+template  bool X = true;
+  )cpp";
   auto AST = TU.build();
-  

[PATCH] D89221: [clang-rename] Fix rename on function template specializations.

2020-10-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: kbobyrev.
Herald added a project: clang.
hokein requested review of this revision.

previously, we missed to rename occurrences to explicit function template
specilizations.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D89221

Files:
  clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
  clang/test/clang-rename/FunctionTemplate.cpp


Index: clang/test/clang-rename/FunctionTemplate.cpp
===
--- /dev/null
+++ clang/test/clang-rename/FunctionTemplate.cpp
@@ -0,0 +1,19 @@
+template 
+void Foo(T t); // CHECK: void Bar(T t);
+
+template <>
+void Foo(int a); // CHECK: void Bar(int a);
+
+void test() {
+  Foo(1); // CHECK: Bar(1);
+}
+
+// Test 1.
+// RUN: clang-rename -offset=28 -new-name=Bar %s -- | sed 's,//.*,,' | 
FileCheck %s
+// Test 2.
+// RUN: clang-rename -offset=81 -new-name=Bar %s -- | sed 's,//.*,,' | 
FileCheck %s
+// Test 3.
+// RUN: clang-rename -offset=137 -new-name=Bar %s -- | sed 's,//.*,,' | 
FileCheck %s
+
+// To find offsets after modifying the file, use:
+//   grep -Ubo 'Foo.*' 
Index: clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
===
--- clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -81,6 +81,12 @@
 } else if (const auto *TemplateDecl =
dyn_cast(FoundDecl)) {
   handleClassTemplateDecl(TemplateDecl);
+} else if (const auto *FD = dyn_cast(FoundDecl)) {
+  USRSet.insert(getUSRForDecl(FD));
+  if (const auto *FTD = FD->getPrimaryTemplate())
+handleFunctionTemplateDecl(FTD);
+} else if (const auto *FD = dyn_cast(FoundDecl)) {
+  handleFunctionTemplateDecl(FD);
 } else {
   USRSet.insert(getUSRForDecl(FoundDecl));
 }
@@ -120,6 +126,12 @@
 addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
   }
 
+  void handleFunctionTemplateDecl(const FunctionTemplateDecl *FTD) {
+USRSet.insert(getUSRForDecl(FTD));
+for (const auto *S : FTD->specializations())
+  USRSet.insert(getUSRForDecl(S));
+  }
+
   void addUSRsOfCtorDtors(const CXXRecordDecl *RD) {
 const auto* RecordDecl = RD->getDefinition();
 


Index: clang/test/clang-rename/FunctionTemplate.cpp
===
--- /dev/null
+++ clang/test/clang-rename/FunctionTemplate.cpp
@@ -0,0 +1,19 @@
+template 
+void Foo(T t); // CHECK: void Bar(T t);
+
+template <>
+void Foo(int a); // CHECK: void Bar(int a);
+
+void test() {
+  Foo(1); // CHECK: Bar(1);
+}
+
+// Test 1.
+// RUN: clang-rename -offset=28 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+// Test 2.
+// RUN: clang-rename -offset=81 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+// Test 3.
+// RUN: clang-rename -offset=137 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
+
+// To find offsets after modifying the file, use:
+//   grep -Ubo 'Foo.*' 
Index: clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
===
--- clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -81,6 +81,12 @@
 } else if (const auto *TemplateDecl =
dyn_cast(FoundDecl)) {
   handleClassTemplateDecl(TemplateDecl);
+} else if (const auto *FD = dyn_cast(FoundDecl)) {
+  USRSet.insert(getUSRForDecl(FD));
+  if (const auto *FTD = FD->getPrimaryTemplate())
+handleFunctionTemplateDecl(FTD);
+} else if (const auto *FD = dyn_cast(FoundDecl)) {
+  handleFunctionTemplateDecl(FD);
 } else {
   USRSet.insert(getUSRForDecl(FoundDecl));
 }
@@ -120,6 +126,12 @@
 addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
   }
 
+  void handleFunctionTemplateDecl(const FunctionTemplateDecl *FTD) {
+USRSet.insert(getUSRForDecl(FTD));
+for (const auto *S : FTD->specializations())
+  USRSet.insert(getUSRForDecl(S));
+  }
+
   void addUSRsOfCtorDtors(const CXXRecordDecl *RD) {
 const auto* RecordDecl = RD->getDefinition();
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D89220: [clang-rename] Simplify the code of handling class paritial specializations, NFC.

2020-10-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: kbobyrev.
Herald added a project: clang.
hokein requested review of this revision.

Instead of collecting all specializations and doing a post-filterin, we
can just get all targeted specializations from 
getPartialSpecializationsizations.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D89220

Files:
  clang/include/clang/AST/DeclTemplate.h
  clang/lib/AST/DeclTemplate.cpp
  clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp


Index: clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
===
--- clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -27,6 +27,7 @@
 #include "clang/Tooling/Refactoring.h"
 #include "clang/Tooling/Refactoring/Rename/USRFinder.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/STLExtras.h"
 
 #include 
 #include 
@@ -96,12 +97,6 @@
 return true;
   }
 
-  bool VisitClassTemplatePartialSpecializationDecl(
-  const ClassTemplatePartialSpecializationDecl *PartialSpec) {
-PartialSpecs.push_back(PartialSpec);
-return true;
-  }
-
 private:
   void handleCXXRecordDecl(const CXXRecordDecl *RecordDecl) {
 if (!RecordDecl->getDefinition()) {
@@ -118,11 +113,10 @@
   void handleClassTemplateDecl(const ClassTemplateDecl *TemplateDecl) {
 for (const auto *Specialization : TemplateDecl->specializations())
   addUSRsOfCtorDtors(Specialization);
-
-for (const auto *PartialSpec : PartialSpecs) {
-  if (PartialSpec->getSpecializedTemplate() == TemplateDecl)
-addUSRsOfCtorDtors(PartialSpec);
-}
+SmallVector PartialSpecs;
+TemplateDecl->getPartialSpecializations(PartialSpecs);
+llvm::for_each(PartialSpecs,
+   [&](const auto *Spec) { addUSRsOfCtorDtors(Spec); });
 addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
   }
 
@@ -184,7 +178,6 @@
   std::set USRSet;
   std::vector OverriddenMethods;
   std::vector InstantiatedMethods;
-  std::vector PartialSpecs;
 };
 } // namespace
 
Index: clang/lib/AST/DeclTemplate.cpp
===
--- clang/lib/AST/DeclTemplate.cpp
+++ clang/lib/AST/DeclTemplate.cpp
@@ -440,7 +440,7 @@
 }
 
 llvm::FoldingSetVector &
-ClassTemplateDecl::getPartialSpecializations() {
+ClassTemplateDecl::getPartialSpecializations() const {
   LoadLazySpecializations();
   return getCommonPtr()->PartialSpecializations;
 }
@@ -528,7 +528,7 @@
 }
 
 void ClassTemplateDecl::getPartialSpecializations(
-  SmallVectorImpl ) {
+SmallVectorImpl ) const {
   llvm::FoldingSetVector 
 = getPartialSpecializations();
   PS.clear();
Index: clang/include/clang/AST/DeclTemplate.h
===
--- clang/include/clang/AST/DeclTemplate.h
+++ clang/include/clang/AST/DeclTemplate.h
@@ -2266,7 +2266,7 @@
   /// Retrieve the set of partial specializations of this class
   /// template.
   llvm::FoldingSetVector &
-  getPartialSpecializations();
+  getPartialSpecializations() const;
 
   ClassTemplateDecl(ASTContext , DeclContext *DC, SourceLocation L,
 DeclarationName Name, TemplateParameterList *Params,
@@ -2363,7 +2363,7 @@
 
   /// Retrieve the partial specializations as an ordered list.
   void getPartialSpecializations(
-  SmallVectorImpl );
+  SmallVectorImpl ) const;
 
   /// Find a class template partial specialization with the given
   /// type T.


Index: clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
===
--- clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -27,6 +27,7 @@
 #include "clang/Tooling/Refactoring.h"
 #include "clang/Tooling/Refactoring/Rename/USRFinder.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/STLExtras.h"
 
 #include 
 #include 
@@ -96,12 +97,6 @@
 return true;
   }
 
-  bool VisitClassTemplatePartialSpecializationDecl(
-  const ClassTemplatePartialSpecializationDecl *PartialSpec) {
-PartialSpecs.push_back(PartialSpec);
-return true;
-  }
-
 private:
   void handleCXXRecordDecl(const CXXRecordDecl *RecordDecl) {
 if (!RecordDecl->getDefinition()) {
@@ -118,11 +113,10 @@
   void handleClassTemplateDecl(const ClassTemplateDecl *TemplateDecl) {
 for (const auto *Specialization : TemplateDecl->specializations())
   addUSRsOfCtorDtors(Specialization);
-
-for (const auto *PartialSpec : PartialSpecs) {
-  if (PartialSpec->getSpecializedTemplate() == TemplateDecl)
-addUSRsOfCtorDtors(PartialSpec);
-}
+SmallVector PartialSpecs;
+TemplateDecl->getPartialSpecializations(PartialSpecs);
+llvm::for_each(PartialSpecs,
+   [&](const auto *Spec) { addUSRsOfCtorDtors(Spec); });
 

[PATCH] D89098: [clang] Fix returning the underlying VarDecl as top-level decl for VarTemplateDecl.

2020-10-09 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: sammccall.
Herald added subscribers: usaxena95, kadircet, arphaman, kristof.beyls.
Herald added a project: clang.
hokein requested review of this revision.

Given the following VarTemplateDecl AST,

  VarTemplateDecl col:26 X
  |-TemplateTypeParmDecl typename depth 0 index 0
  `-VarDecl X 'bool' cinit
`-CXXBoolLiteralExpr 'bool' true

previously, we returned the VarDecl as the top-level decl, which was not
correct, the top-level decl should be VarTemplateDecl.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D89098

Files:
  clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
  clang/lib/Parse/ParseDecl.cpp


Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -2195,6 +2195,7 @@
 
   // Inform the current actions module that we just parsed this declarator.
   Decl *ThisDecl = nullptr;
+  VarTemplateDecl *VarTemplateD = nullptr;
   switch (TemplateInfo.Kind) {
   case ParsedTemplateInfo::NonTemplate:
 ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
@@ -2205,10 +2206,12 @@
 ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
*TemplateInfo.TemplateParams,
D);
-if (VarTemplateDecl *VT = dyn_cast_or_null(ThisDecl))
+if (VarTemplateDecl *VT = dyn_cast_or_null(ThisDecl)) {
   // Re-direct this decl to refer to the templated decl so that we can
   // initialize it.
   ThisDecl = VT->getTemplatedDecl();
+  VarTemplateD = VT;
+}
 break;
   }
   case ParsedTemplateInfo::ExplicitInstantiation: {
@@ -2385,8 +2388,7 @@
   }
 
   Actions.FinalizeDeclaration(ThisDecl);
-
-  return ThisDecl;
+  return VarTemplateD ? VarTemplateD : ThisDecl;
 }
 
 /// ParseSpecifierQualifierList
Index: clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
===
--- clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
@@ -104,6 +104,14 @@
   EXPECT_THAT(AST.getLocalTopLevelDecls(), ElementsAre(DeclNamed("main")));
 }
 
+TEST(ParsedASTTest, VarTemplateDecl) {
+  TestTU TU;
+  TU.Code = "template  bool X = true;";
+  auto AST = TU.build();
+  EXPECT_THAT(AST.getLocalTopLevelDecls(),
+  ElementsAre(AllOf(DeclNamed("X"), WithTemplateArgs("";
+}
+
 TEST(ParsedASTTest, DoesNotGetIncludedTopDecls) {
   TestTU TU;
   TU.HeaderCode = R"cpp(


Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -2195,6 +2195,7 @@
 
   // Inform the current actions module that we just parsed this declarator.
   Decl *ThisDecl = nullptr;
+  VarTemplateDecl *VarTemplateD = nullptr;
   switch (TemplateInfo.Kind) {
   case ParsedTemplateInfo::NonTemplate:
 ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
@@ -2205,10 +2206,12 @@
 ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
*TemplateInfo.TemplateParams,
D);
-if (VarTemplateDecl *VT = dyn_cast_or_null(ThisDecl))
+if (VarTemplateDecl *VT = dyn_cast_or_null(ThisDecl)) {
   // Re-direct this decl to refer to the templated decl so that we can
   // initialize it.
   ThisDecl = VT->getTemplatedDecl();
+  VarTemplateD = VT;
+}
 break;
   }
   case ParsedTemplateInfo::ExplicitInstantiation: {
@@ -2385,8 +2388,7 @@
   }
 
   Actions.FinalizeDeclaration(ThisDecl);
-
-  return ThisDecl;
+  return VarTemplateD ? VarTemplateD : ThisDecl;
 }
 
 /// ParseSpecifierQualifierList
Index: clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
===
--- clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
@@ -104,6 +104,14 @@
   EXPECT_THAT(AST.getLocalTopLevelDecls(), ElementsAre(DeclNamed("main")));
 }
 
+TEST(ParsedASTTest, VarTemplateDecl) {
+  TestTU TU;
+  TU.Code = "template  bool X = true;";
+  auto AST = TU.build();
+  EXPECT_THAT(AST.getLocalTopLevelDecls(),
+  ElementsAre(AllOf(DeclNamed("X"), WithTemplateArgs("";
+}
+
 TEST(ParsedASTTest, DoesNotGetIncludedTopDecls) {
   TestTU TU;
   TU.HeaderCode = R"cpp(
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D89036: [clangd] Add more incomplete_type diagnostics that could be fixed by include-fixer.

2020-10-09 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGefd8c9ed726d: [clangd] Add more incomplete_type diagnostics 
that could be fixed by include… (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89036

Files:
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -705,11 +705,18 @@
   $nested[[X::]]Nested n;
 }
 class Y : $base[[public ns::X]] {};
-int main() {
-  ns::X *x;
+void test(ns::X *x, ns::X& ref_x) {
   x$access[[->]]f();
   auto& $type[[[]]a] = *x;
+
+  ns::X $incomplete[[var]];
+  $tag[[ref_x]]->f();
+  $use[[ns::X()]];
+  $sizeof[[sizeof]](ns::X);
+  for (auto it : $for[[ref_x]]);
 }
+
+ns::X $return[[func]]() {}
   )cpp");
   auto TU = TestTU::withCode(Test.code());
   TU.ExtraArgs.push_back("-std=c++17");
@@ -739,7 +746,37 @@
"incomplete type 'ns::X' where a complete type is 
required"),
   DiagName("incomplete_type"),
   WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
-  "Add include \"x.h\" for symbol ns::X");
+  "Add include \"x.h\" for symbol ns::X"))),
+  AllOf(Diag(Test.range("incomplete"),
+ "variable has incomplete type 'ns::X'"),
+DiagName("typecheck_decl_incomplete_type"),
+WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(
+  Diag(Test.range("tag"), "incomplete definition of type 'ns::X'"),
+  DiagName("typecheck_incomplete_tag"),
+  WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+  "Add include \"x.h\" for symbol ns::X"))),
+  AllOf(
+  Diag(Test.range("use"), "invalid use of incomplete type 
'ns::X'"),
+  DiagName("invalid_incomplete_type_use"),
+  WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+  "Add include \"x.h\" for symbol ns::X"))),
+  AllOf(Diag(Test.range("sizeof"), "invalid application of 'sizeof' to 
"
+   "an incomplete type 'ns::X'"),
+DiagName("sizeof_alignof_incomplete_or_sizeless_type"),
+WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(Diag(Test.range("for"),
+ "cannot use incomplete type 'ns::X' as a range"),
+DiagName("for_range_incomplete_type"),
+WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(Diag(Test.range("return"),
+ "incomplete result type 'ns::X' in function definition"),
+DiagName("func_def_incomplete_result"),
+WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+"Add include \"x.h\" for symbol ns::X");
 }
 
 TEST(IncludeFixerTest, NoSuggestIncludeWhenNoDefinitionInHeader) {
Index: clang-tools-extra/clangd/IncludeFixer.cpp
===
--- clang-tools-extra/clangd/IncludeFixer.cpp
+++ clang-tools-extra/clangd/IncludeFixer.cpp
@@ -72,6 +72,12 @@
   case diag::err_incomplete_base_class:
   case diag::err_incomplete_member_access:
   case diag::err_incomplete_type:
+  case diag::err_typecheck_decl_incomplete_type:
+  case diag::err_typecheck_incomplete_tag:
+  case diag::err_invalid_incomplete_type_use:
+  case diag::err_sizeof_alignof_incomplete_or_sizeless_type:
+  case diag::err_for_range_incomplete_type:
+  case diag::err_func_def_incomplete_result:
 // Incomplete type diagnostics should have a QualType argument for the
 // incomplete type.
 for (unsigned Idx = 0; Idx < Info.getNumArgs(); ++Idx) {


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -705,11 +705,18 @@
   $nested[[X::]]Nested n;
 }
 class Y : $base[[public ns::X]] {};
-int main() {
-  ns::X *x;
+void test(ns::X *x, ns::X& ref_x) {
   x$access[[->]]f();
   auto& $type[[[]]a] = *x;
+
+  ns::X $incomplete[[var]];
+  $tag[[ref_x]]->f();
+  $use[[ns::X()]];
+  $sizeof[[sizeof]](ns::X);
+  for (auto it : $for[[ref_x]]);
 }
+
+ns::X $return[[func]]() {}
   )cpp");
   auto TU = 

[PATCH] D89046: [AST] Build recovery expression by default for all language.

2020-10-08 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296968.
hokein added a comment.

fix unexpected format changes.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89046

Files:
  clang/include/clang/Basic/LangOptions.def
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/builtins-ppc-error.c
  clang/test/CodeGen/builtins-systemz-zvector-error.c
  clang/test/CodeGen/builtins-systemz-zvector2-error.c
  clang/test/CodeGen/builtins-systemz-zvector3-error.c
  clang/test/Index/complete-switch.c
  clang/test/OpenMP/begin_declare_variant_messages.c
  clang/test/OpenMP/declare_variant_messages.c
  clang/test/Parser/objc-foreach-syntax.m
  clang/test/Sema/__try.c
  clang/test/Sema/enum.c
  clang/test/Sema/typo-correction.c

Index: clang/test/Sema/typo-correction.c
===
--- clang/test/Sema/typo-correction.c
+++ clang/test/Sema/typo-correction.c
@@ -14,9 +14,9 @@
   // expected-error {{use of undeclared identifier 'b'}}
 
 int foobar;  // expected-note {{'foobar' declared here}}
-a = goobar ?: 4;  // expected-warning {{type specifier missing, defaults to 'int'}} \
-  // expected-error {{use of undeclared identifier 'goobar'; did you mean 'foobar'?}} \
-  // expected-error {{initializer element is not a compile-time constant}}
+new_a = goobar ?: 4; // expected-warning {{type specifier missing, defaults to 'int'}} \
+  // expected-error {{use of undeclared identifier 'goobar'; did you mean 'foobar'?}} \
+  // expected-error {{initializer element is not a compile-time constant}}
 
 struct ContainerStuct {
   enum { SOME_ENUM }; // expected-note {{'SOME_ENUM' declared here}}
@@ -50,10 +50,10 @@
   cabs(errij);  // expected-error {{use of undeclared identifier 'errij'}}
 }
 
-extern long afunction(int); // expected-note {{'afunction' declared here}}
+extern long afunction(int);
 void fn2() {
-  f(THIS_IS_AN_ERROR, // expected-error {{use of undeclared identifier 'THIS_IS_AN_ERROR'}}
-afunction(afunction_));  // expected-error {{use of undeclared identifier 'afunction_'; did you mean 'afunction'?}}
+  f(THIS_IS_AN_ERROR,   // expected-error {{use of undeclared identifier 'THIS_IS_AN_ERROR'}}
+afunction(afunction_)); // expected-error {{use of undeclared identifier 'afunction_'}}
 }
 
 int d = X ? d : L; // expected-error 2 {{use of undeclared identifier}}
Index: clang/test/Sema/enum.c
===
--- clang/test/Sema/enum.c
+++ clang/test/Sema/enum.c
@@ -100,7 +100,8 @@
 // PR7911
 extern enum PR7911T PR7911V; // expected-warning{{ISO C forbids forward references to 'enum' types}}
 void PR7911F() {
-  switch (PR7911V); // expected-error {{statement requires expression of integer type}}
+  switch (PR7911V); // expected-error {{statement requires expression of integer type}} \
+// expected-warning {{switch statement has empty body}} expected-note {{put the semicolon on a separate line to silence this warning}}
 }
 
 char test5[__has_feature(enumerator_attributes) ? 1 : -1];
Index: clang/test/Sema/__try.c
===
--- clang/test/Sema/__try.c
+++ clang/test/Sema/__try.c
@@ -50,9 +50,9 @@
 }  // expected-error{{expected '__except' or '__finally' block}}
 
 void TEST() {
-  __except ( FilterExpression() ) { // expected-warning{{implicit declaration of function '__except' is invalid in C99}} \
-// expected-error{{too few arguments to function call, expected 1, have 0}}
-
+  __except (FilterExpression()) { // expected-warning{{implicit declaration of function '__except' is invalid in C99}} \
+// expected-error{{too few arguments to function call, expected 1, have 0}} \
+// expected-error{{expected ';' after expression}}
   }
 }
 
Index: clang/test/Parser/objc-foreach-syntax.m
===
--- clang/test/Parser/objc-foreach-syntax.m
+++ clang/test/Parser/objc-foreach-syntax.m
@@ -21,5 +21,8 @@
 
 
 static int test7(id keys) {
-  for (id key; in keys) ;  // expected-error {{use of undeclared identifier 'in'}}
+  // FIXME: would be nice to suppress the secondary diagnostics.
+  for (id key; in keys) ;  // expected-error {{use of undeclared identifier 'in'}} \
+   // expected-error {{expected ';' in 'for' statement specifier}} \
+   // expected-warning {{expression result unused}}
 }
Index: clang/test/OpenMP/declare_variant_messages.c
===
--- clang/test/OpenMP/declare_variant_messages.c
+++ clang/test/OpenMP/declare_variant_messages.c
@@ -10,7 +10,7 @@
 #pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}}
 #pragma omp declare variant( // expected-error 

[PATCH] D89046: [AST] Build recovery expression by default for all language.

2020-10-08 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
Herald added subscribers: cfe-commits, arphaman, kbarton, nemanjai.
Herald added a project: clang.
hokein requested review of this revision.

Not intent to land it now, we need to run internal experiments to make
sure this is not crashy.

It is ready for review, all changes are diagnostic adjustments.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D89046

Files:
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/builtins-ppc-error.c
  clang/test/CodeGen/builtins-systemz-zvector-error.c
  clang/test/CodeGen/builtins-systemz-zvector2-error.c
  clang/test/CodeGen/builtins-systemz-zvector3-error.c
  clang/test/Index/complete-switch.c
  clang/test/OpenMP/begin_declare_variant_messages.c
  clang/test/OpenMP/declare_variant_messages.c
  clang/test/Parser/objc-foreach-syntax.m
  clang/test/Sema/__try.c
  clang/test/Sema/enum.c
  clang/test/Sema/typo-correction.c

Index: clang/test/Sema/typo-correction.c
===
--- clang/test/Sema/typo-correction.c
+++ clang/test/Sema/typo-correction.c
@@ -14,9 +14,9 @@
   // expected-error {{use of undeclared identifier 'b'}}
 
 int foobar;  // expected-note {{'foobar' declared here}}
-a = goobar ?: 4;  // expected-warning {{type specifier missing, defaults to 'int'}} \
-  // expected-error {{use of undeclared identifier 'goobar'; did you mean 'foobar'?}} \
-  // expected-error {{initializer element is not a compile-time constant}}
+new_a = goobar ?: 4; // expected-warning {{type specifier missing, defaults to 'int'}} \
+  // expected-error {{use of undeclared identifier 'goobar'; did you mean 'foobar'?}} \
+  // expected-error {{initializer element is not a compile-time constant}}
 
 struct ContainerStuct {
   enum { SOME_ENUM }; // expected-note {{'SOME_ENUM' declared here}}
@@ -50,10 +50,10 @@
   cabs(errij);  // expected-error {{use of undeclared identifier 'errij'}}
 }
 
-extern long afunction(int); // expected-note {{'afunction' declared here}}
+extern long afunction(int);
 void fn2() {
-  f(THIS_IS_AN_ERROR, // expected-error {{use of undeclared identifier 'THIS_IS_AN_ERROR'}}
-afunction(afunction_));  // expected-error {{use of undeclared identifier 'afunction_'; did you mean 'afunction'?}}
+  f(THIS_IS_AN_ERROR,   // expected-error {{use of undeclared identifier 'THIS_IS_AN_ERROR'}}
+afunction(afunction_)); // expected-error {{use of undeclared identifier 'afunction_'}}
 }
 
 int d = X ? d : L; // expected-error 2 {{use of undeclared identifier}}
Index: clang/test/Sema/enum.c
===
--- clang/test/Sema/enum.c
+++ clang/test/Sema/enum.c
@@ -100,7 +100,9 @@
 // PR7911
 extern enum PR7911T PR7911V; // expected-warning{{ISO C forbids forward references to 'enum' types}}
 void PR7911F() {
-  switch (PR7911V); // expected-error {{statement requires expression of integer type}}
+  switch (PR7911V)
+; // expected-error {{statement requires expression of integer type}} \
+// expected-warning {{switch statement has empty body}} expected-note {{put the semicolon on a separate line to silence this warning}}
 }
 
 char test5[__has_feature(enumerator_attributes) ? 1 : -1];
Index: clang/test/Sema/__try.c
===
--- clang/test/Sema/__try.c
+++ clang/test/Sema/__try.c
@@ -50,9 +50,9 @@
 }  // expected-error{{expected '__except' or '__finally' block}}
 
 void TEST() {
-  __except ( FilterExpression() ) { // expected-warning{{implicit declaration of function '__except' is invalid in C99}} \
-// expected-error{{too few arguments to function call, expected 1, have 0}}
-
+  __except (FilterExpression()) { // expected-warning{{implicit declaration of function '__except' is invalid in C99}} \
+// expected-error{{too few arguments to function call, expected 1, have 0}} \
+// expected-error{{expected ';' after expression}}
   }
 }
 
Index: clang/test/Parser/objc-foreach-syntax.m
===
--- clang/test/Parser/objc-foreach-syntax.m
+++ clang/test/Parser/objc-foreach-syntax.m
@@ -21,5 +21,9 @@
 
 
 static int test7(id keys) {
-  for (id key; in keys) ;  // expected-error {{use of undeclared identifier 'in'}}
+  // FIXME: would be nice to suppress the secondary diagnostics.
+  for (id key; in keys)
+; // expected-error {{use of undeclared identifier 'in'}} \
+   // expected-error {{expected ';' in 'for' statement specifier}} \
+   // expected-warning {{expression result unused}}
 }
Index: clang/test/OpenMP/declare_variant_messages.c
===
--- clang/test/OpenMP/declare_variant_messages.c
+++ clang/test/OpenMP/declare_variant_messages.c
@@ -10,7 +10,7 @@
 

[PATCH] D89045: [AST][RecoveryExpr] Don't perform early typo correction in C.

2020-10-08 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: sammccall.
Herald added a project: clang.
hokein requested review of this revision.

The dependent mechanism for C error-recovery is mostly finished,
this is the only place we have missed.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D89045

Files:
  clang/lib/Sema/SemaExpr.cpp
  clang/test/AST/ast-dump-recovery.c


Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -24,14 +24,10 @@
 int unary_address = &(a + 1);
 
 // CHECK:   VarDecl {{.*}} ternary 'int' cinit
-// CHECK-NEXT:  `-RecoveryExpr {{.*}}
+// CHECK-NEXT:  `-ConditionalOperator {{.*}}
 // CHECK-NEXT:|-DeclRefExpr {{.*}} 'a'
-// CHECK-NEXT:|-TypoExpr {{.*}}
+// CHECK-NEXT:|-RecoveryExpr {{.*}}
 // CHECK-NEXT:`-DeclRefExpr {{.*}} 'a'
-// FIXME: The TypoExpr should never be print, and should be downgraded to
-// RecoveryExpr -- typo correction is performed too early in C-only codepath,
-// which makes no correction when clang finishes the full expr 
(Sema::Sema::ActOnFinishFullExpr).
-// this will be fixed when we support dependent mechanism and delayed typo 
correction for C.
 int ternary = a ? undef : a;
 
 void test1() {
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -8558,7 +8558,7 @@
 SourceLocation ColonLoc,
 Expr *CondExpr, Expr *LHSExpr,
 Expr *RHSExpr) {
-  if (!getLangOpts().CPlusPlus) {
+  if (!Context.isDependenceAllowed()) {
 // C cannot handle TypoExpr nodes in the condition because it
 // doesn't handle dependent types properly, so make sure any TypoExprs have
 // been dealt with before checking the operands.


Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -24,14 +24,10 @@
 int unary_address = &(a + 1);
 
 // CHECK:   VarDecl {{.*}} ternary 'int' cinit
-// CHECK-NEXT:  `-RecoveryExpr {{.*}}
+// CHECK-NEXT:  `-ConditionalOperator {{.*}}
 // CHECK-NEXT:|-DeclRefExpr {{.*}} 'a'
-// CHECK-NEXT:|-TypoExpr {{.*}}
+// CHECK-NEXT:|-RecoveryExpr {{.*}}
 // CHECK-NEXT:`-DeclRefExpr {{.*}} 'a'
-// FIXME: The TypoExpr should never be print, and should be downgraded to
-// RecoveryExpr -- typo correction is performed too early in C-only codepath,
-// which makes no correction when clang finishes the full expr (Sema::Sema::ActOnFinishFullExpr).
-// this will be fixed when we support dependent mechanism and delayed typo correction for C.
 int ternary = a ? undef : a;
 
 void test1() {
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -8558,7 +8558,7 @@
 SourceLocation ColonLoc,
 Expr *CondExpr, Expr *LHSExpr,
 Expr *RHSExpr) {
-  if (!getLangOpts().CPlusPlus) {
+  if (!Context.isDependenceAllowed()) {
 // C cannot handle TypoExpr nodes in the condition because it
 // doesn't handle dependent types properly, so make sure any TypoExprs have
 // been dealt with before checking the operands.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D89036: [clangd] Add more incomplete_type diagnostics that could be fixed by include-fixer.

2020-10-08 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In D89036#2319320 , @kadircet wrote:

> Tests seem to be failing on premerge bots:
>
> - https://reviews.llvm.org/harbormaster/unit/view/177841/
> - https://reviews.llvm.org/harbormaster/unit/view/177842/

opps, sorry -- I made a few minor changes without rerunning the test, it should 
be fixed now.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89036

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


[PATCH] D89036: [clangd] Add more incomplete_type diagnostics that could be fixed by include-fixer.

2020-10-08 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296961.
hokein added a comment.

Fix the test.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89036

Files:
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -705,11 +705,18 @@
   $nested[[X::]]Nested n;
 }
 class Y : $base[[public ns::X]] {};
-int main() {
-  ns::X *x;
+void test(ns::X *x, ns::X& ref_x) {
   x$access[[->]]f();
   auto& $type[[[]]a] = *x;
+
+  ns::X $incomplete[[var]];
+  $tag[[ref_x]]->f();
+  $use[[ns::X()]];
+  $sizeof[[sizeof]](ns::X);
+  for (auto it : $for[[ref_x]]);
 }
+
+ns::X $return[[func]]() {}
   )cpp");
   auto TU = TestTU::withCode(Test.code());
   TU.ExtraArgs.push_back("-std=c++17");
@@ -739,7 +746,37 @@
"incomplete type 'ns::X' where a complete type is 
required"),
   DiagName("incomplete_type"),
   WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
-  "Add include \"x.h\" for symbol ns::X");
+  "Add include \"x.h\" for symbol ns::X"))),
+  AllOf(Diag(Test.range("incomplete"),
+ "variable has incomplete type 'ns::X'"),
+DiagName("typecheck_decl_incomplete_type"),
+WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(
+  Diag(Test.range("tag"), "incomplete definition of type 'ns::X'"),
+  DiagName("typecheck_incomplete_tag"),
+  WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+  "Add include \"x.h\" for symbol ns::X"))),
+  AllOf(
+  Diag(Test.range("use"), "invalid use of incomplete type 
'ns::X'"),
+  DiagName("invalid_incomplete_type_use"),
+  WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+  "Add include \"x.h\" for symbol ns::X"))),
+  AllOf(Diag(Test.range("sizeof"), "invalid application of 'sizeof' to 
"
+   "an incomplete type 'ns::X'"),
+DiagName("sizeof_alignof_incomplete_or_sizeless_type"),
+WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(Diag(Test.range("for"),
+ "cannot use incomplete type 'ns::X' as a range"),
+DiagName("for_range_incomplete_type"),
+WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(Diag(Test.range("return"),
+ "incomplete result type 'ns::X' in function definition"),
+DiagName("func_def_incomplete_result"),
+WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+"Add include \"x.h\" for symbol ns::X");
 }
 
 TEST(IncludeFixerTest, NoSuggestIncludeWhenNoDefinitionInHeader) {
Index: clang-tools-extra/clangd/IncludeFixer.cpp
===
--- clang-tools-extra/clangd/IncludeFixer.cpp
+++ clang-tools-extra/clangd/IncludeFixer.cpp
@@ -72,6 +72,12 @@
   case diag::err_incomplete_base_class:
   case diag::err_incomplete_member_access:
   case diag::err_incomplete_type:
+  case diag::err_typecheck_decl_incomplete_type:
+  case diag::err_typecheck_incomplete_tag:
+  case diag::err_invalid_incomplete_type_use:
+  case diag::err_sizeof_alignof_incomplete_or_sizeless_type:
+  case diag::err_for_range_incomplete_type:
+  case diag::err_func_def_incomplete_result:
 // Incomplete type diagnostics should have a QualType argument for the
 // incomplete type.
 for (unsigned Idx = 0; Idx < Info.getNumArgs(); ++Idx) {


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -705,11 +705,18 @@
   $nested[[X::]]Nested n;
 }
 class Y : $base[[public ns::X]] {};
-int main() {
-  ns::X *x;
+void test(ns::X *x, ns::X& ref_x) {
   x$access[[->]]f();
   auto& $type[[[]]a] = *x;
+
+  ns::X $incomplete[[var]];
+  $tag[[ref_x]]->f();
+  $use[[ns::X()]];
+  $sizeof[[sizeof]](ns::X);
+  for (auto it : $for[[ref_x]]);
 }
+
+ns::X $return[[func]]() {}
   )cpp");
   auto TU = TestTU::withCode(Test.code());
   TU.ExtraArgs.push_back("-std=c++17");
@@ -739,7 +746,37 @@
"incomplete 

[PATCH] D89036: [clangd] Add more incomplete_type diagnostics that could be fixed by include-fixer.

2020-10-08 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: kadircet.
Herald added subscribers: usaxena95, arphaman.
Herald added a project: clang.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D89036

Files:
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -707,9 +707,18 @@
 class Y : $base[[public ns::X]] {};
 int main() {
   ns::X *x;
+  ns::X& ref_x;
   x$access[[->]]f();
   auto& $type[[[]]a] = *x;
+
+  ns::X $incomplete[[var]];
+  $tag[[ref_x]]->f();
+  $use[[ns::X()]];
+  $sizeof[[sizeof]](ns::X);
+  for (auto it : $for[[ref_x]]);
 }
+
+ns::X $return[[func]]() {}
   )cpp");
   auto TU = TestTU::withCode(Test.code());
   TU.ExtraArgs.push_back("-std=c++17");
@@ -739,7 +748,37 @@
"incomplete type 'ns::X' where a complete type is 
required"),
   DiagName("incomplete_type"),
   WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
-  "Add include \"x.h\" for symbol ns::X");
+  "Add include \"x.h\" for symbol ns::X"))),
+  AllOf(Diag(Test.range("incomplete"),
+ "variable has incomplete type 'ns::X'"),
+DiagName("typecheck_decl_incomplete_type"),
+WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(
+  Diag(Test.range("tag"), "incomplete definition of type 'ns::X'"),
+  DiagName("typecheck_incomplete_tag"),
+  WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+  "Add include \"x.h\" for symbol ns::X"))),
+  AllOf(
+  Diag(Test.range("use"), "invalid use of incomplete type 
'ns::X'"),
+  DiagName("invalid_incomplete_type_use"),
+  WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+  "Add include \"x.h\" for symbol ns::X"))),
+  AllOf(Diag(Test.range("sizeof"), "invalid application of 'sizeof' to 
"
+   "an incomplete type 'ns::X'"),
+DiagName("sizeof_alignof_incomplete_or_sizeless_type"),
+WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(Diag(Test.range("for"),
+ "cannot use incomplete type 'ns::X' as a range"),
+DiagName("for_range_incomplete_type"),
+WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(Diag(Test.range("return"),
+ "incomplete result type 'ns::X' in function definition"),
+DiagName("func_def_incomplete_result"),
+WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+"Add include \"x.h\" for symbol ns::X");
 }
 
 TEST(IncludeFixerTest, NoSuggestIncludeWhenNoDefinitionInHeader) {
Index: clang-tools-extra/clangd/IncludeFixer.cpp
===
--- clang-tools-extra/clangd/IncludeFixer.cpp
+++ clang-tools-extra/clangd/IncludeFixer.cpp
@@ -72,6 +72,12 @@
   case diag::err_incomplete_base_class:
   case diag::err_incomplete_member_access:
   case diag::err_incomplete_type:
+  case diag::err_typecheck_decl_incomplete_type:
+  case diag::err_typecheck_incomplete_tag:
+  case diag::err_invalid_incomplete_type_use:
+  case diag::err_sizeof_alignof_incomplete_or_sizeless_type:
+  case diag::err_for_range_incomplete_type:
+  case diag::err_func_def_incomplete_result:
 // Incomplete type diagnostics should have a QualType argument for the
 // incomplete type.
 for (unsigned Idx = 0; Idx < Info.getNumArgs(); ++Idx) {


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -707,9 +707,18 @@
 class Y : $base[[public ns::X]] {};
 int main() {
   ns::X *x;
+  ns::X& ref_x;
   x$access[[->]]f();
   auto& $type[[[]]a] = *x;
+
+  ns::X $incomplete[[var]];
+  $tag[[ref_x]]->f();
+  $use[[ns::X()]];
+  $sizeof[[sizeof]](ns::X);
+  for (auto it : $for[[ref_x]]);
 }
+
+ns::X $return[[func]]() {}
   )cpp");
   auto TU = TestTU::withCode(Test.code());
   TU.ExtraArgs.push_back("-std=c++17");
@@ -739,7 +748,37 @@
"incomplete type 'ns::X' where a 

[PATCH] D88964: [clangd] Add a missing include-fixer test for incomplete_type, NFC.

2020-10-08 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGa4e27220c2a1: [clangd] Add a missing include-fixer test for 
incomplete_type, NFC. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88964

Files:
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -708,9 +708,11 @@
 int main() {
   ns::X *x;
   x$access[[->]]f();
+  auto& $type[[[]]a] = *x;
 }
   )cpp");
   auto TU = TestTU::withCode(Test.code());
+  TU.ExtraArgs.push_back("-std=c++17");
   auto Index = buildIndexWithSymbol(
   {SymbolWithHeader{"ns::X", "unittest:///x.h", "\"x.h\""}});
   TU.ExternalIndex = Index.get();
@@ -731,7 +733,13 @@
  "member access into incomplete type 'ns::X'"),
 DiagName("incomplete_member_access"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
-"Add include \"x.h\" for symbol ns::X");
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(
+  Diag(Test.range("type"),
+   "incomplete type 'ns::X' where a complete type is 
required"),
+  DiagName("incomplete_type"),
+  WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+  "Add include \"x.h\" for symbol ns::X");
 }
 
 TEST(IncludeFixerTest, NoSuggestIncludeWhenNoDefinitionInHeader) {
Index: clang-tools-extra/clangd/IncludeFixer.cpp
===
--- clang-tools-extra/clangd/IncludeFixer.cpp
+++ clang-tools-extra/clangd/IncludeFixer.cpp
@@ -68,10 +68,10 @@
 std::vector IncludeFixer::fix(DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic ) const {
   switch (Info.getID()) {
-  case diag::err_incomplete_type:
-  case diag::err_incomplete_member_access:
-  case diag::err_incomplete_base_class:
   case diag::err_incomplete_nested_name_spec:
+  case diag::err_incomplete_base_class:
+  case diag::err_incomplete_member_access:
+  case diag::err_incomplete_type:
 // Incomplete type diagnostics should have a QualType argument for the
 // incomplete type.
 for (unsigned Idx = 0; Idx < Info.getNumArgs(); ++Idx) {


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -708,9 +708,11 @@
 int main() {
   ns::X *x;
   x$access[[->]]f();
+  auto& $type[[[]]a] = *x;
 }
   )cpp");
   auto TU = TestTU::withCode(Test.code());
+  TU.ExtraArgs.push_back("-std=c++17");
   auto Index = buildIndexWithSymbol(
   {SymbolWithHeader{"ns::X", "unittest:///x.h", "\"x.h\""}});
   TU.ExternalIndex = Index.get();
@@ -731,7 +733,13 @@
  "member access into incomplete type 'ns::X'"),
 DiagName("incomplete_member_access"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
-"Add include \"x.h\" for symbol ns::X");
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(
+  Diag(Test.range("type"),
+   "incomplete type 'ns::X' where a complete type is required"),
+  DiagName("incomplete_type"),
+  WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+  "Add include \"x.h\" for symbol ns::X");
 }
 
 TEST(IncludeFixerTest, NoSuggestIncludeWhenNoDefinitionInHeader) {
Index: clang-tools-extra/clangd/IncludeFixer.cpp
===
--- clang-tools-extra/clangd/IncludeFixer.cpp
+++ clang-tools-extra/clangd/IncludeFixer.cpp
@@ -68,10 +68,10 @@
 std::vector IncludeFixer::fix(DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic ) const {
   switch (Info.getID()) {
-  case diag::err_incomplete_type:
-  case diag::err_incomplete_member_access:
-  case diag::err_incomplete_base_class:
   case diag::err_incomplete_nested_name_spec:
+  case diag::err_incomplete_base_class:
+  case diag::err_incomplete_member_access:
+  case diag::err_incomplete_type:
 // Incomplete type diagnostics should have a QualType argument for the
 // incomplete type.
 for (unsigned Idx = 0; Idx < Info.getNumArgs(); ++Idx) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org

[PATCH] D88964: [clangd] Add a missing include-fixer test for incomplete_type, NFC.

2020-10-08 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp:738
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(Diag(Test.range("nested"),
+ "incomplete type 'ns::X' named in nested name specifier"),

kadircet wrote:
> hokein wrote:
> > kadircet wrote:
> > > can you move this back to original position ?
> > yeah, I reordered the list.
> > 
> > there are two orders: the one listed here, and the one listed in 
> > `IncludeFixer.cpp`.
> > 
> > The motivation is to make them aligned, so that it would be easier to 
> > compare and spot the difference. The current state is not friendly to 
> > readers.
> i don't think the orderings in the source vs test is that relevant, but SGTM 
> if it helps you. mainly because:
> - as it might be harder in future to trigger diagnostics in the order we want
> - it is an invariant hard to maintain without at least the reviewer or author 
> of changes knowing about(and remembering) it
yeah, it does help me, especially when I start adding more diagnostics.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88964

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


[PATCH] D84304: [AST][RecoveryExpr] Part 2: Build dependent callexpr in C for error-recovery.

2020-10-08 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296885.
hokein added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84304

Files:
  clang/lib/Sema/SemaExpr.cpp
  clang/test/AST/ast-dump-recovery.c
  clang/test/Sema/error-dependence.c


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -10,6 +10,9 @@
   // verify diagnostic "operand of type '' where arithmetic or
   // pointer type is required" is not emitted.
   (float)call(); // expected-error {{too few arguments to function call}}
+  // verify disgnostic "called object type '' is not a function
+  // or function pointer" is not emitted.
+  (*__builtin_classify_type)(1); // expected-error {{builtin functions must be 
directly called}}
 }
 
 void test2(int* ptr, float f) {
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -87,3 +87,18 @@
   // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
   (float)some_func();
 }
+
+void test3() {
+  // CHECK: CallExpr {{.*}} '' contains-errors
+  // CHECK-NEXT: |-ParenExpr {{.*}} contains-errors lvalue
+  // CHECK-NEXT: | `-RecoveryExpr {{.*}} contains-errors
+  // CHECK-NEXT: |   `-DeclRefExpr {{.*}} '__builtin_classify_type'
+  // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+  (*__builtin_classify_type)(1);
+
+  extern void ext();
+  // CHECK: CallExpr {{.*}} 'void' contains-errors
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'ext'
+  // CHECK-NEXT: `-RecoveryExpr {{.*}} ''
+  ext(undef_var);
+}
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -6439,6 +6439,21 @@
 checkDirectCallValidity(*this, Fn, FD, ArgExprs);
   }
 
+  if (Context.isDependenceAllowed() &&
+  (Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(ArgExprs))) 
{
+assert(!getLangOpts().CPlusPlus);
+assert(Fn->containsErrors() ||
+   llvm::any_of(ArgExprs,
+[](clang::Expr *E) { return E->containsErrors(); }) &&
+   "should only occur in error-recovery path.");
+QualType ReturnType =
+llvm::isa_and_nonnull(NDecl)
+? dyn_cast(NDecl)->getCallResultType()
+: Context.DependentTy;
+return CallExpr::Create(Context, Fn, ArgExprs, ReturnType,
+Expr::getValueKindForType(ReturnType), RParenLoc,
+CurFPFeatureOverrides());
+  }
   return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs, RParenLoc,
ExecConfig, IsExecConfig);
 }
@@ -6579,7 +6594,7 @@
  CurFPFeatureOverrides(), NumParams, UsesADL);
   }
 
-  if (!getLangOpts().CPlusPlus) {
+  if (!Context.isDependenceAllowed()) {
 // Forget about the nulled arguments since typo correction
 // do not handle them well.
 TheCall->shrinkNumArgs(Args.size());
@@ -19116,7 +19131,7 @@
 /// Check for operands with placeholder types and complain if found.
 /// Returns ExprError() if there was an error and no recovery was possible.
 ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
-  if (!getLangOpts().CPlusPlus) {
+  if (!Context.isDependenceAllowed()) {
 // C cannot handle TypoExpr nodes on either side of a binop because it
 // doesn't handle dependent types properly, so make sure any TypoExprs have
 // been dealt with before checking the operands.


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -10,6 +10,9 @@
   // verify diagnostic "operand of type '' where arithmetic or
   // pointer type is required" is not emitted.
   (float)call(); // expected-error {{too few arguments to function call}}
+  // verify disgnostic "called object type '' is not a function
+  // or function pointer" is not emitted.
+  (*__builtin_classify_type)(1); // expected-error {{builtin functions must be directly called}}
 }
 
 void test2(int* ptr, float f) {
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -87,3 +87,18 @@
   // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
   (float)some_func();
 }
+
+void test3() {
+  // CHECK: CallExpr {{.*}} '' contains-errors
+  // CHECK-NEXT: |-ParenExpr {{.*}} contains-errors lvalue
+  // CHECK-NEXT: | `-RecoveryExpr {{.*}} contains-errors
+  // CHECK-NEXT: |   `-DeclRefExpr {{.*}} '__builtin_classify_type'
+  // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+  (*__builtin_classify_type)(1);
+
+ 

[PATCH] D84387: [AST][RecoveryExpr] Part4: Support dependent cast-expr in C for error-recovery.

2020-10-08 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGa96bcfb19674: [AST][RecoveryExpr] Support dependent 
cast-expr in C for error-recovery. (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D84387?vs=296611=296882#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84387

Files:
  clang/lib/Sema/SemaCast.cpp
  clang/test/AST/ast-dump-recovery.c
  clang/test/Sema/error-dependence.c


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -1,11 +1,15 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -frecovery-ast -fno-recovery-ast-type 
%s
 
-int call(int); // expected-note2 {{'call' declared here}}
+int call(int); // expected-note3 {{'call' declared here}}
 
 void test1(int s) {
   // verify "assigning to 'int' from incompatible type ''" is
   // not emitted.
   s = call(); // expected-error {{too few arguments to function call}}
+
+  // verify diagnostic "operand of type '' where arithmetic or
+  // pointer type is required" is not emitted.
+  (float)call(); // expected-error {{too few arguments to function call}}
 }
 
 void test2(int* ptr, float f) {
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -81,4 +81,9 @@
   // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int *' lvalue
   // CHECK-NEXT: `-DeclRefExpr {{.*}} 'float' lvalue
   (ptr > f ? ptr : f);
+
+  // CHECK: CStyleCastExpr {{.*}} 'float' contains-errors 
+  // CHECK-NEXT: `-RecoveryExpr {{.*}} ''
+  // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
+  (float)some_func();
 }
Index: clang/lib/Sema/SemaCast.cpp
===
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -2707,6 +2707,17 @@
 return;
   }
 
+  // If the type is dependent, we won't do any other semantic analysis now.
+  if (Self.getASTContext().isDependenceAllowed() &&
+  (DestType->isDependentType() || SrcExpr.get()->isTypeDependent() ||
+   SrcExpr.get()->isValueDependent())) {
+assert((DestType->containsErrors() || SrcExpr.get()->containsErrors() ||
+SrcExpr.get()->containsErrors()) &&
+   "should only occur in error-recovery path.");
+assert(Kind == CK_Dependent);
+return;
+  }
+
   // Overloads are allowed with C extensions, so we need to support them.
   if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
 DeclAccessPair DAP;


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -1,11 +1,15 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -frecovery-ast -fno-recovery-ast-type %s
 
-int call(int); // expected-note2 {{'call' declared here}}
+int call(int); // expected-note3 {{'call' declared here}}
 
 void test1(int s) {
   // verify "assigning to 'int' from incompatible type ''" is
   // not emitted.
   s = call(); // expected-error {{too few arguments to function call}}
+
+  // verify diagnostic "operand of type '' where arithmetic or
+  // pointer type is required" is not emitted.
+  (float)call(); // expected-error {{too few arguments to function call}}
 }
 
 void test2(int* ptr, float f) {
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -81,4 +81,9 @@
   // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int *' lvalue
   // CHECK-NEXT: `-DeclRefExpr {{.*}} 'float' lvalue
   (ptr > f ? ptr : f);
+
+  // CHECK: CStyleCastExpr {{.*}} 'float' contains-errors 
+  // CHECK-NEXT: `-RecoveryExpr {{.*}} ''
+  // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
+  (float)some_func();
 }
Index: clang/lib/Sema/SemaCast.cpp
===
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -2707,6 +2707,17 @@
 return;
   }
 
+  // If the type is dependent, we won't do any other semantic analysis now.
+  if (Self.getASTContext().isDependenceAllowed() &&
+  (DestType->isDependentType() || SrcExpr.get()->isTypeDependent() ||
+   SrcExpr.get()->isValueDependent())) {
+assert((DestType->containsErrors() || SrcExpr.get()->containsErrors() ||
+SrcExpr.get()->containsErrors()) &&
+   "should only occur in error-recovery path.");
+assert(Kind == CK_Dependent);
+return;
+  }
+
   // Overloads are allowed with C extensions, so we need to support them.
   if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
 DeclAccessPair DAP;

[PATCH] D88881: [clangd] Add a NewName optional parameter to clangdServer::prepareRename.

2020-10-08 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/ClangdServer.h:277
+  ///
+  /// If NewName is provided, it peforms a name validation.
   void prepareRename(PathRef File, Position Pos,

danielmartin wrote:
> 
oh, thanks! Fixed in ba268d2fb09ceabfa03a6499258f973be62d7663.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D1

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


[PATCH] D88881: [clangd] Add a NewName optional parameter to clangdServer::prepareRename.

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG9c09e2055ee4: [clangd] Add a NewName optional parameter to 
clangdServer::prepareRename. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D1

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/unittests/RenameTests.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.h

Index: clang-tools-extra/clangd/unittests/SyncAPI.h
===
--- clang-tools-extra/clangd/unittests/SyncAPI.h
+++ clang-tools-extra/clangd/unittests/SyncAPI.h
@@ -46,6 +46,7 @@
 
 llvm::Expected
 runPrepareRename(ClangdServer , PathRef File, Position Pos,
+ llvm::Optional NewName,
  const clangd::RenameOptions );
 
 llvm::Expected
Index: clang-tools-extra/clangd/unittests/SyncAPI.cpp
===
--- clang-tools-extra/clangd/unittests/SyncAPI.cpp
+++ clang-tools-extra/clangd/unittests/SyncAPI.cpp
@@ -105,11 +105,12 @@
   return std::move(*Result);
 }
 
-llvm::Expected runPrepareRename(ClangdServer ,
-  PathRef File, Position Pos,
-  const RenameOptions ) {
+llvm::Expected
+runPrepareRename(ClangdServer , PathRef File, Position Pos,
+ llvm::Optional NewName,
+ const RenameOptions ) {
   llvm::Optional> Result;
-  Server.prepareRename(File, Pos, RenameOpts, capture(Result));
+  Server.prepareRename(File, Pos, NewName, RenameOpts, capture(Result));
   return std::move(*Result);
 }
 
Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -730,8 +730,8 @@
   runAddDocument(Server, FooHPath, FooH.code());
   runAddDocument(Server, FooCCPath, FooCC.code());
 
-  auto Results =
-  runPrepareRename(Server, FooCCPath, FooCC.point(), {/*CrossFile=*/true});
+  auto Results = runPrepareRename(Server, FooCCPath, FooCC.point(),
+  /*NewName=*/llvm::None, {/*CrossFile=*/true});
   // verify that for multi-file rename, we only return main-file occurrences.
   ASSERT_TRUE(bool(Results)) << Results.takeError();
   // We don't know the result is complete in prepareRename (passing a nullptr
@@ -740,9 +740,17 @@
   EXPECT_THAT(FooCC.ranges(),
   testing::UnorderedElementsAreArray(Results->LocalChanges));
 
-  // single-file rename on global symbols, we should report an error.
+  // verify name validation.
   Results =
-  runPrepareRename(Server, FooCCPath, FooCC.point(), {/*CrossFile=*/false});
+  runPrepareRename(Server, FooCCPath, FooCC.point(),
+   /*NewName=*/std::string("int"), {/*CrossFile=*/true});
+  EXPECT_FALSE(Results);
+  EXPECT_THAT(llvm::toString(Results.takeError()),
+  testing::HasSubstr("keyword"));
+
+  // single-file rename on global symbols, we should report an error.
+  Results = runPrepareRename(Server, FooCCPath, FooCC.point(),
+ /*NewName=*/llvm::None, {/*CrossFile=*/false});
   EXPECT_FALSE(Results);
   EXPECT_THAT(llvm::toString(Results.takeError()),
   testing::HasSubstr("is used outside"));
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -273,7 +273,10 @@
 StringRef TriggerText, Callback> CB);
 
   /// Test the validity of a rename operation.
+  ///
+  /// If NewName is provided, it peforms a name validation.
   void prepareRename(PathRef File, Position Pos,
+ llvm::Optional NewName,
  const RenameOptions ,
  Callback CB);
 
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -399,9 +399,11 @@
 }
 
 void ClangdServer::prepareRename(PathRef File, Position Pos,
+ llvm::Optional NewName,
  const RenameOptions ,
  Callback CB) {
-  auto Action = [Pos, File = File.str(), CB = std::move(CB), RenameOpts,
+  auto Action = [Pos, File = File.str(), CB = std::move(CB),
+ NewName = std::move(NewName), RenameOpts,
  this](llvm::Expected InpAST) mutable {
 if (!InpAST)
   return CB(InpAST.takeError());

[PATCH] D88964: [clangd] Add a missing include-fixer test for incomplete_type, NFC.

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296767.
hokein added a comment.

update: don't change the order in test.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88964

Files:
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -708,9 +708,11 @@
 int main() {
   ns::X *x;
   x$access[[->]]f();
+  auto& $type[[[]]a] = *x;
 }
   )cpp");
   auto TU = TestTU::withCode(Test.code());
+  TU.ExtraArgs.push_back("-std=c++17");
   auto Index = buildIndexWithSymbol(
   {SymbolWithHeader{"ns::X", "unittest:///x.h", "\"x.h\""}});
   TU.ExternalIndex = Index.get();
@@ -731,7 +733,13 @@
  "member access into incomplete type 'ns::X'"),
 DiagName("incomplete_member_access"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
-"Add include \"x.h\" for symbol ns::X");
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(
+  Diag(Test.range("type"),
+   "incomplete type 'ns::X' where a complete type is 
required"),
+  DiagName("incomplete_type"),
+  WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+  "Add include \"x.h\" for symbol ns::X");
 }
 
 TEST(IncludeFixerTest, NoSuggestIncludeWhenNoDefinitionInHeader) {
Index: clang-tools-extra/clangd/IncludeFixer.cpp
===
--- clang-tools-extra/clangd/IncludeFixer.cpp
+++ clang-tools-extra/clangd/IncludeFixer.cpp
@@ -68,10 +68,10 @@
 std::vector IncludeFixer::fix(DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic ) const {
   switch (Info.getID()) {
-  case diag::err_incomplete_type:
-  case diag::err_incomplete_member_access:
-  case diag::err_incomplete_base_class:
   case diag::err_incomplete_nested_name_spec:
+  case diag::err_incomplete_base_class:
+  case diag::err_incomplete_member_access:
+  case diag::err_incomplete_type:
 // Incomplete type diagnostics should have a QualType argument for the
 // incomplete type.
 for (unsigned Idx = 0; Idx < Info.getNumArgs(); ++Idx) {


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -708,9 +708,11 @@
 int main() {
   ns::X *x;
   x$access[[->]]f();
+  auto& $type[[[]]a] = *x;
 }
   )cpp");
   auto TU = TestTU::withCode(Test.code());
+  TU.ExtraArgs.push_back("-std=c++17");
   auto Index = buildIndexWithSymbol(
   {SymbolWithHeader{"ns::X", "unittest:///x.h", "\"x.h\""}});
   TU.ExternalIndex = Index.get();
@@ -731,7 +733,13 @@
  "member access into incomplete type 'ns::X'"),
 DiagName("incomplete_member_access"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
-"Add include \"x.h\" for symbol ns::X");
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(
+  Diag(Test.range("type"),
+   "incomplete type 'ns::X' where a complete type is required"),
+  DiagName("incomplete_type"),
+  WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+  "Add include \"x.h\" for symbol ns::X");
 }
 
 TEST(IncludeFixerTest, NoSuggestIncludeWhenNoDefinitionInHeader) {
Index: clang-tools-extra/clangd/IncludeFixer.cpp
===
--- clang-tools-extra/clangd/IncludeFixer.cpp
+++ clang-tools-extra/clangd/IncludeFixer.cpp
@@ -68,10 +68,10 @@
 std::vector IncludeFixer::fix(DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic ) const {
   switch (Info.getID()) {
-  case diag::err_incomplete_type:
-  case diag::err_incomplete_member_access:
-  case diag::err_incomplete_base_class:
   case diag::err_incomplete_nested_name_spec:
+  case diag::err_incomplete_base_class:
+  case diag::err_incomplete_member_access:
+  case diag::err_incomplete_type:
 // Incomplete type diagnostics should have a QualType argument for the
 // incomplete type.
 for (unsigned Idx = 0; Idx < Info.getNumArgs(); ++Idx) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D88964: [clangd] Add a missing include-fixer test for incomplete_type, NFC.

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp:709
   ns::X *x;
+  auto& $type[[[]]a] = *x;
   x$access[[->]]f();

kadircet wrote:
> should this be `$type[[a]]` ?
yeah, but this is the actual diagnostic range, though it is wired. 



Comment at: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp:715
   auto TU = TestTU::withCode(Test.code());
+  TU.ExtraArgs.push_back("-std=c++17");
   auto Index = buildIndexWithSymbol(

kadircet wrote:
> why do we need c++17 ?
The newly-added test case is using C++17 feature (structure binding), needs 
this flag to suppress a diagnostic warning. 




Comment at: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp:738
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(Diag(Test.range("nested"),
+ "incomplete type 'ns::X' named in nested name specifier"),

kadircet wrote:
> can you move this back to original position ?
yeah, I reordered the list.

there are two orders: the one listed here, and the one listed in 
`IncludeFixer.cpp`.

The motivation is to make them aligned, so that it would be easier to compare 
and spot the difference. The current state is not friendly to readers.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88964

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


[PATCH] D88964: [clangd] Add a missing include-fixer test for incomplete_type, NFC.

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: kadircet.
Herald added subscribers: usaxena95, arphaman.
Herald added a project: clang.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

Also sort the list to make it easier to verify with the implementation
code.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D88964

Files:
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -702,15 +702,17 @@
   Annotations Test(R"cpp(// error-ok
 $insert[[]]namespace ns {
   class X;
-  $nested[[X::]]Nested n;
 }
 class Y : $base[[public ns::X]] {};
 int main() {
   ns::X *x;
+  auto& $type[[[]]a] = *x;
   x$access[[->]]f();
+  $nested[[ns::X::]]Nested n;
 }
   )cpp");
   auto TU = TestTU::withCode(Test.code());
+  TU.ExtraArgs.push_back("-std=c++17");
   auto Index = buildIndexWithSymbol(
   {SymbolWithHeader{"ns::X", "unittest:///x.h", "\"x.h\""}});
   TU.ExternalIndex = Index.get();
@@ -718,18 +720,24 @@
   EXPECT_THAT(
   TU.build().getDiagnostics(),
   UnorderedElementsAre(
-  AllOf(Diag(Test.range("nested"),
- "incomplete type 'ns::X' named in nested name specifier"),
-DiagName("incomplete_nested_name_spec"),
-WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
-"Add include \"x.h\" for symbol ns::X"))),
   AllOf(Diag(Test.range("base"), "base class has incomplete type"),
 DiagName("incomplete_base_class"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
 "Add include \"x.h\" for symbol ns::X"))),
+  AllOf(
+  Diag(Test.range("type"),
+   "incomplete type 'ns::X' where a complete type is 
required"),
+  DiagName("incomplete_type"),
+  WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+  "Add include \"x.h\" for symbol ns::X"))),
   AllOf(Diag(Test.range("access"),
  "member access into incomplete type 'ns::X'"),
 DiagName("incomplete_member_access"),
+WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+"Add include \"x.h\" for symbol ns::X"))),
+  AllOf(Diag(Test.range("nested"),
+ "incomplete type 'ns::X' named in nested name specifier"),
+DiagName("incomplete_nested_name_spec"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
 "Add include \"x.h\" for symbol ns::X");
 }
Index: clang-tools-extra/clangd/IncludeFixer.cpp
===
--- clang-tools-extra/clangd/IncludeFixer.cpp
+++ clang-tools-extra/clangd/IncludeFixer.cpp
@@ -68,9 +68,9 @@
 std::vector IncludeFixer::fix(DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic ) const {
   switch (Info.getID()) {
+  case diag::err_incomplete_base_class:
   case diag::err_incomplete_type:
   case diag::err_incomplete_member_access:
-  case diag::err_incomplete_base_class:
   case diag::err_incomplete_nested_name_spec:
 // Incomplete type diagnostics should have a QualType argument for the
 // incomplete type.


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -702,15 +702,17 @@
   Annotations Test(R"cpp(// error-ok
 $insert[[]]namespace ns {
   class X;
-  $nested[[X::]]Nested n;
 }
 class Y : $base[[public ns::X]] {};
 int main() {
   ns::X *x;
+  auto& $type[[[]]a] = *x;
   x$access[[->]]f();
+  $nested[[ns::X::]]Nested n;
 }
   )cpp");
   auto TU = TestTU::withCode(Test.code());
+  TU.ExtraArgs.push_back("-std=c++17");
   auto Index = buildIndexWithSymbol(
   {SymbolWithHeader{"ns::X", "unittest:///x.h", "\"x.h\""}});
   TU.ExternalIndex = Index.get();
@@ -718,18 +720,24 @@
   EXPECT_THAT(
   TU.build().getDiagnostics(),
   UnorderedElementsAre(
-  AllOf(Diag(Test.range("nested"),
- "incomplete type 'ns::X' named in nested name specifier"),
-DiagName("incomplete_nested_name_spec"),
-WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
-"Add include \"x.h\" for symbol ns::X"))),
   AllOf(Diag(Test.range("base"), "base class has incomplete type"),
 DiagName("incomplete_base_class"),
 

[PATCH] D84304: [AST][RecoveryExpr] Part 2: Build dependent callexpr in C for error-recovery.

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang/lib/Sema/SemaExpr.cpp:6444
+   "should only occur in error-recovery path.");
+return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy,
+VK_RValue, RParenLoc);

sammccall wrote:
> sammccall wrote:
> > Is this really the right place vs in BuildResolvedCallExpr?
> why DependentTy? shouldn't it be the return type of the function, if 
> available?
> Is this really the right place vs in BuildResolvedCallExpr?

BuildResolvedCallExpr does some semantic analysis/check, it might emit 
diagnostics, which we want to avoid. And putting the logic here also aligns 
with what C++ code path does.

> why DependentTy? shouldn't it be the return type of the function, if 
> available?

oh, yeah, I missed this. Added.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84304

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


[PATCH] D84304: [AST][RecoveryExpr] Part 2: Build dependent callexpr in C for error-recovery.

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296634.
hokein added a comment.

fix format.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84304

Files:
  clang/lib/Sema/SemaExpr.cpp
  clang/test/AST/ast-dump-recovery.c
  clang/test/Sema/error-dependence.c


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -6,6 +6,10 @@
   // verify "assigning to 'int' from incompatible type ''" is
   // not emitted.
   s = call(); // expected-error {{too few arguments to function call}}
+
+  // verify disgnostic "called object type '' is not a function
+  // or function pointer" is not emitted.
+  (*__builtin_classify_type)(1); // expected-error {{builtin functions must be 
directly called}}
 }
 
 void test2(int* ptr, float f) {
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -82,3 +82,18 @@
   // CHECK-NEXT: `-DeclRefExpr {{.*}} 'float' lvalue
   (ptr > f ? ptr : f);
 }
+
+void test3() {
+  // CHECK: CallExpr {{.*}} '' contains-errors
+  // CHECK-NEXT: |-ParenExpr {{.*}} contains-errors lvalue
+  // CHECK-NEXT: | `-RecoveryExpr {{.*}} contains-errors
+  // CHECK-NEXT: |   `-DeclRefExpr {{.*}} '__builtin_classify_type'
+  // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+  (*__builtin_classify_type)(1);
+
+  extern void ext();
+  // CHECK: CallExpr {{.*}} 'void' contains-errors
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'ext'
+  // CHECK-NEXT: `-RecoveryExpr {{.*}} ''
+  ext(undef_var);
+}
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -6439,6 +6439,21 @@
 checkDirectCallValidity(*this, Fn, FD, ArgExprs);
   }
 
+  if (Context.isDependenceAllowed() &&
+  (Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(ArgExprs))) 
{
+assert(!getLangOpts().CPlusPlus);
+assert(Fn->containsErrors() ||
+   llvm::any_of(ArgExprs,
+[](clang::Expr *E) { return E->containsErrors(); }) &&
+   "should only occur in error-recovery path.");
+QualType ReturnType =
+llvm::isa_and_nonnull(NDecl)
+? dyn_cast(NDecl)->getCallResultType()
+: Context.DependentTy;
+return CallExpr::Create(Context, Fn, ArgExprs, ReturnType,
+Expr::getValueKindForType(ReturnType), RParenLoc,
+CurFPFeatureOverrides());
+  }
   return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs, RParenLoc,
ExecConfig, IsExecConfig);
 }
@@ -6579,7 +6594,7 @@
  CurFPFeatureOverrides(), NumParams, UsesADL);
   }
 
-  if (!getLangOpts().CPlusPlus) {
+  if (!Context.isDependenceAllowed()) {
 // Forget about the nulled arguments since typo correction
 // do not handle them well.
 TheCall->shrinkNumArgs(Args.size());
@@ -19116,7 +19131,7 @@
 /// Check for operands with placeholder types and complain if found.
 /// Returns ExprError() if there was an error and no recovery was possible.
 ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
-  if (!getLangOpts().CPlusPlus) {
+  if (!Context.isDependenceAllowed()) {
 // C cannot handle TypoExpr nodes on either side of a binop because it
 // doesn't handle dependent types properly, so make sure any TypoExprs have
 // been dealt with before checking the operands.


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -6,6 +6,10 @@
   // verify "assigning to 'int' from incompatible type ''" is
   // not emitted.
   s = call(); // expected-error {{too few arguments to function call}}
+
+  // verify disgnostic "called object type '' is not a function
+  // or function pointer" is not emitted.
+  (*__builtin_classify_type)(1); // expected-error {{builtin functions must be directly called}}
 }
 
 void test2(int* ptr, float f) {
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -82,3 +82,18 @@
   // CHECK-NEXT: `-DeclRefExpr {{.*}} 'float' lvalue
   (ptr > f ? ptr : f);
 }
+
+void test3() {
+  // CHECK: CallExpr {{.*}} '' contains-errors
+  // CHECK-NEXT: |-ParenExpr {{.*}} contains-errors lvalue
+  // CHECK-NEXT: | `-RecoveryExpr {{.*}} contains-errors
+  // CHECK-NEXT: |   `-DeclRefExpr {{.*}} '__builtin_classify_type'
+  // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+  (*__builtin_classify_type)(1);
+
+  extern void ext();
+  // CHECK: CallExpr {{.*}} 

[PATCH] D84304: [AST][RecoveryExpr] Part 2: Build dependent callexpr in C for error-recovery.

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296633.
hokein marked 4 inline comments as done.
hokein added a comment.

address comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84304

Files:
  clang/lib/Sema/SemaExpr.cpp
  clang/test/AST/ast-dump-recovery.c
  clang/test/Sema/error-dependence.c


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -6,6 +6,10 @@
   // verify "assigning to 'int' from incompatible type ''" is
   // not emitted.
   s = call(); // expected-error {{too few arguments to function call}}
+
+  // verify disgnostic "called object type '' is not a function
+  // or function pointer" is not emitted.
+  (*__builtin_classify_type)(1); // expected-error {{builtin functions must be 
directly called}}
 }
 
 void test2(int* ptr, float f) {
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -82,3 +82,18 @@
   // CHECK-NEXT: `-DeclRefExpr {{.*}} 'float' lvalue
   (ptr > f ? ptr : f);
 }
+
+void test3() {
+  // CHECK: CallExpr {{.*}} '' contains-errors
+  // CHECK-NEXT: |-ParenExpr {{.*}} contains-errors lvalue
+  // CHECK-NEXT: | `-RecoveryExpr {{.*}} contains-errors
+  // CHECK-NEXT: |   `-DeclRefExpr {{.*}} '__builtin_classify_type'
+  // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+  (*__builtin_classify_type)(1);
+
+  extern void ext();
+  // CHECK: CallExpr {{.*}} 'void' contains-errors
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'ext'
+  // CHECK-NEXT: `-RecoveryExpr {{.*}} ''
+  ext(undef_var);
+}
\ No newline at end of file
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -6439,6 +6439,21 @@
 checkDirectCallValidity(*this, Fn, FD, ArgExprs);
   }
 
+  if (Context.isDependenceAllowed() &&
+  (Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(ArgExprs))) 
{
+assert(!getLangOpts().CPlusPlus);
+assert(Fn->containsErrors() ||
+   llvm::any_of(ArgExprs,
+[](clang::Expr *E) { return E->containsErrors(); }) &&
+   "should only occur in error-recovery path.");
+QualType ReturnType =
+llvm::isa_and_nonnull(NDecl)
+? dyn_cast(NDecl)->getCallResultType()
+: Context.DependentTy;
+return CallExpr::Create(Context, Fn, ArgExprs, ReturnType,
+Expr::getValueKindForType(ReturnType), RParenLoc,
+CurFPFeatureOverrides());
+  }
   return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs, RParenLoc,
ExecConfig, IsExecConfig);
 }
@@ -6579,7 +6594,7 @@
  CurFPFeatureOverrides(), NumParams, UsesADL);
   }
 
-  if (!getLangOpts().CPlusPlus) {
+  if (!Context.isDependenceAllowed()) {
 // Forget about the nulled arguments since typo correction
 // do not handle them well.
 TheCall->shrinkNumArgs(Args.size());
@@ -19116,7 +19131,7 @@
 /// Check for operands with placeholder types and complain if found.
 /// Returns ExprError() if there was an error and no recovery was possible.
 ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
-  if (!getLangOpts().CPlusPlus) {
+  if (!Context.isDependenceAllowed()) {
 // C cannot handle TypoExpr nodes on either side of a binop because it
 // doesn't handle dependent types properly, so make sure any TypoExprs have
 // been dealt with before checking the operands.


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -6,6 +6,10 @@
   // verify "assigning to 'int' from incompatible type ''" is
   // not emitted.
   s = call(); // expected-error {{too few arguments to function call}}
+
+  // verify disgnostic "called object type '' is not a function
+  // or function pointer" is not emitted.
+  (*__builtin_classify_type)(1); // expected-error {{builtin functions must be directly called}}
 }
 
 void test2(int* ptr, float f) {
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -82,3 +82,18 @@
   // CHECK-NEXT: `-DeclRefExpr {{.*}} 'float' lvalue
   (ptr > f ? ptr : f);
 }
+
+void test3() {
+  // CHECK: CallExpr {{.*}} '' contains-errors
+  // CHECK-NEXT: |-ParenExpr {{.*}} contains-errors lvalue
+  // CHECK-NEXT: | `-RecoveryExpr {{.*}} contains-errors
+  // CHECK-NEXT: |   `-DeclRefExpr {{.*}} '__builtin_classify_type'
+  // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+  

[PATCH] D88881: [clangd] Add a NewName optional parameter to clangdServer::prepareRename.

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In D1#2313863 , @sammccall wrote:

> Can you add a bit more context to the commit message?
>
> And should we expose this as an extension on `textDocument/prepareRename`?

no needed right now. AFAIK, there are no lsp clients that would use that.




Comment at: clang-tools-extra/clangd/ClangdServer.cpp:404
  const RenameOptions ,
  Callback CB) {
+  auto Action = [Pos, File = File.str(), CB = std::move(CB),

sammccall wrote:
> we can fail already here if the name is specified and empty
yeah, we could do that, but not sure this is a good idea:

- adding special-case code (I'd like to avoid)
- error-message might be re-prioritized -- if an invalid pos, and empty new 
name are passed through this API, we will emit error message "the name is 
empty" rather than "no symbol was found", I think "no symbol was found" is 
slightly more important than the "name is empty"; 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D1

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


[PATCH] D88881: [clangd] Add a NewName optional parameter to clangdServer::prepareRename.

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296622.
hokein marked an inline comment as done.
hokein added a comment.

make NewName optional.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D1

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/unittests/RenameTests.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.h

Index: clang-tools-extra/clangd/unittests/SyncAPI.h
===
--- clang-tools-extra/clangd/unittests/SyncAPI.h
+++ clang-tools-extra/clangd/unittests/SyncAPI.h
@@ -46,6 +46,7 @@
 
 llvm::Expected
 runPrepareRename(ClangdServer , PathRef File, Position Pos,
+ llvm::Optional NewName,
  const clangd::RenameOptions );
 
 llvm::Expected
Index: clang-tools-extra/clangd/unittests/SyncAPI.cpp
===
--- clang-tools-extra/clangd/unittests/SyncAPI.cpp
+++ clang-tools-extra/clangd/unittests/SyncAPI.cpp
@@ -105,11 +105,12 @@
   return std::move(*Result);
 }
 
-llvm::Expected runPrepareRename(ClangdServer ,
-  PathRef File, Position Pos,
-  const RenameOptions ) {
+llvm::Expected
+runPrepareRename(ClangdServer , PathRef File, Position Pos,
+ llvm::Optional NewName,
+ const RenameOptions ) {
   llvm::Optional> Result;
-  Server.prepareRename(File, Pos, RenameOpts, capture(Result));
+  Server.prepareRename(File, Pos, NewName, RenameOpts, capture(Result));
   return std::move(*Result);
 }
 
Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -730,8 +730,8 @@
   runAddDocument(Server, FooHPath, FooH.code());
   runAddDocument(Server, FooCCPath, FooCC.code());
 
-  auto Results =
-  runPrepareRename(Server, FooCCPath, FooCC.point(), {/*CrossFile=*/true});
+  auto Results = runPrepareRename(Server, FooCCPath, FooCC.point(),
+  /*NewName=*/llvm::None, {/*CrossFile=*/true});
   // verify that for multi-file rename, we only return main-file occurrences.
   ASSERT_TRUE(bool(Results)) << Results.takeError();
   // We don't know the result is complete in prepareRename (passing a nullptr
@@ -740,9 +740,17 @@
   EXPECT_THAT(FooCC.ranges(),
   testing::UnorderedElementsAreArray(Results->LocalChanges));
 
-  // single-file rename on global symbols, we should report an error.
+  // verify name validation.
   Results =
-  runPrepareRename(Server, FooCCPath, FooCC.point(), {/*CrossFile=*/false});
+  runPrepareRename(Server, FooCCPath, FooCC.point(),
+   /*NewName=*/std::string("int"), {/*CrossFile=*/true});
+  EXPECT_FALSE(Results);
+  EXPECT_THAT(llvm::toString(Results.takeError()),
+  testing::HasSubstr("keyword"));
+
+  // single-file rename on global symbols, we should report an error.
+  Results = runPrepareRename(Server, FooCCPath, FooCC.point(),
+ /*NewName=*/llvm::None, {/*CrossFile=*/false});
   EXPECT_FALSE(Results);
   EXPECT_THAT(llvm::toString(Results.takeError()),
   testing::HasSubstr("is used outside"));
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -273,7 +273,10 @@
 StringRef TriggerText, Callback> CB);
 
   /// Test the validity of a rename operation.
+  ///
+  /// If NewName is provided, it peforms a name validation.
   void prepareRename(PathRef File, Position Pos,
+ llvm::Optional NewName,
  const RenameOptions ,
  Callback CB);
 
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -399,9 +399,11 @@
 }
 
 void ClangdServer::prepareRename(PathRef File, Position Pos,
+ llvm::Optional NewName,
  const RenameOptions ,
  Callback CB) {
-  auto Action = [Pos, File = File.str(), CB = std::move(CB), RenameOpts,
+  auto Action = [Pos, File = File.str(), CB = std::move(CB),
+ NewName = std::move(NewName), RenameOpts,
  this](llvm::Expected InpAST) mutable {
 if (!InpAST)
   return CB(InpAST.takeError());
@@ -413,7 +415,7 @@
 //the cost, thus the result may be 

[PATCH] D88472: [clangd] Don't set the Underlying bit on targets of UsingDecls.

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGf24649b77d85: [clangd] Dont set the Underlying bit on 
targets of UsingDecls. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88472

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/FindTarget.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.cpp
  clang-tools-extra/clangd/unittests/XRefsTests.cpp

Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp
===
--- clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -1118,17 +1118,18 @@
   // decls.
   R"cpp(
   namespace ns { class [[Foo]] {}; }
-  using ns::F^oo;
+  // FIXME: don't return the using decl if it touches the cursor position.
+  using ns::[[F^oo]];
 )cpp",
 
   R"cpp(
   namespace ns { int [[x]](char); int [[x]](double); }
-  using ns::^x;
+  using ns::[[^x]];
 )cpp",
 
   R"cpp(
   namespace ns { int [[x]](char); int x(double); }
-  using ns::x;
+  using ns::[[x]];
   int y = ^x('a');
 )cpp",
 
@@ -1156,7 +1157,7 @@
   };
   template 
   struct Derived : Base {
-using Base::w^aldo;
+using Base::[[w^aldo]];
   };
 )cpp",
   };
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -181,8 +181,7 @@
 int x = [[f]](42);
   )cpp";
   // f(char) is not referenced!
-  EXPECT_DECLS("DeclRefExpr", {"using foo::f", Rel::Alias},
-   {"int f(int)", Rel::Underlying});
+  EXPECT_DECLS("DeclRefExpr", {"using foo::f", Rel::Alias}, {"int f(int)"});
 
   Code = R"cpp(
 namespace foo {
@@ -192,9 +191,8 @@
 [[using foo::f]];
   )cpp";
   // All overloads are referenced.
-  EXPECT_DECLS("UsingDecl", {"using foo::f", Rel::Alias},
-   {"int f(int)", Rel::Underlying},
-   {"int f(char)", Rel::Underlying});
+  EXPECT_DECLS("UsingDecl", {"using foo::f", Rel::Alias}, {"int f(int)"},
+   {"int f(char)"});
 
   Code = R"cpp(
 struct X {
@@ -205,8 +203,7 @@
 };
 int x = Y().[[foo]]();
   )cpp";
-  EXPECT_DECLS("MemberExpr", {"using X::foo", Rel::Alias},
-   {"int foo()", Rel::Underlying});
+  EXPECT_DECLS("MemberExpr", {"using X::foo", Rel::Alias}, {"int foo()"});
 
   Code = R"cpp(
   template 
@@ -219,7 +216,7 @@
   };
 )cpp";
   EXPECT_DECLS("UnresolvedUsingValueDecl", {"using Base::waldo", Rel::Alias},
-   {"void waldo()", Rel::Underlying});
+   {"void waldo()"});
 }
 
 TEST_F(TargetDeclTest, ConstructorInitList) {
Index: clang-tools-extra/clangd/XRefs.cpp
===
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -343,18 +343,6 @@
   }
 }
 
-// Give the underlying decl if navigation is triggered on a non-renaming
-// alias.
-if (llvm::isa(D) || llvm::isa(D)) {
-  // FIXME: address more complicated cases. TargetDecl(... Underlying) gives
-  // all overload candidates, we only want the targeted one if the cursor is
-  // on an using-alias usage, workround it with getDeclAtPosition.
-  llvm::for_each(
-  getDeclAtPosition(AST, CurLoc, DeclRelation::Underlying, NodeKind),
-  [&](const NamedDecl *UD) { AddResultDecl(UD); });
-  continue;
-}
-
 // Special case: if the class name is selected, also map Objective-C
 // categories and category implementations back to their class interface.
 //
@@ -1159,17 +1147,6 @@
 DeclRelation::TemplatePattern | DeclRelation::Alias;
 std::vector Decls =
 getDeclAtPosition(AST, *CurLoc, Relations);
-std::vector NonrenamingAliasUnderlyingDecls;
-// If the results include a *non-renaming* alias, get its
-// underlying decls as well. (See similar logic in locateASTReferent()).
-for (const NamedDecl *D : Decls) {
-  if (llvm::isa(D) || llvm::isa(D)) {
-for (const NamedDecl *AD :
- getDeclAtPosition(AST, *CurLoc, DeclRelation::Underlying))
-  NonrenamingAliasUnderlyingDecls.push_back(AD);
-  }
-}
-llvm::copy(NonrenamingAliasUnderlyingDecls, std::back_inserter(Decls));
 
 // We traverse the AST to find references in the main file.
 auto MainFileRefs = findRefs(Decls, AST);
Index: clang-tools-extra/clangd/FindTarget.h
===
--- clang-tools-extra/clangd/FindTarget.h
+++ 

[PATCH] D88472: [clangd] Don't set the Underlying bit on targets of UsingDecls.

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/unittests/XRefsTests.cpp:1121
   namespace ns { class [[Foo]] {}; }
-  using ns::F^oo;
+  using ns::[[F^oo]];
 )cpp",

sammccall wrote:
> I'd like to make a plan to solve this regression (we can do it here or in a 
> followup patch, happy to hack on that).
> 
> What do you think about the following heuristic:
>  - if go-to-definition yields multiple results
>  - and a particular result touches the cursor*
>  - (optional) and that result is marked with Alias
>  - then drop it from the set
> It means we still keep some special-case code, but it's not complex and 
> fairly intuitive I think.
sounds good. I'd leave it as a follow-up. Added a FIXME.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88472

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


[PATCH] D88472: [clangd] Don't set the Underlying bit on targets of UsingDecls.

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296612.
hokein marked 2 inline comments as done.
hokein added a comment.

address comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88472

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/FindTarget.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.cpp
  clang-tools-extra/clangd/unittests/XRefsTests.cpp

Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp
===
--- clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -1118,17 +1118,18 @@
   // decls.
   R"cpp(
   namespace ns { class [[Foo]] {}; }
-  using ns::F^oo;
+  // FIXME: don't return the using decl if it touches the cursor position.
+  using ns::[[F^oo]];
 )cpp",
 
   R"cpp(
   namespace ns { int [[x]](char); int [[x]](double); }
-  using ns::^x;
+  using ns::[[^x]];
 )cpp",
 
   R"cpp(
   namespace ns { int [[x]](char); int x(double); }
-  using ns::x;
+  using ns::[[x]];
   int y = ^x('a');
 )cpp",
 
@@ -1156,7 +1157,7 @@
   };
   template 
   struct Derived : Base {
-using Base::w^aldo;
+using Base::[[w^aldo]];
   };
 )cpp",
   };
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -181,8 +181,7 @@
 int x = [[f]](42);
   )cpp";
   // f(char) is not referenced!
-  EXPECT_DECLS("DeclRefExpr", {"using foo::f", Rel::Alias},
-   {"int f(int)", Rel::Underlying});
+  EXPECT_DECLS("DeclRefExpr", {"using foo::f", Rel::Alias}, {"int f(int)"});
 
   Code = R"cpp(
 namespace foo {
@@ -192,9 +191,8 @@
 [[using foo::f]];
   )cpp";
   // All overloads are referenced.
-  EXPECT_DECLS("UsingDecl", {"using foo::f", Rel::Alias},
-   {"int f(int)", Rel::Underlying},
-   {"int f(char)", Rel::Underlying});
+  EXPECT_DECLS("UsingDecl", {"using foo::f", Rel::Alias}, {"int f(int)"},
+   {"int f(char)"});
 
   Code = R"cpp(
 struct X {
@@ -205,8 +203,7 @@
 };
 int x = Y().[[foo]]();
   )cpp";
-  EXPECT_DECLS("MemberExpr", {"using X::foo", Rel::Alias},
-   {"int foo()", Rel::Underlying});
+  EXPECT_DECLS("MemberExpr", {"using X::foo", Rel::Alias}, {"int foo()"});
 
   Code = R"cpp(
   template 
@@ -219,7 +216,7 @@
   };
 )cpp";
   EXPECT_DECLS("UnresolvedUsingValueDecl", {"using Base::waldo", Rel::Alias},
-   {"void waldo()", Rel::Underlying});
+   {"void waldo()"});
 }
 
 TEST_F(TargetDeclTest, ConstructorInitList) {
Index: clang-tools-extra/clangd/XRefs.cpp
===
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -343,18 +343,6 @@
   }
 }
 
-// Give the underlying decl if navigation is triggered on a non-renaming
-// alias.
-if (llvm::isa(D) || llvm::isa(D)) {
-  // FIXME: address more complicated cases. TargetDecl(... Underlying) gives
-  // all overload candidates, we only want the targeted one if the cursor is
-  // on an using-alias usage, workround it with getDeclAtPosition.
-  llvm::for_each(
-  getDeclAtPosition(AST, CurLoc, DeclRelation::Underlying, NodeKind),
-  [&](const NamedDecl *UD) { AddResultDecl(UD); });
-  continue;
-}
-
 // Special case: if the class name is selected, also map Objective-C
 // categories and category implementations back to their class interface.
 //
@@ -1159,17 +1147,6 @@
 DeclRelation::TemplatePattern | DeclRelation::Alias;
 std::vector Decls =
 getDeclAtPosition(AST, *CurLoc, Relations);
-std::vector NonrenamingAliasUnderlyingDecls;
-// If the results include a *non-renaming* alias, get its
-// underlying decls as well. (See similar logic in locateASTReferent()).
-for (const NamedDecl *D : Decls) {
-  if (llvm::isa(D) || llvm::isa(D)) {
-for (const NamedDecl *AD :
- getDeclAtPosition(AST, *CurLoc, DeclRelation::Underlying))
-  NonrenamingAliasUnderlyingDecls.push_back(AD);
-  }
-}
-llvm::copy(NonrenamingAliasUnderlyingDecls, std::back_inserter(Decls));
 
 // We traverse the AST to find references in the main file.
 auto MainFileRefs = findRefs(Decls, AST);
Index: clang-tools-extra/clangd/FindTarget.h
===
--- clang-tools-extra/clangd/FindTarget.h
+++ clang-tools-extra/clangd/FindTarget.h
@@ -102,13 +102,20 @@
   TemplatePattern,
 
   // Alias options apply when the declaration is an alias.
- 

[PATCH] D84387: [AST][RecoveryExpr] Part4: Suppress spurious "err_typecheck_expect_scalar_operand" diagnostic

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

> I'm not sure I love having the assertion for contains-errors every place that 
> handles dependent code in C.

My feeling is that the assertion would help for understanding the code 
(comparing with documenting it somewhere), and we don't have too many places.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84387

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


[PATCH] D84387: [AST][RecoveryExpr] Part4: Suppress spurious "err_typecheck_expect_scalar_operand" diagnostic

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296611.
hokein marked an inline comment as done.
hokein added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84387

Files:
  clang/lib/Sema/SemaCast.cpp
  clang/test/AST/ast-dump-recovery.c
  clang/test/Sema/error-dependence.c


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -6,6 +6,10 @@
   // verify "assigning to 'int' from incompatible type ''" is
   // not emitted.
   s = call(); // expected-error {{too few arguments to function call}}
+
+  // verify diagnostic "operand of type '' where arithmetic or
+  // pointer type is required" is not emitted.
+  (float)call(); // expected-error {{too few arguments to function call}}
 }
 
 void test2(int* ptr, float f) {
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -81,4 +81,9 @@
   // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int *' lvalue
   // CHECK-NEXT: `-DeclRefExpr {{.*}} 'float' lvalue
   (ptr > f ? ptr : f);
+
+  // CHECK: CStyleCastExpr {{.*}} 'float' contains-errors 
+  // CHECK-NEXT: `-RecoveryExpr {{.*}} ''
+  // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
+  (float)some_func();
 }
Index: clang/lib/Sema/SemaCast.cpp
===
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -2707,6 +2707,17 @@
 return;
   }
 
+  // If the type is dependent, we won't do any other semantic analysis now.
+  if (Self.getASTContext().isDependenceAllowed() &&
+  (DestType->isDependentType() || SrcExpr.get()->isTypeDependent() ||
+   SrcExpr.get()->isValueDependent())) {
+assert((DestType->containsErrors() || SrcExpr.get()->containsErrors() ||
+SrcExpr.get()->containsErrors()) &&
+   "should only occur in error-recovery path.");
+assert(Kind == CK_Dependent);
+return;
+  }
+
   // Overloads are allowed with C extensions, so we need to support them.
   if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
 DeclAccessPair DAP;


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -6,6 +6,10 @@
   // verify "assigning to 'int' from incompatible type ''" is
   // not emitted.
   s = call(); // expected-error {{too few arguments to function call}}
+
+  // verify diagnostic "operand of type '' where arithmetic or
+  // pointer type is required" is not emitted.
+  (float)call(); // expected-error {{too few arguments to function call}}
 }
 
 void test2(int* ptr, float f) {
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -81,4 +81,9 @@
   // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int *' lvalue
   // CHECK-NEXT: `-DeclRefExpr {{.*}} 'float' lvalue
   (ptr > f ? ptr : f);
+
+  // CHECK: CStyleCastExpr {{.*}} 'float' contains-errors 
+  // CHECK-NEXT: `-RecoveryExpr {{.*}} ''
+  // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
+  (float)some_func();
 }
Index: clang/lib/Sema/SemaCast.cpp
===
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -2707,6 +2707,17 @@
 return;
   }
 
+  // If the type is dependent, we won't do any other semantic analysis now.
+  if (Self.getASTContext().isDependenceAllowed() &&
+  (DestType->isDependentType() || SrcExpr.get()->isTypeDependent() ||
+   SrcExpr.get()->isValueDependent())) {
+assert((DestType->containsErrors() || SrcExpr.get()->containsErrors() ||
+SrcExpr.get()->containsErrors()) &&
+   "should only occur in error-recovery path.");
+assert(Kind == CK_Dependent);
+return;
+  }
+
   // Overloads are allowed with C extensions, so we need to support them.
   if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
 DeclAccessPair DAP;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D84322: [AST][RecoveryExpr] Part3: Support dependent conditional operators in C for error recovery.

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG334ec6f807fa: [AST][RecoveryExpr] Support dependent 
conditional operators in C for error… (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84322

Files:
  clang/lib/Sema/SemaExpr.cpp
  clang/test/AST/ast-dump-recovery.c
  clang/test/Sema/error-dependence.c


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -1,9 +1,15 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -frecovery-ast -fno-recovery-ast-type 
%s
 
-int call(int); // expected-note {{'call' declared here}}
+int call(int); // expected-note2 {{'call' declared here}}
 
 void test1(int s) {
   // verify "assigning to 'int' from incompatible type ''" is
   // not emitted.
   s = call(); // expected-error {{too few arguments to function call}}
 }
+
+void test2(int* ptr, float f) {
+  // verify diagnostic "used type '' where arithmetic or 
pointer
+  // type is required" is not emitted.
+  (call() ? ptr : f); // expected-error {{too few arguments to function call}}
+}
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -71,4 +71,14 @@
   // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'some_func'
   // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
   some_func(), 1;
+
+  // conditional operator (comparison is invalid)
+  float f;
+  // CHECK: ConditionalOperator {{.*}} '' contains-errors
+  // CHECK-NEXT: |-RecoveryExpr {{.*}} ''
+  // CHECK-NEXT: | |-DeclRefExpr {{.*}} 'int *' lvalue
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'float' lvalue
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int *' lvalue
+  // CHECK-NEXT: `-DeclRefExpr {{.*}} 'float' lvalue
+  (ptr > f ? ptr : f);
 }
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -8067,6 +8067,16 @@
   VK = VK_RValue;
   OK = OK_Ordinary;
 
+  if (Context.isDependenceAllowed() &&
+  (Cond.get()->isTypeDependent() || LHS.get()->isTypeDependent() ||
+   RHS.get()->isTypeDependent())) {
+assert(!getLangOpts().CPlusPlus);
+assert(Cond.get()->containsErrors() || LHS.get()->containsErrors() ||
+   RHS.get()->containsErrors() &&
+   "should only occur in error-recovery path.");
+return Context.DependentTy;
+  }
+
   // The OpenCL operator with a vector condition is sufficiently
   // different to merit its own checker.
   if ((getLangOpts().OpenCL && Cond.get()->getType()->isVectorType()) ||


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -1,9 +1,15 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -frecovery-ast -fno-recovery-ast-type %s
 
-int call(int); // expected-note {{'call' declared here}}
+int call(int); // expected-note2 {{'call' declared here}}
 
 void test1(int s) {
   // verify "assigning to 'int' from incompatible type ''" is
   // not emitted.
   s = call(); // expected-error {{too few arguments to function call}}
 }
+
+void test2(int* ptr, float f) {
+  // verify diagnostic "used type '' where arithmetic or pointer
+  // type is required" is not emitted.
+  (call() ? ptr : f); // expected-error {{too few arguments to function call}}
+}
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -71,4 +71,14 @@
   // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'some_func'
   // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
   some_func(), 1;
+
+  // conditional operator (comparison is invalid)
+  float f;
+  // CHECK: ConditionalOperator {{.*}} '' contains-errors
+  // CHECK-NEXT: |-RecoveryExpr {{.*}} ''
+  // CHECK-NEXT: | |-DeclRefExpr {{.*}} 'int *' lvalue
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'float' lvalue
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int *' lvalue
+  // CHECK-NEXT: `-DeclRefExpr {{.*}} 'float' lvalue
+  (ptr > f ? ptr : f);
 }
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -8067,6 +8067,16 @@
   VK = VK_RValue;
   OK = OK_Ordinary;
 
+  if (Context.isDependenceAllowed() &&
+  (Cond.get()->isTypeDependent() || LHS.get()->isTypeDependent() ||
+   RHS.get()->isTypeDependent())) {
+assert(!getLangOpts().CPlusPlus);
+assert(Cond.get()->containsErrors() || LHS.get()->containsErrors() ||
+   

[PATCH] D84322: [AST][RecoveryExpr] Part3: Support dependent conditional operators in C for error recovery.

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296609.
hokein marked 2 inline comments as done.
hokein added a comment.

address comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84322

Files:
  clang/lib/Sema/SemaExpr.cpp
  clang/test/AST/ast-dump-recovery.c
  clang/test/Sema/error-dependence.c


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -1,9 +1,15 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -frecovery-ast -fno-recovery-ast-type 
%s
 
-int call(int); // expected-note {{'call' declared here}}
+int call(int); // expected-note2 {{'call' declared here}}
 
 void test1(int s) {
   // verify "assigning to 'int' from incompatible type ''" is
   // not emitted.
   s = call(); // expected-error {{too few arguments to function call}}
 }
+
+void test2(int* ptr, float f) {
+  // verify diagnostic "used type '' where arithmetic or 
pointer
+  // type is required" is not emitted.
+  (call() ? ptr : f); // expected-error {{too few arguments to function call}}
+}
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -71,4 +71,14 @@
   // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'some_func'
   // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
   some_func(), 1;
+
+  // conditional operator (comparison is invalid)
+  float f;
+  // CHECK: ConditionalOperator {{.*}} '' contains-errors
+  // CHECK-NEXT: |-RecoveryExpr {{.*}} ''
+  // CHECK-NEXT: | |-DeclRefExpr {{.*}} 'int *' lvalue
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'float' lvalue
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int *' lvalue
+  // CHECK-NEXT: `-DeclRefExpr {{.*}} 'float' lvalue
+  (ptr > f ? ptr : f);
 }
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -8067,6 +8067,16 @@
   VK = VK_RValue;
   OK = OK_Ordinary;
 
+  if (Context.isDependenceAllowed() &&
+  (Cond.get()->isTypeDependent() || LHS.get()->isTypeDependent() ||
+   RHS.get()->isTypeDependent())) {
+assert(!getLangOpts().CPlusPlus);
+assert(Cond.get()->containsErrors() || LHS.get()->containsErrors() ||
+   RHS.get()->containsErrors() &&
+   "should only occur in error-recovery path.");
+return Context.DependentTy;
+  }
+
   // The OpenCL operator with a vector condition is sufficiently
   // different to merit its own checker.
   if ((getLangOpts().OpenCL && Cond.get()->getType()->isVectorType()) ||


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -1,9 +1,15 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -frecovery-ast -fno-recovery-ast-type %s
 
-int call(int); // expected-note {{'call' declared here}}
+int call(int); // expected-note2 {{'call' declared here}}
 
 void test1(int s) {
   // verify "assigning to 'int' from incompatible type ''" is
   // not emitted.
   s = call(); // expected-error {{too few arguments to function call}}
 }
+
+void test2(int* ptr, float f) {
+  // verify diagnostic "used type '' where arithmetic or pointer
+  // type is required" is not emitted.
+  (call() ? ptr : f); // expected-error {{too few arguments to function call}}
+}
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -71,4 +71,14 @@
   // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'some_func'
   // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
   some_func(), 1;
+
+  // conditional operator (comparison is invalid)
+  float f;
+  // CHECK: ConditionalOperator {{.*}} '' contains-errors
+  // CHECK-NEXT: |-RecoveryExpr {{.*}} ''
+  // CHECK-NEXT: | |-DeclRefExpr {{.*}} 'int *' lvalue
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'float' lvalue
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int *' lvalue
+  // CHECK-NEXT: `-DeclRefExpr {{.*}} 'float' lvalue
+  (ptr > f ? ptr : f);
 }
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -8067,6 +8067,16 @@
   VK = VK_RValue;
   OK = OK_Ordinary;
 
+  if (Context.isDependenceAllowed() &&
+  (Cond.get()->isTypeDependent() || LHS.get()->isTypeDependent() ||
+   RHS.get()->isTypeDependent())) {
+assert(!getLangOpts().CPlusPlus);
+assert(Cond.get()->containsErrors() || LHS.get()->containsErrors() ||
+   RHS.get()->containsErrors() &&
+   "should only occur in error-recovery path.");
+return Context.DependentTy;
+  }
+
   // The OpenCL operator 

[PATCH] D84322: [AST][RecoveryExpr] Part3: Support dependent conditional operators in C for error recovery.

2020-10-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang/test/Sema/error-dependence.c:18
+  // type is required" is not emitted.
+  ptr > f ? ptr : f; // expected-error {{invalid operands to binary 
expression}}
+}

sammccall wrote:
> hokein wrote:
> > sammccall wrote:
> > > nit: parens would help me understand here :-)
> > > 
> > > I don't find this example compelling because we should know that "ptr > 
> > > f" is a boolean.
> > > 
> > > Can we just have `undefined ? ptr : f`, expecting the only diag to be the 
> > > undeclared ident?
> > > I don't find this example compelling because we should know that "ptr > 
> > > f" is a boolean.
> > 
> > this is a reasonable impression, but in this case, there is no 
> > binary-operator `>` -- operands `ptr`, `f` have different types, and 
> > invalid for binary operator, instead we build a recovery-expr.
> > 
> > so the AST looks like (added in the dump-recovery.c test as well)
> > 
> > ```
> >   ConditionalOperator> '' contains-errors
> > | |-RecoveryExpr  '' contains-errors lvalue
> > | | |-DeclRefExpr  'int *' lvalue Var 0x8fdb620 'ptr' 'int *'
> > | | `-DeclRefExpr  'float' lvalue Var 0x8ffd388 'f' 'float'
> > | |-DeclRefExpr  'int *' lvalue Var 0x8fdb620 'ptr' 'int *'
> > | `-DeclRefExpr  'float' lvalue Var 0x8ffd388 'f' 'float'
> > ``` 
> > 
> > > Can we just have undefined ? ptr : f, expecting the only diag to be the 
> > > undeclared ident?
> > 
> > no unfortunately. the whole statement is being dropped (we don't preserve 
> > this in C/C++). 
> `undefined() ? ptr : f` then?
oh, yeah. undefined() is not working (undefined function is implicitly treated 
as `int ()` in C), but `call()` would work.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84322

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


[PATCH] D88875: [clangd] Add basic keyword-name-validation in rename.

2020-10-06 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG8a3cbb1535a9: [clangd] Add basic keyword-name-validation in 
rename. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88875

Files:
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/unittests/RenameTests.cpp


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -516,6 +516,7 @@
 const char* ErrorMessage; // null if no error
 bool IsHeaderFile;
 const SymbolIndex *Index;
+llvm::StringRef NewName = "DummyName";
   };
   TestTU OtherFile = TestTU::withCode("Outside s; auto ss = ");
   const char *CommonHeader = R"cpp(
@@ -542,6 +543,11 @@
   )cpp",
nullptr, HeaderFile, Index},
 
+  {R"cpp(
+void ^f();
+  )cpp",
+   "keyword", HeaderFile, Index, "return"},
+
   {R"cpp(// disallow -- symbol is indexable and has other refs in index.
 void f() {
   Out^side s;
@@ -639,7 +645,7 @@
   TU.ExtraArgs.push_back("-xobjective-c++-header");
 }
 auto AST = TU.build();
-llvm::StringRef NewName = "dummyNewName";
+llvm::StringRef NewName = Case.NewName;
 auto Results =
 rename({T.point(), NewName, AST, testPath(TU.Filename), Case.Index});
 bool WantRename = true;
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -120,6 +120,9 @@
   UsedOutsideFile, // for within-file rename only.
   UnsupportedSymbol,
   AmbiguousSymbol,
+
+  // name validation.
+  RenameToKeywords,
 };
 
 llvm::Optional renameable(const NamedDecl ,
@@ -208,6 +211,8 @@
   return "symbol is not a supported kind (e.g. namespace, macro)";
 case ReasonToReject::AmbiguousSymbol:
   return "there are multiple symbols at the given location";
+case ReasonToReject::RenameToKeywords:
+  return "the chosen name is a keyword";
 }
 llvm_unreachable("unhandled reason kind");
   };
@@ -471,6 +476,8 @@
 return makeError(ReasonToReject::NoSymbolFound);
   if (DeclsUnderCursor.size() > 1)
 return makeError(ReasonToReject::AmbiguousSymbol);
+  if (isKeyword(RInputs.NewName, AST.getLangOpts()))
+return makeError(ReasonToReject::RenameToKeywords);
 
   const auto  =
   llvm::cast(*(*DeclsUnderCursor.begin())->getCanonicalDecl());
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -273,9 +273,6 @@
 StringRef TriggerText, Callback> CB);
 
   /// Test the validity of a rename operation.
-  ///
-  /// The returned result describes edits in the main-file only (all
-  /// occurrences of the renamed symbol are simply deleted.
   void prepareRename(PathRef File, Position Pos,
  const RenameOptions ,
  Callback CB);
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -412,9 +412,9 @@
 //  - for cross-file rename, we deliberately pass a nullptr index to save
 //the cost, thus the result may be incomplete as it only contains
 //main-file occurrences;
-auto Results = clangd::rename({Pos, /*NewName*/ "", InpAST->AST, File,
-   RenameOpts.AllowCrossFile ? nullptr : Index,
-   RenameOpts});
+auto Results = clangd::rename(
+{Pos, /*NewName=*/"__clangd_rename_dummy", InpAST->AST, File,
+ RenameOpts.AllowCrossFile ? nullptr : Index, RenameOpts});
 if (!Results) {
   // LSP says to return null on failure, but that will result in a generic
   // failure message. If we send an LSP error response, clients can surface


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -516,6 +516,7 @@
 const char* ErrorMessage; // null if no error
 bool IsHeaderFile;
 const SymbolIndex *Index;
+llvm::StringRef NewName = "DummyName";
   };
   TestTU OtherFile = TestTU::withCode("Outside s; auto ss = ");
   const char *CommonHeader = R"cpp(
@@ -542,6 +543,11 @@
   )cpp",
 

[PATCH] D88875: [clangd] Add basic keyword-name-validation in rename.

2020-10-06 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/ClangdServer.cpp:416
+auto Results = clangd::rename(
+{Pos, /*NewName=*/"__clangd_rename_dummy", InpAST->AST, File,
+ RenameOpts.AllowCrossFile ? nullptr : Index, RenameOpts});

sammccall wrote:
> oh, reserved name is clever :-)
> 
> Though it occurs to me - we could actually warn on rename to a reserved name!
> (We can still do this and just ignore __clangd_*)
giving a warning is nice, it seems too strict to forbidden users (library 
developers)) renaming a symbol to `__a` . The code is still compilable after 
all.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88875

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


[PATCH] D88875: [clangd] Add basic keyword-name-validation in rename.

2020-10-06 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/refactor/Rename.cpp:124
+
+  // name validation.
+  RenameToKeywords,

sammccall wrote:
> nit: not sure we need a separate section for these, I can imagine at most 
> keyword/conflict/shadow
yeah, I would leave it as-is for now. we could factor this out when there are 
more.



Comment at: clang-tools-extra/clangd/refactor/Rename.cpp:479
 return makeError(ReasonToReject::AmbiguousSymbol);
+  // Empty name is legal -- this allows rename API to return all occurrences
+  // even the name is unknown.

sammccall wrote:
> Now that prepareRename only exposes ranges rather than edits, do we still 
> need this empty special case, or can we go back to using 
> "clangd_rename_dummy" or so?
> 
> (Sorry for the back and forth here)
oh, you're right. And the documentation of the prepareRename is stale. Updated.

A slight concern of using a dummy name is that it may cause a name validation, 
but it should rarely happen if we choose some name like `clangd_rename_dummy`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88875

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


[PATCH] D88875: [clangd] Add basic keyword-name-validation in rename.

2020-10-06 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296438.
hokein marked an inline comment as done.
hokein added a comment.

address comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88875

Files:
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/unittests/RenameTests.cpp


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -516,6 +516,7 @@
 const char* ErrorMessage; // null if no error
 bool IsHeaderFile;
 const SymbolIndex *Index;
+llvm::StringRef NewName = "DummyName";
   };
   TestTU OtherFile = TestTU::withCode("Outside s; auto ss = ");
   const char *CommonHeader = R"cpp(
@@ -542,6 +543,11 @@
   )cpp",
nullptr, HeaderFile, Index},
 
+  {R"cpp(
+void ^f();
+  )cpp",
+   "keyword", HeaderFile, Index, "return"},
+
   {R"cpp(// disallow -- symbol is indexable and has other refs in index.
 void f() {
   Out^side s;
@@ -639,7 +645,7 @@
   TU.ExtraArgs.push_back("-xobjective-c++-header");
 }
 auto AST = TU.build();
-llvm::StringRef NewName = "dummyNewName";
+llvm::StringRef NewName = Case.NewName;
 auto Results =
 rename({T.point(), NewName, AST, testPath(TU.Filename), Case.Index});
 bool WantRename = true;
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -120,6 +120,9 @@
   UsedOutsideFile, // for within-file rename only.
   UnsupportedSymbol,
   AmbiguousSymbol,
+
+  // name validation.
+  RenameToKeywords,
 };
 
 llvm::Optional renameable(const NamedDecl ,
@@ -208,6 +211,8 @@
   return "symbol is not a supported kind (e.g. namespace, macro)";
 case ReasonToReject::AmbiguousSymbol:
   return "there are multiple symbols at the given location";
+case ReasonToReject::RenameToKeywords:
+  return "the chosen name is a keyword";
 }
 llvm_unreachable("unhandled reason kind");
   };
@@ -471,6 +476,8 @@
 return makeError(ReasonToReject::NoSymbolFound);
   if (DeclsUnderCursor.size() > 1)
 return makeError(ReasonToReject::AmbiguousSymbol);
+  if (isKeyword(RInputs.NewName, AST.getLangOpts()))
+return makeError(ReasonToReject::RenameToKeywords);
 
   const auto  =
   llvm::cast(*(*DeclsUnderCursor.begin())->getCanonicalDecl());
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -273,9 +273,6 @@
 StringRef TriggerText, Callback> CB);
 
   /// Test the validity of a rename operation.
-  ///
-  /// The returned result describes edits in the main-file only (all
-  /// occurrences of the renamed symbol are simply deleted.
   void prepareRename(PathRef File, Position Pos,
  const RenameOptions ,
  Callback CB);
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -412,9 +412,9 @@
 //  - for cross-file rename, we deliberately pass a nullptr index to save
 //the cost, thus the result may be incomplete as it only contains
 //main-file occurrences;
-auto Results = clangd::rename({Pos, /*NewName*/ "", InpAST->AST, File,
-   RenameOpts.AllowCrossFile ? nullptr : Index,
-   RenameOpts});
+auto Results = clangd::rename(
+{Pos, /*NewName=*/"__clangd_rename_dummy", InpAST->AST, File,
+ RenameOpts.AllowCrossFile ? nullptr : Index, RenameOpts});
 if (!Results) {
   // LSP says to return null on failure, but that will result in a generic
   // failure message. If we send an LSP error response, clients can surface


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -516,6 +516,7 @@
 const char* ErrorMessage; // null if no error
 bool IsHeaderFile;
 const SymbolIndex *Index;
+llvm::StringRef NewName = "DummyName";
   };
   TestTU OtherFile = TestTU::withCode("Outside s; auto ss = ");
   const char *CommonHeader = R"cpp(
@@ -542,6 +543,11 @@
   )cpp",
nullptr, HeaderFile, Index},
 
+  {R"cpp(
+void ^f();
+  )cpp",
+   "keyword", 

[PATCH] D88881: [clangd] Add a NewName optional parameter to clangdServer::prepareRename.

2020-10-06 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: sammccall.
Herald added subscribers: usaxena95, kadircet, arphaman.
Herald added a project: clang.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

so that our embedders can implement customized behavior on top of it.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D1

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/unittests/RenameTests.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.h

Index: clang-tools-extra/clangd/unittests/SyncAPI.h
===
--- clang-tools-extra/clangd/unittests/SyncAPI.h
+++ clang-tools-extra/clangd/unittests/SyncAPI.h
@@ -46,6 +46,7 @@
 
 llvm::Expected
 runPrepareRename(ClangdServer , PathRef File, Position Pos,
+ llvm::StringRef NewName,
  const clangd::RenameOptions );
 
 llvm::Expected
Index: clang-tools-extra/clangd/unittests/SyncAPI.cpp
===
--- clang-tools-extra/clangd/unittests/SyncAPI.cpp
+++ clang-tools-extra/clangd/unittests/SyncAPI.cpp
@@ -107,9 +107,10 @@
 
 llvm::Expected runPrepareRename(ClangdServer ,
   PathRef File, Position Pos,
+  llvm::StringRef NewName,
   const RenameOptions ) {
   llvm::Optional> Result;
-  Server.prepareRename(File, Pos, RenameOpts, capture(Result));
+  Server.prepareRename(File, Pos, NewName, RenameOpts, capture(Result));
   return std::move(*Result);
 }
 
Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -730,8 +730,8 @@
   runAddDocument(Server, FooHPath, FooH.code());
   runAddDocument(Server, FooCCPath, FooCC.code());
 
-  auto Results =
-  runPrepareRename(Server, FooCCPath, FooCC.point(), {/*CrossFile=*/true});
+  auto Results = runPrepareRename(Server, FooCCPath, FooCC.point(),
+  /*NewName=*/"", {/*CrossFile=*/true});
   // verify that for multi-file rename, we only return main-file occurrences.
   ASSERT_TRUE(bool(Results)) << Results.takeError();
   // We don't know the result is complete in prepareRename (passing a nullptr
@@ -740,9 +740,16 @@
   EXPECT_THAT(FooCC.ranges(),
   testing::UnorderedElementsAreArray(Results->LocalChanges));
 
+  // verify name validation.
+  Results = runPrepareRename(Server, FooCCPath, FooCC.point(),
+ /*NewName=*/"int", {/*CrossFile=*/true});
+  EXPECT_FALSE(Results);
+  EXPECT_THAT(llvm::toString(Results.takeError()),
+  testing::HasSubstr("renamed to a reserved keyword"));
+
   // single-file rename on global symbols, we should report an error.
-  Results =
-  runPrepareRename(Server, FooCCPath, FooCC.point(), {/*CrossFile=*/false});
+  Results = runPrepareRename(Server, FooCCPath, FooCC.point(), /*NewName=*/"",
+ {/*CrossFile=*/false});
   EXPECT_FALSE(Results);
   EXPECT_THAT(llvm::toString(Results.takeError()),
   testing::HasSubstr("is used outside"));
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -274,9 +274,11 @@
 
   /// Test the validity of a rename operation.
   ///
+  /// If NewName is not empty, it peforms a name validation.
+  ///
   /// The returned result describes edits in the main-file only (all
   /// occurrences of the renamed symbol are simply deleted.
-  void prepareRename(PathRef File, Position Pos,
+  void prepareRename(PathRef File, Position Pos, llvm::StringRef NewName,
  const RenameOptions ,
  Callback CB);
 
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -399,9 +399,11 @@
 }
 
 void ClangdServer::prepareRename(PathRef File, Position Pos,
+ llvm::StringRef NewName,
  const RenameOptions ,
  Callback CB) {
-  auto Action = [Pos, File = File.str(), CB = std::move(CB), RenameOpts,
+  auto Action = [Pos, File = File.str(), CB = std::move(CB),
+ NewName = NewName.str(), RenameOpts,
  this](llvm::Expected InpAST) mutable {
 if (!InpAST)
   return CB(InpAST.takeError());
@@ -412,7 +414,7 @@
 //  - for 

[PATCH] D88828: [clangd] Verify the diagnostic code in include-fixer diagnostic tests, NFC.

2020-10-06 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG48a82c42457b: [clangd] Verify the diagnostic code in 
include-fixer diagnostic tests, NFC. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88828

Files:
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -720,13 +720,16 @@
   UnorderedElementsAre(
   AllOf(Diag(Test.range("nested"),
  "incomplete type 'ns::X' named in nested name specifier"),
+DiagName("incomplete_nested_name_spec"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
 "Add include \"x.h\" for symbol ns::X"))),
   AllOf(Diag(Test.range("base"), "base class has incomplete type"),
+DiagName("incomplete_base_class"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
 "Add include \"x.h\" for symbol ns::X"))),
   AllOf(Diag(Test.range("access"),
  "member access into incomplete type 'ns::X'"),
+DiagName("incomplete_member_access"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
 "Add include \"x.h\" for symbol ns::X");
 }
@@ -789,19 +792,23 @@
   TU.build().getDiagnostics(),
   UnorderedElementsAre(
   AllOf(Diag(Test.range("unqualified1"), "unknown type name 'X'"),
+DiagName("unknown_typename"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
 "Add include \"x.h\" for symbol ns::X"))),
   Diag(Test.range("unqualified2"), "use of undeclared identifier 'X'"),
   AllOf(Diag(Test.range("qualified1"),
  "no type named 'X' in namespace 'ns'"),
+DiagName("typename_nested_not_found"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
 "Add include \"x.h\" for symbol ns::X"))),
   AllOf(Diag(Test.range("qualified2"),
  "no member named 'X' in namespace 'ns'"),
+DiagName("no_member"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
 "Add include \"x.h\" for symbol ns::X"))),
   AllOf(Diag(Test.range("global"),
  "no type named 'Global' in the global namespace"),
+DiagName("typename_nested_not_found"),
 WithFix(Fix(Test.range("insert"), "#include \"global.h\"\n",
 "Add include \"global.h\" for symbol Global");
 }
@@ -825,6 +832,7 @@
   EXPECT_THAT(TU.build().getDiagnostics(),
   UnorderedElementsAre(AllOf(
   Diag(Test.range("unqualified"), "unknown type name 'X'"),
+  DiagName("unknown_typename"),
   WithFix(Fix(Test.range("insert"), "#include \"a.h\"\n",
   "Add include \"a.h\" for symbol na::X"),
   Fix(Test.range("insert"), "#include \"b.h\"\n",
@@ -905,6 +913,7 @@
   TU.build().getDiagnostics(),
   UnorderedElementsAre(AllOf(
   Diag(Test.range(), "no member named 'scope' in namespace 'ns'"),
+  DiagName("no_member"),
   WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
   "Add include \"x.h\" for symbol ns::scope::X_Y");
 }
@@ -934,22 +943,26 @@
   AllOf(
   Diag(Test.range("q1"), "use of undeclared identifier 'clangd'; "
  "did you mean 'clang'?"),
+  DiagName("undeclared_var_use_suggest"),
   WithFix(_, // change clangd to clang
   Fix(Test.range("insert"), "#include \"x.h\"\n",
   "Add include \"x.h\" for symbol clang::clangd::X"))),
   AllOf(
   Diag(Test.range("x"), "no type named 'X' in namespace 'clang'"),
+  DiagName("typename_nested_not_found"),
   WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
   "Add include \"x.h\" for symbol clang::clangd::X"))),
   AllOf(
   Diag(Test.range("q2"), "use of undeclared identifier 'clangd'; "
  "did you mean 'clang'?"),
+  DiagName("undeclared_var_use_suggest"),
   WithFix(
-  _, // change clangd to clangd
+  _, // change clangd to clang
   Fix(Test.range("insert"), "#include \"y.h\"\n",
   "Add 

[PATCH] D88828: [clangd] Verify the diagnostic code in include-fixer diagnostic tests, NFC.

2020-10-06 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In D88828#2311679 , @kadircet wrote:

> LGTM, but can you add some description about why you've decided to do it now 
> :D

yeah, this comes up when I read the code, I think it is easier to spot which 
diagnostics in the include-fixer list are tested, (e.g. `err_incomplete_type` 
is not tested yet).

And my next step to see whether there are other missing diagnostics that could 
be fixed by inserting a header.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88828

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


[PATCH] D88875: [clangd] Add basic keyword-name-validation in rename.

2020-10-06 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: sammccall.
Herald added subscribers: usaxena95, kadircet, arphaman.
Herald added a project: clang.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D88875

Files:
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/unittests/RenameTests.cpp


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -516,6 +516,7 @@
 const char* ErrorMessage; // null if no error
 bool IsHeaderFile;
 const SymbolIndex *Index;
+llvm::StringRef NewName = "DummyName";
   };
   TestTU OtherFile = TestTU::withCode("Outside s; auto ss = ");
   const char *CommonHeader = R"cpp(
@@ -542,6 +543,11 @@
   )cpp",
nullptr, HeaderFile, Index},
 
+  {R"cpp(
+void ^f();
+  )cpp",
+   "keyword", HeaderFile, Index, "return"},
+
   {R"cpp(// disallow -- symbol is indexable and has other refs in index.
 void f() {
   Out^side s;
@@ -639,7 +645,7 @@
   TU.ExtraArgs.push_back("-xobjective-c++-header");
 }
 auto AST = TU.build();
-llvm::StringRef NewName = "dummyNewName";
+llvm::StringRef NewName = Case.NewName;
 auto Results =
 rename({T.point(), NewName, AST, testPath(TU.Filename), Case.Index});
 bool WantRename = true;
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -120,6 +120,9 @@
   UsedOutsideFile, // for within-file rename only.
   UnsupportedSymbol,
   AmbiguousSymbol,
+
+  // name validation.
+  RenameToKeywords,
 };
 
 llvm::Optional renameable(const NamedDecl ,
@@ -208,6 +211,8 @@
   return "symbol is not a supported kind (e.g. namespace, macro)";
 case ReasonToReject::AmbiguousSymbol:
   return "there are multiple symbols at the given location";
+case ReasonToReject::RenameToKeywords:
+  return "symbol is renamed to a reserved keyword";
 }
 llvm_unreachable("unhandled reason kind");
   };
@@ -471,6 +476,10 @@
 return makeError(ReasonToReject::NoSymbolFound);
   if (DeclsUnderCursor.size() > 1)
 return makeError(ReasonToReject::AmbiguousSymbol);
+  // Empty name is legal -- this allows rename API to return all occurrences
+  // even the name is unknown.
+  if (!RInputs.NewName.empty() && isKeyword(RInputs.NewName, 
AST.getLangOpts()))
+return makeError(ReasonToReject::RenameToKeywords);
 
   const auto  =
   llvm::cast(*(*DeclsUnderCursor.begin())->getCanonicalDecl());


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -516,6 +516,7 @@
 const char* ErrorMessage; // null if no error
 bool IsHeaderFile;
 const SymbolIndex *Index;
+llvm::StringRef NewName = "DummyName";
   };
   TestTU OtherFile = TestTU::withCode("Outside s; auto ss = ");
   const char *CommonHeader = R"cpp(
@@ -542,6 +543,11 @@
   )cpp",
nullptr, HeaderFile, Index},
 
+  {R"cpp(
+void ^f();
+  )cpp",
+   "keyword", HeaderFile, Index, "return"},
+
   {R"cpp(// disallow -- symbol is indexable and has other refs in index.
 void f() {
   Out^side s;
@@ -639,7 +645,7 @@
   TU.ExtraArgs.push_back("-xobjective-c++-header");
 }
 auto AST = TU.build();
-llvm::StringRef NewName = "dummyNewName";
+llvm::StringRef NewName = Case.NewName;
 auto Results =
 rename({T.point(), NewName, AST, testPath(TU.Filename), Case.Index});
 bool WantRename = true;
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -120,6 +120,9 @@
   UsedOutsideFile, // for within-file rename only.
   UnsupportedSymbol,
   AmbiguousSymbol,
+
+  // name validation.
+  RenameToKeywords,
 };
 
 llvm::Optional renameable(const NamedDecl ,
@@ -208,6 +211,8 @@
   return "symbol is not a supported kind (e.g. namespace, macro)";
 case ReasonToReject::AmbiguousSymbol:
   return "there are multiple symbols at the given location";
+case ReasonToReject::RenameToKeywords:
+  return "symbol is renamed to a reserved keyword";
 }
 llvm_unreachable("unhandled reason kind");
   };
@@ -471,6 +476,10 @@
 return makeError(ReasonToReject::NoSymbolFound);
   if (DeclsUnderCursor.size() > 1)
 return makeError(ReasonToReject::AmbiguousSymbol);
+  // Empty name is legal -- 

[PATCH] D84322: [AST][RecoveryExpr] Part3: Suppress spurious "typecheck_cond_expect_scalar" diagnostic

2020-10-06 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang/test/Sema/error-dependence.c:18
+  // type is required" is not emitted.
+  ptr > f ? ptr : f; // expected-error {{invalid operands to binary 
expression}}
+}

sammccall wrote:
> nit: parens would help me understand here :-)
> 
> I don't find this example compelling because we should know that "ptr > f" is 
> a boolean.
> 
> Can we just have `undefined ? ptr : f`, expecting the only diag to be the 
> undeclared ident?
> I don't find this example compelling because we should know that "ptr > f" is 
> a boolean.

this is a reasonable impression, but in this case, there is no binary-operator 
`>` -- operands `ptr`, `f` have different types, and invalid for binary 
operator, instead we build a recovery-expr.

so the AST looks like (added in the dump-recovery.c test as well)

```
  ConditionalOperator> '' contains-errors
| |-RecoveryExpr  '' contains-errors lvalue
| | |-DeclRefExpr  'int *' lvalue Var 0x8fdb620 'ptr' 'int *'
| | `-DeclRefExpr  'float' lvalue Var 0x8ffd388 'f' 'float'
| |-DeclRefExpr  'int *' lvalue Var 0x8fdb620 'ptr' 'int *'
| `-DeclRefExpr  'float' lvalue Var 0x8ffd388 'f' 'float'
``` 

> Can we just have undefined ? ptr : f, expecting the only diag to be the 
> undeclared ident?

no unfortunately. the whole statement is being dropped (we don't preserve this 
in C/C++). 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84322

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


[PATCH] D84322: [AST][RecoveryExpr] Part3: Suppress spurious "typecheck_cond_expect_scalar" diagnostic

2020-10-06 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296374.
hokein added a comment.

rebase and add ast-dump test.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84322

Files:
  clang/lib/Sema/SemaExpr.cpp
  clang/test/AST/ast-dump-recovery.c
  clang/test/Sema/error-dependence.c


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -7,3 +7,9 @@
   // not emitted.
   s = call(); // expected-error {{too few arguments to function call}}
 }
+
+void test2(int* ptr, float f) {
+  // verify diagnostic "used type '' where arithmetic or 
pointer
+  // type is required" is not emitted.
+  ptr > f ? ptr : f; // expected-error {{invalid operands to binary 
expression}}
+}
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -71,4 +71,14 @@
   // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'some_func'
   // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
   some_func(), 1;
+
+  // conditional operator
+  float f;
+  // CHECK: ConditionalOperator {{.*}} '' contains-errors
+  // CHECK-NEXT: |-RecoveryExpr {{.*}} ''
+  // CHECK-NEXT: | |-DeclRefExpr {{.*}} 'int *' lvalue
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'float' lvalue
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int *' lvalue
+  // CHECK-NEXT: `-DeclRefExpr {{.*}} 'float' lvalue
+  ptr > f ? ptr : f;
 }
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -8067,6 +8067,16 @@
   VK = VK_RValue;
   OK = OK_Ordinary;
 
+  if (Context.isDependenceAllowed() &&
+  (Cond.get()->isTypeDependent() || LHS.get()->isTypeDependent() ||
+   RHS.get()->isTypeDependent())) {
+assert(!getLangOpts().CPlusPlus);
+assert(Cond.get()->containsErrors() || LHS.get()->containsErrors() ||
+   RHS.get()->containsErrors() &&
+   "should only occur in error-recovery path.");
+return Context.DependentTy;
+  }
+
   // The OpenCL operator with a vector condition is sufficiently
   // different to merit its own checker.
   if ((getLangOpts().OpenCL && Cond.get()->getType()->isVectorType()) ||


Index: clang/test/Sema/error-dependence.c
===
--- clang/test/Sema/error-dependence.c
+++ clang/test/Sema/error-dependence.c
@@ -7,3 +7,9 @@
   // not emitted.
   s = call(); // expected-error {{too few arguments to function call}}
 }
+
+void test2(int* ptr, float f) {
+  // verify diagnostic "used type '' where arithmetic or pointer
+  // type is required" is not emitted.
+  ptr > f ? ptr : f; // expected-error {{invalid operands to binary expression}}
+}
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -71,4 +71,14 @@
   // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'some_func'
   // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
   some_func(), 1;
+
+  // conditional operator
+  float f;
+  // CHECK: ConditionalOperator {{.*}} '' contains-errors
+  // CHECK-NEXT: |-RecoveryExpr {{.*}} ''
+  // CHECK-NEXT: | |-DeclRefExpr {{.*}} 'int *' lvalue
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'float' lvalue
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int *' lvalue
+  // CHECK-NEXT: `-DeclRefExpr {{.*}} 'float' lvalue
+  ptr > f ? ptr : f;
 }
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -8067,6 +8067,16 @@
   VK = VK_RValue;
   OK = OK_Ordinary;
 
+  if (Context.isDependenceAllowed() &&
+  (Cond.get()->isTypeDependent() || LHS.get()->isTypeDependent() ||
+   RHS.get()->isTypeDependent())) {
+assert(!getLangOpts().CPlusPlus);
+assert(Cond.get()->containsErrors() || LHS.get()->containsErrors() ||
+   RHS.get()->containsErrors() &&
+   "should only occur in error-recovery path.");
+return Context.DependentTy;
+  }
+
   // The OpenCL operator with a vector condition is sufficiently
   // different to merit its own checker.
   if ((getLangOpts().OpenCL && Cond.get()->getType()->isVectorType()) ||
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D84226: [AST][RecoveryExpr] Part1: Support dependent binary operator in C for error recovery.

2020-10-06 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG70d9dc867417: [AST][RecoveryExpr] Support dependent binary 
operator in C for error recovery. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84226

Files:
  clang/include/clang/AST/ASTContext.h
  clang/lib/Sema/SemaExpr.cpp
  clang/test/AST/ast-dump-recovery.c
  clang/test/Sema/error-dependence.c

Index: clang/test/Sema/error-dependence.c
===
--- /dev/null
+++ clang/test/Sema/error-dependence.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -frecovery-ast -fno-recovery-ast-type %s
+
+int call(int); // expected-note {{'call' declared here}}
+
+void test1(int s) {
+  // verify "assigning to 'int' from incompatible type ''" is
+  // not emitted.
+  s = call(); // expected-error {{too few arguments to function call}}
+}
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -42,11 +42,33 @@
 
 void test2() {
   int* ptr;
-  // FIXME: the top-level expr should be a binary operator.
-  // CHECK:  ImplicitCastExpr {{.*}} contains-errors 
-  // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors lvalue
-  // CHECK-NEXT:   |-DeclRefExpr {{.*}} 'ptr' 'int *'
-  // CHECK-NEXT:   `-RecoveryExpr {{.*}}
-  // CHECK-NEXT: `-DeclRefExpr {{.*}} 'some_func'
+  // CHECK: BinaryOperator {{.*}} 'int *' contains-errors '='
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'ptr' 'int *'
+  // CHECK-NEXT: `-RecoveryExpr {{.*}}
+  // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
   ptr = some_func(); // should not crash
+
+  int compoundOp;
+  // CHECK: CompoundAssignOperator {{.*}} 'int' contains-errors '+='
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'compoundOp'
+  // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors
+  // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
+  compoundOp += some_func();
+
+  // CHECK: BinaryOperator {{.*}} 'int' contains-errors '||'
+  // CHECK-NEXT: |-RecoveryExpr {{.*}}
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'some_func'
+  // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+  some_func() || 1;
+
+  // CHECK: BinaryOperator {{.*}} '' contains-errors ','
+  // CHECK-NEXT: |-IntegerLiteral {{.*}} 'int' 1
+  // CHECK-NEXT: `-RecoveryExpr {{.*}}
+  // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
+  1, some_func();
+  // CHECK: BinaryOperator {{.*}} 'int' contains-errors ','
+  // CHECK-NEXT: |-RecoveryExpr {{.*}} ''
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'some_func'
+  // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+  some_func(), 1;
 }
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -24,6 +24,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/ExprOpenMP.h"
+#include "clang/AST/OperationKinds.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Builtins.h"
@@ -13683,7 +13684,7 @@
 CorrectDelayedTyposInBinOp(Sema , BinaryOperatorKind Opc, Expr *LHSExpr,
Expr *RHSExpr) {
   ExprResult LHS = LHSExpr, RHS = RHSExpr;
-  if (!S.getLangOpts().CPlusPlus) {
+  if (!S.Context.isDependenceAllowed()) {
 // C cannot handle TypoExpr nodes on either side of a binop because it
 // doesn't handle dependent types properly, so make sure any TypoExprs have
 // been dealt with before checking the operands.
@@ -14364,6 +14365,47 @@
   return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
   }
 
+  if (getLangOpts().RecoveryAST &&
+  (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())) {
+assert(!getLangOpts().CPlusPlus);
+assert((LHSExpr->containsErrors() || RHSExpr->containsErrors()) &&
+   "Should only occur in error-recovery path.");
+if (BinaryOperator::isCompoundAssignmentOp(Opc))
+  // C [6.15.16] p3:
+  // An assignment expression has the value of the left operand after the
+  // assignment, but is not an lvalue.
+  return CompoundAssignOperator::Create(
+  Context, LHSExpr, RHSExpr, Opc,
+  LHSExpr->getType().getUnqualifiedType(), VK_RValue, OK_Ordinary,
+  OpLoc, CurFPFeatureOverrides());
+QualType ResultType;
+switch (Opc) {
+case BO_Assign:
+  ResultType = LHSExpr->getType().getUnqualifiedType();
+  break;
+case BO_LT:
+case BO_GT:
+case BO_LE:
+case BO_GE:
+case BO_EQ:
+case BO_NE:
+case BO_LAnd:
+case BO_LOr:
+  // These operators have a fixed result type regardless of operands.
+  ResultType = Context.IntTy;
+  break;
+case BO_Comma:
+   

[PATCH] D84226: [AST][RecoveryExpr] Part1: Support dependent binary operator in C for error recovery.

2020-10-06 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296367.
hokein marked 2 inline comments as done.
hokein added a comment.

address comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84226

Files:
  clang/include/clang/AST/ASTContext.h
  clang/lib/Sema/SemaExpr.cpp
  clang/test/AST/ast-dump-recovery.c
  clang/test/Sema/error-dependence.c

Index: clang/test/Sema/error-dependence.c
===
--- /dev/null
+++ clang/test/Sema/error-dependence.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -frecovery-ast -fno-recovery-ast-type %s
+
+int call(int); // expected-note {{'call' declared here}}
+
+void test1(int s) {
+  // verify "assigning to 'int' from incompatible type ''" is
+  // not emitted.
+  s = call(); // expected-error {{too few arguments to function call}}
+}
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -42,11 +42,33 @@
 
 void test2() {
   int* ptr;
-  // FIXME: the top-level expr should be a binary operator.
-  // CHECK:  ImplicitCastExpr {{.*}} contains-errors 
-  // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors lvalue
-  // CHECK-NEXT:   |-DeclRefExpr {{.*}} 'ptr' 'int *'
-  // CHECK-NEXT:   `-RecoveryExpr {{.*}}
-  // CHECK-NEXT: `-DeclRefExpr {{.*}} 'some_func'
+  // CHECK: BinaryOperator {{.*}} 'int *' contains-errors '='
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'ptr' 'int *'
+  // CHECK-NEXT: `-RecoveryExpr {{.*}}
+  // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
   ptr = some_func(); // should not crash
+
+  int compoundOp;
+  // CHECK: CompoundAssignOperator {{.*}} 'int' contains-errors '+='
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'compoundOp'
+  // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors
+  // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
+  compoundOp += some_func();
+
+  // CHECK: BinaryOperator {{.*}} 'int' contains-errors '||'
+  // CHECK-NEXT: |-RecoveryExpr {{.*}}
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'some_func'
+  // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+  some_func() || 1;
+
+  // CHECK: BinaryOperator {{.*}} '' contains-errors ','
+  // CHECK-NEXT: |-IntegerLiteral {{.*}} 'int' 1
+  // CHECK-NEXT: `-RecoveryExpr {{.*}}
+  // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
+  1, some_func();
+  // CHECK: BinaryOperator {{.*}} 'int' contains-errors ','
+  // CHECK-NEXT: |-RecoveryExpr {{.*}} ''
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'some_func'
+  // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+  some_func(), 1;
 }
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -24,6 +24,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/ExprOpenMP.h"
+#include "clang/AST/OperationKinds.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Builtins.h"
@@ -13683,7 +13684,7 @@
 CorrectDelayedTyposInBinOp(Sema , BinaryOperatorKind Opc, Expr *LHSExpr,
Expr *RHSExpr) {
   ExprResult LHS = LHSExpr, RHS = RHSExpr;
-  if (!S.getLangOpts().CPlusPlus) {
+  if (!S.Context.isDependenceAllowed()) {
 // C cannot handle TypoExpr nodes on either side of a binop because it
 // doesn't handle dependent types properly, so make sure any TypoExprs have
 // been dealt with before checking the operands.
@@ -14364,6 +14365,47 @@
   return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
   }
 
+  if (getLangOpts().RecoveryAST &&
+  (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())) {
+assert(!getLangOpts().CPlusPlus);
+assert((LHSExpr->containsErrors() || RHSExpr->containsErrors()) &&
+   "Should only occur in error-recovery path.");
+if (BinaryOperator::isCompoundAssignmentOp(Opc))
+  // C [6.15.16] p3:
+  // An assignment expression has the value of the left operand after the
+  // assignment, but is not an lvalue.
+  return CompoundAssignOperator::Create(
+  Context, LHSExpr, RHSExpr, Opc,
+  LHSExpr->getType().getUnqualifiedType(), VK_RValue, OK_Ordinary,
+  OpLoc, CurFPFeatureOverrides());
+QualType ResultType;
+switch (Opc) {
+case BO_Assign:
+  ResultType = LHSExpr->getType().getUnqualifiedType();
+  break;
+case BO_LT:
+case BO_GT:
+case BO_LE:
+case BO_GE:
+case BO_EQ:
+case BO_NE:
+case BO_LAnd:
+case BO_LOr:
+  // These operators have a fixed result type regardless of operands.
+  ResultType = Context.IntTy;
+  break;
+case BO_Comma:
+  ResultType = RHSExpr->getType();
+  break;
+default:
+  ResultType = Context.DependentTy;
+  break;
+}
+

[PATCH] D84226: [AST][RecoveryExpr] Part1: Support dependent binary operator in C for error recovery.

2020-10-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang/lib/Sema/SemaExpr.cpp:14365
+   "Should only occur in error-recovery path.");
+if (BinaryOperator::isCompoundAssignmentOp(Opc))
+  return CompoundAssignOperator::Create(

sammccall wrote:
> isAssignmentOp instead? including = itself
Simple assignment `=` doesn't belong to `CompoundAssignOperator`, it should be 
`BinaryOperator`.

Added the handling logic in the switch-case below.



Comment at: clang/test/AST/ast-dump-recovery.c:45
   int* ptr;
-  // FIXME: the top-level expr should be a binary operator.
-  // CHECK:  ImplicitCastExpr {{.*}} contains-errors 
-  // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors lvalue
-  // CHECK-NEXT:   |-DeclRefExpr {{.*}} 'ptr' 'int *'
-  // CHECK-NEXT:   `-RecoveryExpr {{.*}}
-  // CHECK-NEXT: `-DeclRefExpr {{.*}} 'some_func'
+  // CHECK: BinaryOperator {{.*}} contains-errors '='
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'ptr' 'int *'

sammccall wrote:
> `'int *' lvalue contains-errors '='`
oh, this spots a bug in our code -- unlike C++, it should not be a lvalue.

From  C [6.15.16] p3:
> An assignment expression has the value of the left operand after the 
> assignment, but is not an lvalue.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84226

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


[PATCH] D84226: [AST][RecoveryExpr] Part1: Support dependent binary operator in C for error recovery.

2020-10-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296218.
hokein marked 2 inline comments as done.
hokein added a comment.

address comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84226

Files:
  clang/include/clang/AST/ASTContext.h
  clang/lib/Sema/SemaExpr.cpp
  clang/test/AST/ast-dump-recovery.c
  clang/test/Sema/error-dependence.c

Index: clang/test/Sema/error-dependence.c
===
--- /dev/null
+++ clang/test/Sema/error-dependence.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -frecovery-ast -fno-recovery-ast-type %s
+
+int call(int); // expected-note {{'call' declared here}}
+
+void test1(int s) {
+  // verify "assigning to 'int' from incompatible type ''" is
+  // not emitted.
+  s = call(); // expected-error {{too few arguments to function call}}
+}
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -42,11 +42,33 @@
 
 void test2() {
   int* ptr;
-  // FIXME: the top-level expr should be a binary operator.
-  // CHECK:  ImplicitCastExpr {{.*}} contains-errors 
-  // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors lvalue
-  // CHECK-NEXT:   |-DeclRefExpr {{.*}} 'ptr' 'int *'
-  // CHECK-NEXT:   `-RecoveryExpr {{.*}}
-  // CHECK-NEXT: `-DeclRefExpr {{.*}} 'some_func'
+  // CHECK: BinaryOperator {{.*}} 'int *' contains-errors '='
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'ptr' 'int *'
+  // CHECK-NEXT: `-RecoveryExpr {{.*}}
+  // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
   ptr = some_func(); // should not crash
+
+  int compoundOp;
+  // CHECK: CompoundAssignOperator {{.*}} 'int' contains-errors '+='
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'compoundOp'
+  // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors
+  // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
+  compoundOp += some_func();
+
+  // CHECK: BinaryOperator {{.*}} 'int' contains-errors '||'
+  // CHECK-NEXT: |-RecoveryExpr {{.*}}
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'some_func'
+  // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+  some_func() || 1;
+
+  // CHECK: BinaryOperator {{.*}} '' contains-errors ','
+  // CHECK-NEXT: |-IntegerLiteral {{.*}} 'int' 1
+  // CHECK-NEXT: `-RecoveryExpr {{.*}}
+  // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'some_func'
+  1, some_func();
+  // CHECK: BinaryOperator {{.*}} 'int' contains-errors ','
+  // CHECK-NEXT: |-RecoveryExpr {{.*}} ''
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'some_func'
+  // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+  some_func(), 1;
 }
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -24,6 +24,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/ExprOpenMP.h"
+#include "clang/AST/OperationKinds.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Builtins.h"
@@ -13683,7 +13684,7 @@
 CorrectDelayedTyposInBinOp(Sema , BinaryOperatorKind Opc, Expr *LHSExpr,
Expr *RHSExpr) {
   ExprResult LHS = LHSExpr, RHS = RHSExpr;
-  if (!S.getLangOpts().CPlusPlus) {
+  if (!S.Context.isDependenceAllowed()) {
 // C cannot handle TypoExpr nodes on either side of a binop because it
 // doesn't handle dependent types properly, so make sure any TypoExprs have
 // been dealt with before checking the operands.
@@ -14364,6 +14365,49 @@
   return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
   }
 
+  if (getLangOpts().RecoveryAST &&
+  (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())) {
+assert(!getLangOpts().CPlusPlus);
+assert((LHSExpr->containsErrors() || RHSExpr->containsErrors()) &&
+   "Should only occur in error-recovery path.");
+if (BinaryOperator::isCompoundAssignmentOp(Opc))
+  // C [6.15.16] p3:
+  // An assignment expression has the value of the left operand after the
+  // assignment, but is not an lvalue.
+  return CompoundAssignOperator::Create(
+  Context, LHSExpr, RHSExpr, Opc,
+  LHSExpr->getType().getUnqualifiedType(), VK_RValue, OK_Ordinary,
+  OpLoc, CurFPFeatureOverrides());
+switch (Opc) {
+case BO_Assign:
+  return BinaryOperator::Create(Context, LHSExpr, RHSExpr, Opc,
+LHSExpr->getType().getUnqualifiedType(),
+VK_RValue, OK_Ordinary, OpLoc,
+CurFPFeatureOverrides());
+case BO_LT:
+case BO_GT:
+case BO_LE:
+case BO_GE:
+case BO_EQ:
+case BO_NE:
+
+case BO_LAnd:
+case BO_LOr:
+  // These operators have a fixed result type regardless of operands.
+  return 

[PATCH] D88810: [clangd] Add isKeyword function.

2020-10-05 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG1425c7223676: [clangd] Add isKeyword function. (authored by 
hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88810

Files:
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/SourceCode.h
  clang-tools-extra/clangd/unittests/SourceCodeTests.cpp


Index: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
===
--- clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
@@ -789,6 +789,19 @@
   EXPECT_TRUE(isHeaderFile("header.h", LangOpts));
 }
 
+TEST(SourceCodeTests, isKeywords) {
+  LangOptions LangOpts;
+  LangOpts.CPlusPlus20 = true;
+  EXPECT_TRUE(isKeyword("int", LangOpts));
+  EXPECT_TRUE(isKeyword("return", LangOpts));
+  EXPECT_TRUE(isKeyword("co_await", LangOpts));
+
+  // these are identifiers (not keywords!) with special meaning in some
+  // contexts.
+  EXPECT_FALSE(isKeyword("final", LangOpts));
+  EXPECT_FALSE(isKeyword("override", LangOpts));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SourceCode.h
===
--- clang-tools-extra/clangd/SourceCode.h
+++ clang-tools-extra/clangd/SourceCode.h
@@ -248,6 +248,10 @@
   const LangOptions );
 };
 
+/// Return true if the \p TokenName is in the list of reversed keywords of the
+/// language.
+bool isKeyword(llvm::StringRef TokenName, const LangOptions );
+
 /// Heuristically determine namespaces visible at a point, without parsing 
Code.
 /// This considers using-directives and enclosing namespace-declarations that
 /// are visible (and not obfuscated) in the file itself (not headers).
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -633,6 +633,12 @@
   return Ranges;
 }
 
+bool isKeyword(llvm::StringRef NewName, const LangOptions ) {
+  // Keywords are initialized in constructor.
+  clang::IdentifierTable KeywordsTable(LangOpts);
+  return KeywordsTable.find(NewName) != KeywordsTable.end();
+}
+
 namespace {
 struct NamespaceEvent {
   enum {


Index: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
===
--- clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
@@ -789,6 +789,19 @@
   EXPECT_TRUE(isHeaderFile("header.h", LangOpts));
 }
 
+TEST(SourceCodeTests, isKeywords) {
+  LangOptions LangOpts;
+  LangOpts.CPlusPlus20 = true;
+  EXPECT_TRUE(isKeyword("int", LangOpts));
+  EXPECT_TRUE(isKeyword("return", LangOpts));
+  EXPECT_TRUE(isKeyword("co_await", LangOpts));
+
+  // these are identifiers (not keywords!) with special meaning in some
+  // contexts.
+  EXPECT_FALSE(isKeyword("final", LangOpts));
+  EXPECT_FALSE(isKeyword("override", LangOpts));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SourceCode.h
===
--- clang-tools-extra/clangd/SourceCode.h
+++ clang-tools-extra/clangd/SourceCode.h
@@ -248,6 +248,10 @@
   const LangOptions );
 };
 
+/// Return true if the \p TokenName is in the list of reversed keywords of the
+/// language.
+bool isKeyword(llvm::StringRef TokenName, const LangOptions );
+
 /// Heuristically determine namespaces visible at a point, without parsing Code.
 /// This considers using-directives and enclosing namespace-declarations that
 /// are visible (and not obfuscated) in the file itself (not headers).
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -633,6 +633,12 @@
   return Ranges;
 }
 
+bool isKeyword(llvm::StringRef NewName, const LangOptions ) {
+  // Keywords are initialized in constructor.
+  clang::IdentifierTable KeywordsTable(LangOpts);
+  return KeywordsTable.find(NewName) != KeywordsTable.end();
+}
+
 namespace {
 struct NamespaceEvent {
   enum {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D88810: [clangd] Add isKeyword function.

2020-10-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/SourceCode.cpp:638
+  // Keywords are initialized in constructor.
+  clang::IdentifierTable KeywordsTable(LangOpts);
+  return KeywordsTable.find(NewName) != KeywordsTable.end();

sammccall wrote:
> this builds a pretty decent sized hashtable for each call, because LangOpts 
> isn't constant.
> 
> We could consider exposing getKeywordStatus from IdentifierTable.h, then we 
> could build a StringMap (once, statically) and then call 
> getKeywordStatus to apply the per-langopts logic.
> In fact that StringMap might also be generally nice to expose in 
> TokenKinds.h... as long as there are no conflicts.
> 
> Or we could have cache map from LangOpts to IdentifierTable, since we won't 
> see many sets in practice.
> 
> Or maybe it doesn't matter, I suppose!
> Or maybe it doesn't matter, I suppose!
this is my impression as well, there are ~120 keywords for C++, I think the 
number is not too big.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88810

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


[PATCH] D88810: [clangd] Add isKeyword function.

2020-10-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296168.
hokein marked an inline comment as done.
hokein added a comment.

address code comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88810

Files:
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/SourceCode.h
  clang-tools-extra/clangd/unittests/SourceCodeTests.cpp


Index: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
===
--- clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
@@ -789,6 +789,19 @@
   EXPECT_TRUE(isHeaderFile("header.h", LangOpts));
 }
 
+TEST(SourceCodeTests, isKeywords) {
+  LangOptions LangOpts;
+  LangOpts.CPlusPlus20 = true;
+  EXPECT_TRUE(isKeyword("int", LangOpts));
+  EXPECT_TRUE(isKeyword("return", LangOpts));
+  EXPECT_TRUE(isKeyword("co_await", LangOpts));
+
+  // these are identifiers (not keywords!) with special meaning in some
+  // contexts.
+  EXPECT_FALSE(isKeyword("final", LangOpts));
+  EXPECT_FALSE(isKeyword("override", LangOpts));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SourceCode.h
===
--- clang-tools-extra/clangd/SourceCode.h
+++ clang-tools-extra/clangd/SourceCode.h
@@ -248,6 +248,10 @@
   const LangOptions );
 };
 
+/// Return true if the \p TokenName is in the list of reversed keywords of the
+/// language.
+bool isKeyword(llvm::StringRef TokenName, const LangOptions );
+
 /// Heuristically determine namespaces visible at a point, without parsing 
Code.
 /// This considers using-directives and enclosing namespace-declarations that
 /// are visible (and not obfuscated) in the file itself (not headers).
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -633,6 +633,12 @@
   return Ranges;
 }
 
+bool isKeyword(llvm::StringRef NewName, const LangOptions ) {
+  // Keywords are initialized in constructor.
+  clang::IdentifierTable KeywordsTable(LangOpts);
+  return KeywordsTable.find(NewName) != KeywordsTable.end();
+}
+
 namespace {
 struct NamespaceEvent {
   enum {


Index: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
===
--- clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
@@ -789,6 +789,19 @@
   EXPECT_TRUE(isHeaderFile("header.h", LangOpts));
 }
 
+TEST(SourceCodeTests, isKeywords) {
+  LangOptions LangOpts;
+  LangOpts.CPlusPlus20 = true;
+  EXPECT_TRUE(isKeyword("int", LangOpts));
+  EXPECT_TRUE(isKeyword("return", LangOpts));
+  EXPECT_TRUE(isKeyword("co_await", LangOpts));
+
+  // these are identifiers (not keywords!) with special meaning in some
+  // contexts.
+  EXPECT_FALSE(isKeyword("final", LangOpts));
+  EXPECT_FALSE(isKeyword("override", LangOpts));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SourceCode.h
===
--- clang-tools-extra/clangd/SourceCode.h
+++ clang-tools-extra/clangd/SourceCode.h
@@ -248,6 +248,10 @@
   const LangOptions );
 };
 
+/// Return true if the \p TokenName is in the list of reversed keywords of the
+/// language.
+bool isKeyword(llvm::StringRef TokenName, const LangOptions );
+
 /// Heuristically determine namespaces visible at a point, without parsing Code.
 /// This considers using-directives and enclosing namespace-declarations that
 /// are visible (and not obfuscated) in the file itself (not headers).
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -633,6 +633,12 @@
   return Ranges;
 }
 
+bool isKeyword(llvm::StringRef NewName, const LangOptions ) {
+  // Keywords are initialized in constructor.
+  clang::IdentifierTable KeywordsTable(LangOpts);
+  return KeywordsTable.find(NewName) != KeywordsTable.end();
+}
+
 namespace {
 struct NamespaceEvent {
   enum {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D88828: [clangd] Verify the diagnostic code in include-fixer diagnostic tests, NFC.

2020-10-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: kadircet.
Herald added subscribers: usaxena95, arphaman.
Herald added a project: clang.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D88828

Files:
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -720,13 +720,16 @@
   UnorderedElementsAre(
   AllOf(Diag(Test.range("nested"),
  "incomplete type 'ns::X' named in nested name specifier"),
+DiagName("incomplete_nested_name_spec"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
 "Add include \"x.h\" for symbol ns::X"))),
   AllOf(Diag(Test.range("base"), "base class has incomplete type"),
+DiagName("incomplete_base_class"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
 "Add include \"x.h\" for symbol ns::X"))),
   AllOf(Diag(Test.range("access"),
  "member access into incomplete type 'ns::X'"),
+DiagName("incomplete_member_access"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
 "Add include \"x.h\" for symbol ns::X");
 }
@@ -789,19 +792,23 @@
   TU.build().getDiagnostics(),
   UnorderedElementsAre(
   AllOf(Diag(Test.range("unqualified1"), "unknown type name 'X'"),
+DiagName("unknown_typename"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
 "Add include \"x.h\" for symbol ns::X"))),
   Diag(Test.range("unqualified2"), "use of undeclared identifier 'X'"),
   AllOf(Diag(Test.range("qualified1"),
  "no type named 'X' in namespace 'ns'"),
+DiagName("typename_nested_not_found"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
 "Add include \"x.h\" for symbol ns::X"))),
   AllOf(Diag(Test.range("qualified2"),
  "no member named 'X' in namespace 'ns'"),
+DiagName("no_member"),
 WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
 "Add include \"x.h\" for symbol ns::X"))),
   AllOf(Diag(Test.range("global"),
  "no type named 'Global' in the global namespace"),
+DiagName("typename_nested_not_found"),
 WithFix(Fix(Test.range("insert"), "#include \"global.h\"\n",
 "Add include \"global.h\" for symbol Global");
 }
@@ -825,6 +832,7 @@
   EXPECT_THAT(TU.build().getDiagnostics(),
   UnorderedElementsAre(AllOf(
   Diag(Test.range("unqualified"), "unknown type name 'X'"),
+  DiagName("unknown_typename"),
   WithFix(Fix(Test.range("insert"), "#include \"a.h\"\n",
   "Add include \"a.h\" for symbol na::X"),
   Fix(Test.range("insert"), "#include \"b.h\"\n",
@@ -905,6 +913,7 @@
   TU.build().getDiagnostics(),
   UnorderedElementsAre(AllOf(
   Diag(Test.range(), "no member named 'scope' in namespace 'ns'"),
+  DiagName("no_member"),
   WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
   "Add include \"x.h\" for symbol ns::scope::X_Y");
 }
@@ -934,22 +943,26 @@
   AllOf(
   Diag(Test.range("q1"), "use of undeclared identifier 'clangd'; "
  "did you mean 'clang'?"),
+  DiagName("undeclared_var_use_suggest"),
   WithFix(_, // change clangd to clang
   Fix(Test.range("insert"), "#include \"x.h\"\n",
   "Add include \"x.h\" for symbol clang::clangd::X"))),
   AllOf(
   Diag(Test.range("x"), "no type named 'X' in namespace 'clang'"),
+  DiagName("typename_nested_not_found"),
   WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
   "Add include \"x.h\" for symbol clang::clangd::X"))),
   AllOf(
   Diag(Test.range("q2"), "use of undeclared identifier 'clangd'; "
  "did you mean 'clang'?"),
+  DiagName("undeclared_var_use_suggest"),
   WithFix(
-  _, // change clangd to clangd
+  _, // change clangd to clang
   Fix(Test.range("insert"), "#include \"y.h\"\n",
   "Add include \"y.h\" for symbol 

[PATCH] D87350: [AST][RecoveryExpr] Fix a crash on undeduced type.

2020-10-05 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG7f05fe1aeeb0: [AST][RecoveryExpr] Fix a crash on undeduced 
type. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D87350

Files:
  clang/lib/Sema/SemaOverload.cpp
  clang/test/AST/ast-dump-recovery.cpp
  clang/test/SemaCXX/recovery-expr-type.cpp


Index: clang/test/SemaCXX/recovery-expr-type.cpp
===
--- clang/test/SemaCXX/recovery-expr-type.cpp
+++ clang/test/SemaCXX/recovery-expr-type.cpp
@@ -105,3 +105,9 @@
 int v = arr(); // expected-error {{array types cannot be value-initialized}} \
   expected-error {{cannot initialize a variable of type 'int' 
with an rvalue of type 'test8::arr'}}
 }
+
+namespace test9 {
+auto f(); // expected-note {{candidate function not viable}}
+// verify no crash on evaluating the size of undeduced auto type.
+static_assert(sizeof(f(1)), ""); // expected-error {{no matching function for 
call to 'f'}}
+}
Index: clang/test/AST/ast-dump-recovery.cpp
===
--- clang/test/AST/ast-dump-recovery.cpp
+++ clang/test/AST/ast-dump-recovery.cpp
@@ -126,6 +126,12 @@
 // CHECK-NEXT:|   `-UnresolvedLookupExpr {{.*}} 'invalid'
 struct alignas(invalid()) Aligned {};
 
+auto f();
+int f(double);
+// CHECK:  VarDecl {{.*}} unknown_type_call 'int'
+// CHECK-NEXT: `-RecoveryExpr {{.*}} ''
+int unknown_type_call = f(0, 0);
+
 void InvalidInitalizer(int x) {
   struct Bar { Bar(); };
   // CHECK: `-VarDecl {{.*}} a1 'Bar'
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -12880,7 +12880,12 @@
 for (const auto  : CS)
   ConsiderCandidate(C);
 
-  return Result.getValueOr(QualType());
+  if (!Result)
+return QualType();
+  auto Value = Result.getValue();
+  if (Value.isNull() || Value->isUndeducedType())
+return QualType();
+  return Value;
 }
 
 /// FinishOverloadedCallExpr - given an OverloadCandidateSet, builds and 
returns


Index: clang/test/SemaCXX/recovery-expr-type.cpp
===
--- clang/test/SemaCXX/recovery-expr-type.cpp
+++ clang/test/SemaCXX/recovery-expr-type.cpp
@@ -105,3 +105,9 @@
 int v = arr(); // expected-error {{array types cannot be value-initialized}} \
   expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'test8::arr'}}
 }
+
+namespace test9 {
+auto f(); // expected-note {{candidate function not viable}}
+// verify no crash on evaluating the size of undeduced auto type.
+static_assert(sizeof(f(1)), ""); // expected-error {{no matching function for call to 'f'}}
+}
Index: clang/test/AST/ast-dump-recovery.cpp
===
--- clang/test/AST/ast-dump-recovery.cpp
+++ clang/test/AST/ast-dump-recovery.cpp
@@ -126,6 +126,12 @@
 // CHECK-NEXT:|   `-UnresolvedLookupExpr {{.*}} 'invalid'
 struct alignas(invalid()) Aligned {};
 
+auto f();
+int f(double);
+// CHECK:  VarDecl {{.*}} unknown_type_call 'int'
+// CHECK-NEXT: `-RecoveryExpr {{.*}} ''
+int unknown_type_call = f(0, 0);
+
 void InvalidInitalizer(int x) {
   struct Bar { Bar(); };
   // CHECK: `-VarDecl {{.*}} a1 'Bar'
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -12880,7 +12880,12 @@
 for (const auto  : CS)
   ConsiderCandidate(C);
 
-  return Result.getValueOr(QualType());
+  if (!Result)
+return QualType();
+  auto Value = Result.getValue();
+  if (Value.isNull() || Value->isUndeducedType())
+return QualType();
+  return Value;
 }
 
 /// FinishOverloadedCallExpr - given an OverloadCandidateSet, builds and returns
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D84226: [AST][RecoveryExpr] Part1: Support dependent binary operator in C for error recovery.

2020-10-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

I think this patch is ready for another round of review.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84226

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


[PATCH] D87350: [AST][RecoveryExpr] Fix a crash on undeduced type.

2020-10-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang/lib/Sema/SemaOverload.cpp:12880
 
   return Result.getValueOr(QualType());
 }

sammccall wrote:
> hokein wrote:
> > sammccall wrote:
> > > Wouldn't we be better to handle undeduced type here rather than in the 
> > > loop?
> > > 
> > > Not sure if it practically matters, but given: `auto f(); double f(int); 
> > > f(0,0);`
> > > the code in this patch will discard auto and yield `double`, while 
> > > treating this as multiple candidates --> unknown return type seems more 
> > > correct.
> > > 
> > I feel like yield `double` is better in your given example -- in this case, 
> > double is the only candidate, so it is reasonable to preserve the `double` 
> > type.
> There are two overloads, one with `double` and one with an unknown type. 
> They're both candidates for the function being called, and I'm not sure we 
> have any reason to believe the first is more likely.
> 
> Two counterarguments I can think of:
>  - the unknown type is probably also double, as overloads tend to have the 
> same return type
>  - the cost of being wrong isn't so high, so it's OK to not be totally sure
> 
> And maybe there are others... these are probably OK justifications but subtle 
> so I'd like to see a comment tothat effect.
thanks, I think the behavior you suggest is more reasonable -- in the given 
example, go-to-def will yield two candidates, it is wired to catch one of the 
return type (not the other).

Addressed it.



Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D87350

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


[PATCH] D87350: [AST][RecoveryExpr] Fix a crash on undeduced type.

2020-10-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 296120.
hokein added a comment.

address comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D87350

Files:
  clang/lib/Sema/SemaOverload.cpp
  clang/test/AST/ast-dump-recovery.cpp
  clang/test/SemaCXX/recovery-expr-type.cpp


Index: clang/test/SemaCXX/recovery-expr-type.cpp
===
--- clang/test/SemaCXX/recovery-expr-type.cpp
+++ clang/test/SemaCXX/recovery-expr-type.cpp
@@ -105,3 +105,9 @@
 int v = arr(); // expected-error {{array types cannot be value-initialized}} \
   expected-error {{cannot initialize a variable of type 'int' 
with an rvalue of type 'test8::arr'}}
 }
+
+namespace test9 {
+auto f(); // expected-note {{candidate function not viable}}
+// verify no crash on evaluating the size of undeduced auto type.
+static_assert(sizeof(f(1)), ""); // expected-error {{no matching function for 
call to 'f'}}
+}
Index: clang/test/AST/ast-dump-recovery.cpp
===
--- clang/test/AST/ast-dump-recovery.cpp
+++ clang/test/AST/ast-dump-recovery.cpp
@@ -126,6 +126,12 @@
 // CHECK-NEXT:|   `-UnresolvedLookupExpr {{.*}} 'invalid'
 struct alignas(invalid()) Aligned {};
 
+auto f();
+int f(double);
+// CHECK:  VarDecl {{.*}} unknown_type_call 'int'
+// CHECK-NEXT: `-RecoveryExpr {{.*}} ''
+int unknown_type_call = f(0, 0);
+
 void InvalidInitalizer(int x) {
   struct Bar { Bar(); };
   // CHECK: `-VarDecl {{.*}} a1 'Bar'
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -12880,7 +12880,12 @@
 for (const auto  : CS)
   ConsiderCandidate(C);
 
-  return Result.getValueOr(QualType());
+  if (!Result)
+return QualType();
+  auto Value = Result.getValue();
+  if (Value.isNull() || Value->isUndeducedType())
+return QualType();
+  return Value;
 }
 
 /// FinishOverloadedCallExpr - given an OverloadCandidateSet, builds and 
returns


Index: clang/test/SemaCXX/recovery-expr-type.cpp
===
--- clang/test/SemaCXX/recovery-expr-type.cpp
+++ clang/test/SemaCXX/recovery-expr-type.cpp
@@ -105,3 +105,9 @@
 int v = arr(); // expected-error {{array types cannot be value-initialized}} \
   expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'test8::arr'}}
 }
+
+namespace test9 {
+auto f(); // expected-note {{candidate function not viable}}
+// verify no crash on evaluating the size of undeduced auto type.
+static_assert(sizeof(f(1)), ""); // expected-error {{no matching function for call to 'f'}}
+}
Index: clang/test/AST/ast-dump-recovery.cpp
===
--- clang/test/AST/ast-dump-recovery.cpp
+++ clang/test/AST/ast-dump-recovery.cpp
@@ -126,6 +126,12 @@
 // CHECK-NEXT:|   `-UnresolvedLookupExpr {{.*}} 'invalid'
 struct alignas(invalid()) Aligned {};
 
+auto f();
+int f(double);
+// CHECK:  VarDecl {{.*}} unknown_type_call 'int'
+// CHECK-NEXT: `-RecoveryExpr {{.*}} ''
+int unknown_type_call = f(0, 0);
+
 void InvalidInitalizer(int x) {
   struct Bar { Bar(); };
   // CHECK: `-VarDecl {{.*}} a1 'Bar'
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -12880,7 +12880,12 @@
 for (const auto  : CS)
   ConsiderCandidate(C);
 
-  return Result.getValueOr(QualType());
+  if (!Result)
+return QualType();
+  auto Value = Result.getValue();
+  if (Value.isNull() || Value->isUndeducedType())
+return QualType();
+  return Value;
 }
 
 /// FinishOverloadedCallExpr - given an OverloadCandidateSet, builds and returns
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D86048: [AST][RecoveryExpr] Popagate the error-bit from a VarDecl's initializer to DeclRefExpr.

2020-10-05 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG3423d5c9da81: [AST][RecoveryExpr] Popagate the error-bit 
from a VarDecls initializer to… (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86048

Files:
  clang/lib/AST/ComputeDependence.cpp
  clang/test/Sema/invalid-member.cpp


Index: clang/test/Sema/invalid-member.cpp
===
--- clang/test/Sema/invalid-member.cpp
+++ clang/test/Sema/invalid-member.cpp
@@ -19,3 +19,11 @@
 };
 // Should be able to evaluate sizeof without crashing.
 static_assert(sizeof(Z) == 1, "No valid members");
+
+constexpr int N = undef; // expected-error {{use of undeclared identifier}}
+template
+class ABC {};
+class T {
+  ABC abc;
+};
+static_assert(sizeof(T) == 1, "No valid members");
Index: clang/lib/AST/ComputeDependence.cpp
===
--- clang/lib/AST/ComputeDependence.cpp
+++ clang/lib/AST/ComputeDependence.cpp
@@ -466,10 +466,12 @@
  : Var->getType()->isIntegralOrEnumerationType()) &&
 (Var->getType().isConstQualified() ||
  Var->getType()->isReferenceType())) {
-  if (const Expr *Init = Var->getAnyInitializer())
-if (Init->isValueDependent()) {
+  if (const Expr *Init = Var->getAnyInitializer()) {
+if (Init->isValueDependent())
   Deps |= ExprDependence::ValueInstantiation;
-}
+if (Init->containsErrors())
+  Deps |= ExprDependence::Error;
+  }
 }
 
 // (VD) - FIXME: Missing from the standard:


Index: clang/test/Sema/invalid-member.cpp
===
--- clang/test/Sema/invalid-member.cpp
+++ clang/test/Sema/invalid-member.cpp
@@ -19,3 +19,11 @@
 };
 // Should be able to evaluate sizeof without crashing.
 static_assert(sizeof(Z) == 1, "No valid members");
+
+constexpr int N = undef; // expected-error {{use of undeclared identifier}}
+template
+class ABC {};
+class T {
+  ABC abc;
+};
+static_assert(sizeof(T) == 1, "No valid members");
Index: clang/lib/AST/ComputeDependence.cpp
===
--- clang/lib/AST/ComputeDependence.cpp
+++ clang/lib/AST/ComputeDependence.cpp
@@ -466,10 +466,12 @@
  : Var->getType()->isIntegralOrEnumerationType()) &&
 (Var->getType().isConstQualified() ||
  Var->getType()->isReferenceType())) {
-  if (const Expr *Init = Var->getAnyInitializer())
-if (Init->isValueDependent()) {
+  if (const Expr *Init = Var->getAnyInitializer()) {
+if (Init->isValueDependent())
   Deps |= ExprDependence::ValueInstantiation;
-}
+if (Init->containsErrors())
+  Deps |= ExprDependence::Error;
+  }
 }
 
 // (VD) - FIXME: Missing from the standard:
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D86048: [AST][RecoveryExpr] Popagate the error-bit from a VarDecl's initializer to DeclRefExpr.

2020-10-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

@rsmith I'm landing this patch now. Happy to follow-up if you have other 
comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86048

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


[PATCH] D88469: [clangd] Heuristic resolution for dependent type and template names

2020-10-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/FindTarget.cpp:578
+for (const NamedDecl *ND : getMembersReferencedViaDependentName(
+ resolveNestedNameSpecifierToType(DTST->getQualifier()),
+ [DTST](ASTContext &) { return DTST->getIdentifier(); },

we need to be robust in `resolveNestedNameSpecifierToType` -- we may get a null 
qualifier for DependentTemplateSpecializationType, see 
https://reviews.llvm.org/D76320.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88469

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


[PATCH] D88810: [clangd] Add isKeyword function.

2020-10-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: sammccall.
Herald added subscribers: usaxena95, kadircet, arphaman.
Herald added a project: clang.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

This will be used in rename for doing basic name validation.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D88810

Files:
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/SourceCode.h
  clang-tools-extra/clangd/unittests/SourceCodeTests.cpp


Index: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
===
--- clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
@@ -789,6 +789,18 @@
   EXPECT_TRUE(isHeaderFile("header.h", LangOpts));
 }
 
+TEST(SourceCodeTests, isKeywords) {
+  LangOptions LangOpts;
+  LangOpts.CPlusPlus11 = true;
+  EXPECT_TRUE(isKeyword("int", LangOpts));
+  EXPECT_TRUE(isKeyword("return", LangOpts));
+
+  // these are identifiers (not keywords!) with special meaning in some
+  // contexts.
+  EXPECT_FALSE(isKeyword("final", LangOpts));
+  EXPECT_FALSE(isKeyword("override", LangOpts));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SourceCode.h
===
--- clang-tools-extra/clangd/SourceCode.h
+++ clang-tools-extra/clangd/SourceCode.h
@@ -248,6 +248,10 @@
   const LangOptions );
 };
 
+/// Return true if the \p TokenName is in the list of reversed keywords of the
+/// language.
+bool isKeyword(llvm::StringRef TokenName, const LangOptions );
+
 /// Heuristically determine namespaces visible at a point, without parsing 
Code.
 /// This considers using-directives and enclosing namespace-declarations that
 /// are visible (and not obfuscated) in the file itself (not headers).
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -633,6 +633,12 @@
   return Ranges;
 }
 
+bool isKeyword(llvm::StringRef NewName, const LangOptions ) {
+  // Keywords are initialized in constructor.
+  clang::IdentifierTable KeywordsTable(LangOpts);
+  return KeywordsTable.find(NewName) != KeywordsTable.end();
+}
+
 namespace {
 struct NamespaceEvent {
   enum {


Index: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
===
--- clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
@@ -789,6 +789,18 @@
   EXPECT_TRUE(isHeaderFile("header.h", LangOpts));
 }
 
+TEST(SourceCodeTests, isKeywords) {
+  LangOptions LangOpts;
+  LangOpts.CPlusPlus11 = true;
+  EXPECT_TRUE(isKeyword("int", LangOpts));
+  EXPECT_TRUE(isKeyword("return", LangOpts));
+
+  // these are identifiers (not keywords!) with special meaning in some
+  // contexts.
+  EXPECT_FALSE(isKeyword("final", LangOpts));
+  EXPECT_FALSE(isKeyword("override", LangOpts));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SourceCode.h
===
--- clang-tools-extra/clangd/SourceCode.h
+++ clang-tools-extra/clangd/SourceCode.h
@@ -248,6 +248,10 @@
   const LangOptions );
 };
 
+/// Return true if the \p TokenName is in the list of reversed keywords of the
+/// language.
+bool isKeyword(llvm::StringRef TokenName, const LangOptions );
+
 /// Heuristically determine namespaces visible at a point, without parsing Code.
 /// This considers using-directives and enclosing namespace-declarations that
 /// are visible (and not obfuscated) in the file itself (not headers).
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -633,6 +633,12 @@
   return Ranges;
 }
 
+bool isKeyword(llvm::StringRef NewName, const LangOptions ) {
+  // Keywords are initialized in constructor.
+  clang::IdentifierTable KeywordsTable(LangOpts);
+  return KeywordsTable.find(NewName) != KeywordsTable.end();
+}
+
 namespace {
 struct NamespaceEvent {
   enum {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D88634: [clangd] Extend the rename API.

2020-10-02 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG0f0cbcc4b166: [clangd] Extend the rename API. (authored by 
hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88634

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/SourceCode.h
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/refactor/Rename.h
  clang-tools-extra/clangd/test/rename.test
  clang-tools-extra/clangd/unittests/RenameTests.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.h

Index: clang-tools-extra/clangd/unittests/SyncAPI.h
===
--- clang-tools-extra/clangd/unittests/SyncAPI.h
+++ clang-tools-extra/clangd/unittests/SyncAPI.h
@@ -40,9 +40,13 @@
 llvm::Expected>
 runFindDocumentHighlights(ClangdServer , PathRef File, Position Pos);
 
-llvm::Expected runRename(ClangdServer , PathRef File,
-Position Pos, StringRef NewName,
-const clangd::RenameOptions );
+llvm::Expected runRename(ClangdServer , PathRef File,
+   Position Pos, StringRef NewName,
+   const clangd::RenameOptions );
+
+llvm::Expected
+runPrepareRename(ClangdServer , PathRef File, Position Pos,
+ const clangd::RenameOptions );
 
 llvm::Expected
 runFormatFile(ClangdServer , PathRef File, StringRef Code);
Index: clang-tools-extra/clangd/unittests/SyncAPI.cpp
===
--- clang-tools-extra/clangd/unittests/SyncAPI.cpp
+++ clang-tools-extra/clangd/unittests/SyncAPI.cpp
@@ -97,14 +97,22 @@
   return std::move(*Result);
 }
 
-llvm::Expected runRename(ClangdServer , PathRef File,
-Position Pos, llvm::StringRef NewName,
-const RenameOptions ) {
-  llvm::Optional> Result;
+llvm::Expected runRename(ClangdServer , PathRef File,
+   Position Pos, llvm::StringRef NewName,
+   const RenameOptions ) {
+  llvm::Optional> Result;
   Server.rename(File, Pos, NewName, RenameOpts, capture(Result));
   return std::move(*Result);
 }
 
+llvm::Expected runPrepareRename(ClangdServer ,
+  PathRef File, Position Pos,
+  const RenameOptions ) {
+  llvm::Optional> Result;
+  Server.prepareRename(File, Pos, RenameOpts, capture(Result));
+  return std::move(*Result);
+}
+
 llvm::Expected
 runFormatFile(ClangdServer , PathRef File, StringRef Code) {
   llvm::Optional> Result;
Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -502,9 +502,10 @@
   auto RenameResult =
   rename({RenamePos, NewName, AST, testPath(TU.Filename)});
   ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError();
-  ASSERT_EQ(1u, RenameResult->size());
-  EXPECT_EQ(applyEdits(std::move(*RenameResult)).front().second,
-expectedResult(Code, NewName));
+  ASSERT_EQ(1u, RenameResult->GlobalChanges.size());
+  EXPECT_EQ(
+  applyEdits(std::move(RenameResult->GlobalChanges)).front().second,
+  expectedResult(Code, NewName));
 }
   }
 }
@@ -653,8 +654,8 @@
 } else {
   EXPECT_TRUE(bool(Results)) << "rename returned an error: "
  << llvm::toString(Results.takeError());
-  ASSERT_EQ(1u, Results->size());
-  EXPECT_EQ(applyEdits(std::move(*Results)).front().second,
+  ASSERT_EQ(1u, Results->GlobalChanges.size());
+  EXPECT_EQ(applyEdits(std::move(Results->GlobalChanges)).front().second,
 expectedResult(T, NewName));
 }
   }
@@ -683,8 +684,8 @@
   auto RenameResult =
   rename({Code.point(), NewName, AST, testPath(TU.Filename)});
   ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError() << Code.point();
-  ASSERT_EQ(1u, RenameResult->size());
-  EXPECT_EQ(applyEdits(std::move(*RenameResult)).front().second,
+  ASSERT_EQ(1u, RenameResult->GlobalChanges.size());
+  EXPECT_EQ(applyEdits(std::move(RenameResult->GlobalChanges)).front().second,
 expectedResult(Code, NewName));
 }
 
@@ -703,6 +704,44 @@
   testing::HasSubstr("not a supported kind"));
 }
 
+TEST(RenameTest, PrepareRename) {
+  Annotations FooH("void func();");
+  Annotations FooCC(R"cpp(
+#include "foo.h"
+void [[fu^nc]]() {}
+  )cpp");
+  

[PATCH] D88634: [clangd] Extend the rename API.

2020-10-02 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 295819.
hokein marked an inline comment as done.
hokein added a comment.

change LocalChanges type to vector


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88634

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/SourceCode.h
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/refactor/Rename.h
  clang-tools-extra/clangd/test/rename.test
  clang-tools-extra/clangd/unittests/RenameTests.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.h

Index: clang-tools-extra/clangd/unittests/SyncAPI.h
===
--- clang-tools-extra/clangd/unittests/SyncAPI.h
+++ clang-tools-extra/clangd/unittests/SyncAPI.h
@@ -40,9 +40,13 @@
 llvm::Expected>
 runFindDocumentHighlights(ClangdServer , PathRef File, Position Pos);
 
-llvm::Expected runRename(ClangdServer , PathRef File,
-Position Pos, StringRef NewName,
-const clangd::RenameOptions );
+llvm::Expected runRename(ClangdServer , PathRef File,
+   Position Pos, StringRef NewName,
+   const clangd::RenameOptions );
+
+llvm::Expected
+runPrepareRename(ClangdServer , PathRef File, Position Pos,
+ const clangd::RenameOptions );
 
 llvm::Expected
 runFormatFile(ClangdServer , PathRef File, StringRef Code);
Index: clang-tools-extra/clangd/unittests/SyncAPI.cpp
===
--- clang-tools-extra/clangd/unittests/SyncAPI.cpp
+++ clang-tools-extra/clangd/unittests/SyncAPI.cpp
@@ -97,14 +97,22 @@
   return std::move(*Result);
 }
 
-llvm::Expected runRename(ClangdServer , PathRef File,
-Position Pos, llvm::StringRef NewName,
-const RenameOptions ) {
-  llvm::Optional> Result;
+llvm::Expected runRename(ClangdServer , PathRef File,
+   Position Pos, llvm::StringRef NewName,
+   const RenameOptions ) {
+  llvm::Optional> Result;
   Server.rename(File, Pos, NewName, RenameOpts, capture(Result));
   return std::move(*Result);
 }
 
+llvm::Expected runPrepareRename(ClangdServer ,
+  PathRef File, Position Pos,
+  const RenameOptions ) {
+  llvm::Optional> Result;
+  Server.prepareRename(File, Pos, RenameOpts, capture(Result));
+  return std::move(*Result);
+}
+
 llvm::Expected
 runFormatFile(ClangdServer , PathRef File, StringRef Code) {
   llvm::Optional> Result;
Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -502,9 +502,10 @@
   auto RenameResult =
   rename({RenamePos, NewName, AST, testPath(TU.Filename)});
   ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError();
-  ASSERT_EQ(1u, RenameResult->size());
-  EXPECT_EQ(applyEdits(std::move(*RenameResult)).front().second,
-expectedResult(Code, NewName));
+  ASSERT_EQ(1u, RenameResult->GlobalChanges.size());
+  EXPECT_EQ(
+  applyEdits(std::move(RenameResult->GlobalChanges)).front().second,
+  expectedResult(Code, NewName));
 }
   }
 }
@@ -653,8 +654,8 @@
 } else {
   EXPECT_TRUE(bool(Results)) << "rename returned an error: "
  << llvm::toString(Results.takeError());
-  ASSERT_EQ(1u, Results->size());
-  EXPECT_EQ(applyEdits(std::move(*Results)).front().second,
+  ASSERT_EQ(1u, Results->GlobalChanges.size());
+  EXPECT_EQ(applyEdits(std::move(Results->GlobalChanges)).front().second,
 expectedResult(T, NewName));
 }
   }
@@ -683,8 +684,8 @@
   auto RenameResult =
   rename({Code.point(), NewName, AST, testPath(TU.Filename)});
   ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError() << Code.point();
-  ASSERT_EQ(1u, RenameResult->size());
-  EXPECT_EQ(applyEdits(std::move(*RenameResult)).front().second,
+  ASSERT_EQ(1u, RenameResult->GlobalChanges.size());
+  EXPECT_EQ(applyEdits(std::move(RenameResult->GlobalChanges)).front().second,
 expectedResult(Code, NewName));
 }
 
@@ -703,6 +704,44 @@
   testing::HasSubstr("not a supported kind"));
 }
 
+TEST(RenameTest, PrepareRename) {
+  Annotations FooH("void func();");
+  Annotations FooCC(R"cpp(
+#include "foo.h"
+void [[fu^nc]]() {}
+  )cpp");
+  std::string FooHPath = testPath("foo.h");
+  std::string FooCCPath = 

[PATCH] D88634: [clangd] Extend the rename API.

2020-10-02 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/refactor/Rename.h:61
+  Range R;
+  FileEdits Edits;
+};

sammccall wrote:
> hokein wrote:
> > sammccall wrote:
> > > It's slightly awkward to have the half-populated state (may or may not 
> > > contain cross-file results, can't tell without the query).
> > > 
> > > I'd consider redundantly including `Edit LocalChanges` and `FileEdits 
> > > GlobalChanges` with the former always set and the latter empty when 
> > > returned from preparerename.
> > > It's slightly awkward to have the half-populated state (may or may not 
> > > contain cross-file results, can't tell without the query).
> > 
> > I feel this is not too bad, the query is quite trivial, just `Edits.size() 
> > > 1`.
> > 
> > > I'd consider redundantly including Edit LocalChanges and FileEdits 
> > > GlobalChanges with the former always set and the latter empty when 
> > > returned from preparerename.
> > 
> > This change seems nice to get changes for main-file, but I think 
> > `GlobalChanges` should include LocalChanges (otherwise, client side needs 
> > to combine these two when applying the final rename edits)? then we can't 
> > leave the later empty while keeping the former set.
> > 
> > Happy to do the change, but it looks like we don't have usage of 
> > `LocalChanges` so far. In prepareRename, we want main-file occurrences, 
> > `rename` will always return them regardless of single-file or cross-file 
> > rename, so I think `Edits` is efficient. 
> > > It's slightly awkward to have the half-populated state (may or may not 
> > > contain cross-file results, can't tell without the query).
> > 
> > I feel this is not too bad, the query is quite trivial, just `Edits.size() 
> > > 1`.
> This isn't sufficient though: if Edits.size() == 1 then the results may be 
> either complete or incomplete. (Sorry my wording above may have been poor, 
> but this is the distinction I was referring to).
> 
> > > I'd consider redundantly including Edit LocalChanges and FileEdits 
> > > GlobalChanges with the former always set and the latter empty when 
> > > returned from preparerename.
> > 
> > This change seems nice to get changes for main-file, but I think 
> > `GlobalChanges` should include LocalChanges (otherwise, client side needs 
> > to combine these two when applying the final rename edits)? then we can't 
> > leave the later empty while keeping the former set.
> 
> Sure we can. `// If the full set of changes is unknown, this field is empty.`
> 
> > Happy to do the change, but it looks like we don't have usage of 
> > `LocalChanges` so far. In prepareRename, we want main-file occurrences, 
> > `rename` will always return them regardless of single-file or cross-file 
> > rename, so I think `Edits` is efficient. 
> 
> Yes, it's possible to implement correct behavior on top of the current API. 
> It effectively reuses the same field with different semantics/contracts, and 
> the client has enough information to know which contract is in place (and 
> throw away the key in the expected singleton map).
> However I think this is fragile and harder to understand than providing 
> separate fields for the two contracts - using types to distinguish local vs 
> global results makes the data harder to misuse. Given we expect this to be 
> used by embedders, I think it's worth adding the second field.
ah, I see your points, agreed. Added the LocalChanges.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88634

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


[PATCH] D88634: [clangd] Extend the rename API.

2020-10-02 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 295798.
hokein marked 2 inline comments as done.
hokein added a comment.

address comment: add the LocalChanges field in RenameResult.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88634

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/SourceCode.h
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/refactor/Rename.h
  clang-tools-extra/clangd/test/rename.test
  clang-tools-extra/clangd/unittests/RenameTests.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.h

Index: clang-tools-extra/clangd/unittests/SyncAPI.h
===
--- clang-tools-extra/clangd/unittests/SyncAPI.h
+++ clang-tools-extra/clangd/unittests/SyncAPI.h
@@ -40,9 +40,13 @@
 llvm::Expected>
 runFindDocumentHighlights(ClangdServer , PathRef File, Position Pos);
 
-llvm::Expected runRename(ClangdServer , PathRef File,
-Position Pos, StringRef NewName,
-const clangd::RenameOptions );
+llvm::Expected runRename(ClangdServer , PathRef File,
+   Position Pos, StringRef NewName,
+   const clangd::RenameOptions );
+
+llvm::Expected
+runPrepareRename(ClangdServer , PathRef File, Position Pos,
+ const clangd::RenameOptions );
 
 llvm::Expected
 runFormatFile(ClangdServer , PathRef File, StringRef Code);
Index: clang-tools-extra/clangd/unittests/SyncAPI.cpp
===
--- clang-tools-extra/clangd/unittests/SyncAPI.cpp
+++ clang-tools-extra/clangd/unittests/SyncAPI.cpp
@@ -97,14 +97,22 @@
   return std::move(*Result);
 }
 
-llvm::Expected runRename(ClangdServer , PathRef File,
-Position Pos, llvm::StringRef NewName,
-const RenameOptions ) {
-  llvm::Optional> Result;
+llvm::Expected runRename(ClangdServer , PathRef File,
+   Position Pos, llvm::StringRef NewName,
+   const RenameOptions ) {
+  llvm::Optional> Result;
   Server.rename(File, Pos, NewName, RenameOpts, capture(Result));
   return std::move(*Result);
 }
 
+llvm::Expected runPrepareRename(ClangdServer ,
+  PathRef File, Position Pos,
+  const RenameOptions ) {
+  llvm::Optional> Result;
+  Server.prepareRename(File, Pos, RenameOpts, capture(Result));
+  return std::move(*Result);
+}
+
 llvm::Expected
 runFormatFile(ClangdServer , PathRef File, StringRef Code) {
   llvm::Optional> Result;
Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -502,8 +502,8 @@
   auto RenameResult =
   rename({RenamePos, NewName, AST, testPath(TU.Filename)});
   ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError();
-  ASSERT_EQ(1u, RenameResult->size());
-  EXPECT_EQ(applyEdits(std::move(*RenameResult)).front().second,
+  ASSERT_EQ(1u, RenameResult->GlobalChanges.size());
+  EXPECT_EQ(applyEdits(std::move(RenameResult->GlobalChanges)).front().second,
 expectedResult(Code, NewName));
 }
   }
@@ -653,8 +653,8 @@
 } else {
   EXPECT_TRUE(bool(Results)) << "rename returned an error: "
  << llvm::toString(Results.takeError());
-  ASSERT_EQ(1u, Results->size());
-  EXPECT_EQ(applyEdits(std::move(*Results)).front().second,
+  ASSERT_EQ(1u, Results->GlobalChanges.size());
+  EXPECT_EQ(applyEdits(std::move(Results->GlobalChanges)).front().second,
 expectedResult(T, NewName));
 }
   }
@@ -683,8 +683,8 @@
   auto RenameResult =
   rename({Code.point(), NewName, AST, testPath(TU.Filename)});
   ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError() << Code.point();
-  ASSERT_EQ(1u, RenameResult->size());
-  EXPECT_EQ(applyEdits(std::move(*RenameResult)).front().second,
+  ASSERT_EQ(1u, RenameResult->GlobalChanges.size());
+  EXPECT_EQ(applyEdits(std::move(RenameResult->GlobalChanges)).front().second,
 expectedResult(Code, NewName));
 }
 
@@ -703,6 +703,46 @@
   testing::HasSubstr("not a supported kind"));
 }
 
+TEST(RenameTest, PrepareRename) {
+  Annotations FooH("void func();");
+  Annotations FooCC(R"cpp(
+#include "foo.h"
+void [[fu^nc]]() {}
+  )cpp");
+  std::string FooHPath = testPath("foo.h");
+  std::string FooCCPath = testPath("foo.cc");
+  MockFS FS;
+  

[PATCH] D88634: [clangd] Extend the rename API.

2020-10-02 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/ClangdServer.cpp:416
+auto Results = clangd::rename(
+{Pos, "dummy", InpAST->AST, File,
+ RenameOpts.AllowCrossFile ?  : Index, RenameOpts});

sammccall wrote:
> we're now returning the "dummy" string to the caller, so we should document 
> it somewhere (or ideally just make it the empty string and document that)
make it empty string, and added document.



Comment at: clang-tools-extra/clangd/refactor/Rename.h:61
+  Range R;
+  FileEdits Edits;
+};

sammccall wrote:
> It's slightly awkward to have the half-populated state (may or may not 
> contain cross-file results, can't tell without the query).
> 
> I'd consider redundantly including `Edit LocalChanges` and `FileEdits 
> GlobalChanges` with the former always set and the latter empty when returned 
> from preparerename.
> It's slightly awkward to have the half-populated state (may or may not 
> contain cross-file results, can't tell without the query).

I feel this is not too bad, the query is quite trivial, just `Edits.size() > 1`.

> I'd consider redundantly including Edit LocalChanges and FileEdits 
> GlobalChanges with the former always set and the latter empty when returned 
> from preparerename.

This change seems nice to get changes for main-file, but I think 
`GlobalChanges` should include LocalChanges (otherwise, client side needs to 
combine these two when applying the final rename edits)? then we can't leave 
the later empty while keeping the former set.

Happy to do the change, but it looks like we don't have usage of `LocalChanges` 
so far. In prepareRename, we want main-file occurrences, `rename` will always 
return them regardless of single-file or cross-file rename, so I think `Edits` 
is efficient. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88634

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


[PATCH] D88634: [clangd] Extend the rename API.

2020-10-02 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 295747.
hokein marked 6 inline comments as done.
hokein added a comment.

address review comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88634

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/SourceCode.h
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/refactor/Rename.h
  clang-tools-extra/clangd/test/rename.test
  clang-tools-extra/clangd/unittests/RenameTests.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.h

Index: clang-tools-extra/clangd/unittests/SyncAPI.h
===
--- clang-tools-extra/clangd/unittests/SyncAPI.h
+++ clang-tools-extra/clangd/unittests/SyncAPI.h
@@ -40,9 +40,13 @@
 llvm::Expected>
 runFindDocumentHighlights(ClangdServer , PathRef File, Position Pos);
 
-llvm::Expected runRename(ClangdServer , PathRef File,
-Position Pos, StringRef NewName,
-const clangd::RenameOptions );
+llvm::Expected runRename(ClangdServer , PathRef File,
+   Position Pos, StringRef NewName,
+   const clangd::RenameOptions );
+
+llvm::Expected
+runPrepareRename(ClangdServer , PathRef File, Position Pos,
+ const clangd::RenameOptions );
 
 llvm::Expected
 runFormatFile(ClangdServer , PathRef File, StringRef Code);
Index: clang-tools-extra/clangd/unittests/SyncAPI.cpp
===
--- clang-tools-extra/clangd/unittests/SyncAPI.cpp
+++ clang-tools-extra/clangd/unittests/SyncAPI.cpp
@@ -97,14 +97,22 @@
   return std::move(*Result);
 }
 
-llvm::Expected runRename(ClangdServer , PathRef File,
-Position Pos, llvm::StringRef NewName,
-const RenameOptions ) {
-  llvm::Optional> Result;
+llvm::Expected runRename(ClangdServer , PathRef File,
+   Position Pos, llvm::StringRef NewName,
+   const RenameOptions ) {
+  llvm::Optional> Result;
   Server.rename(File, Pos, NewName, RenameOpts, capture(Result));
   return std::move(*Result);
 }
 
+llvm::Expected runPrepareRename(ClangdServer ,
+  PathRef File, Position Pos,
+  const RenameOptions ) {
+  llvm::Optional> Result;
+  Server.prepareRename(File, Pos, RenameOpts, capture(Result));
+  return std::move(*Result);
+}
+
 llvm::Expected
 runFormatFile(ClangdServer , PathRef File, StringRef Code) {
   llvm::Optional> Result;
Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -502,8 +502,8 @@
   auto RenameResult =
   rename({RenamePos, NewName, AST, testPath(TU.Filename)});
   ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError();
-  ASSERT_EQ(1u, RenameResult->size());
-  EXPECT_EQ(applyEdits(std::move(*RenameResult)).front().second,
+  ASSERT_EQ(1u, RenameResult->Edits.size());
+  EXPECT_EQ(applyEdits(std::move(RenameResult->Edits)).front().second,
 expectedResult(Code, NewName));
 }
   }
@@ -653,8 +653,8 @@
 } else {
   EXPECT_TRUE(bool(Results)) << "rename returned an error: "
  << llvm::toString(Results.takeError());
-  ASSERT_EQ(1u, Results->size());
-  EXPECT_EQ(applyEdits(std::move(*Results)).front().second,
+  ASSERT_EQ(1u, Results->Edits.size());
+  EXPECT_EQ(applyEdits(std::move(Results->Edits)).front().second,
 expectedResult(T, NewName));
 }
   }
@@ -683,8 +683,8 @@
   auto RenameResult =
   rename({Code.point(), NewName, AST, testPath(TU.Filename)});
   ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError() << Code.point();
-  ASSERT_EQ(1u, RenameResult->size());
-  EXPECT_EQ(applyEdits(std::move(*RenameResult)).front().second,
+  ASSERT_EQ(1u, RenameResult->Edits.size());
+  EXPECT_EQ(applyEdits(std::move(RenameResult->Edits)).front().second,
 expectedResult(Code, NewName));
 }
 
@@ -703,6 +703,43 @@
   testing::HasSubstr("not a supported kind"));
 }
 
+TEST(RenameTest, PrepareRename) {
+  Annotations FooH("void func();");
+  Annotations FooCC(R"cpp(
+#include "foo.h"
+void [[fu^nc]]() {}
+  )cpp");
+  std::string FooHPath = testPath("foo.h");
+  std::string FooCCPath = testPath("foo.cc");
+  MockFS FS;
+  FS.Files[FooHPath] = std::string(FooH.code());
+  FS.Files[FooCCPath] = 

[PATCH] D88640: [Format] Don't treat compound extension headers (foo.proto.h) as foo.cc main file.

2020-10-02 Thread Haojian Wu via Phabricator via cfe-commits
hokein closed this revision.
hokein marked an inline comment as done.
hokein added a comment.

committed in c1b209cc61290f1ce1243470b825e0994645cb7d 
.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88640

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


[PATCH] D88640: [Format] Don't treat compound extension headers (foo.proto.h) as foo.cc main file.

2020-10-01 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: sammccall.
Herald added a project: clang.
hokein requested review of this revision.

We receive internal bugs about this false positives after D86597 
.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D88640

Files:
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
  clang/unittests/Format/SortIncludesTest.cpp


Index: clang/unittests/Format/SortIncludesTest.cpp
===
--- clang/unittests/Format/SortIncludesTest.cpp
+++ clang/unittests/Format/SortIncludesTest.cpp
@@ -151,6 +151,16 @@
   EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), 
"a.cc").empty());
 }
 
+TEST_F(SortIncludesTest, NoMainFileHeader) {
+  std::string Code = "#include \n"
+ "\n"
+ "#include \"a/extra_action.proto.h\"\n";
+  FmtStyle = getGoogleStyle(FormatStyle::LK_Cpp);
+  EXPECT_TRUE(
+  sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a/extra_action.cc")
+  .empty());
+}
+
 TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) {
   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
   EXPECT_EQ("#include \"a.h\"\n"
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -233,7 +233,10 @@
 bool IncludeCategoryManager::isMainHeader(StringRef IncludeName) const {
   if (!IncludeName.startswith("\""))
 return false;
-  StringRef HeaderStem = matchingStem(IncludeName.drop_front(1).drop_back(1));
+
+  StringRef HeaderStem =
+  llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(
+  1) /* remove the surrounding "" or <> */);
   if (FileStem.startswith(HeaderStem) ||
   FileStem.startswith_lower(HeaderStem)) {
 llvm::Regex MainIncludeRegex(HeaderStem.str() + Style.IncludeIsMainRegex,


Index: clang/unittests/Format/SortIncludesTest.cpp
===
--- clang/unittests/Format/SortIncludesTest.cpp
+++ clang/unittests/Format/SortIncludesTest.cpp
@@ -151,6 +151,16 @@
   EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a.cc").empty());
 }
 
+TEST_F(SortIncludesTest, NoMainFileHeader) {
+  std::string Code = "#include \n"
+ "\n"
+ "#include \"a/extra_action.proto.h\"\n";
+  FmtStyle = getGoogleStyle(FormatStyle::LK_Cpp);
+  EXPECT_TRUE(
+  sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a/extra_action.cc")
+  .empty());
+}
+
 TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) {
   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
   EXPECT_EQ("#include \"a.h\"\n"
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -233,7 +233,10 @@
 bool IncludeCategoryManager::isMainHeader(StringRef IncludeName) const {
   if (!IncludeName.startswith("\""))
 return false;
-  StringRef HeaderStem = matchingStem(IncludeName.drop_front(1).drop_back(1));
+
+  StringRef HeaderStem =
+  llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(
+  1) /* remove the surrounding "" or <> */);
   if (FileStem.startswith(HeaderStem) ||
   FileStem.startswith_lower(HeaderStem)) {
 llvm::Regex MainIncludeRegex(HeaderStem.str() + Style.IncludeIsMainRegex,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D88634: [clangd] Extend the rename API.

2020-10-01 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: sammccall.
Herald added subscribers: usaxena95, kadircet, arphaman.
Herald added a project: clang.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

several changes:

- return a structure result in rename API;
- prepareRename now returns more information (main-file occurrences)
- remove the duplicated detecting-touch-identifier code in prepareRename (which 
is implemented in rename API);


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D88634

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/refactor/Rename.h
  clang-tools-extra/clangd/test/rename.test
  clang-tools-extra/clangd/unittests/RenameTests.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.h

Index: clang-tools-extra/clangd/unittests/SyncAPI.h
===
--- clang-tools-extra/clangd/unittests/SyncAPI.h
+++ clang-tools-extra/clangd/unittests/SyncAPI.h
@@ -40,9 +40,13 @@
 llvm::Expected>
 runFindDocumentHighlights(ClangdServer , PathRef File, Position Pos);
 
-llvm::Expected runRename(ClangdServer , PathRef File,
-Position Pos, StringRef NewName,
-const clangd::RenameOptions );
+llvm::Expected
+runRename(ClangdServer , PathRef File, Position Pos, StringRef NewName,
+  const clangd::RenameOptions );
+
+llvm::Expected
+runPrepareRename(ClangdServer , PathRef File, Position Pos,
+ const clangd::RenameOptions );
 
 llvm::Expected
 runFormatFile(ClangdServer , PathRef File, StringRef Code);
Index: clang-tools-extra/clangd/unittests/SyncAPI.cpp
===
--- clang-tools-extra/clangd/unittests/SyncAPI.cpp
+++ clang-tools-extra/clangd/unittests/SyncAPI.cpp
@@ -97,14 +97,22 @@
   return std::move(*Result);
 }
 
-llvm::Expected runRename(ClangdServer , PathRef File,
-Position Pos, llvm::StringRef NewName,
-const RenameOptions ) {
-  llvm::Optional> Result;
+llvm::Expected runRename(ClangdServer , PathRef File,
+Position Pos, llvm::StringRef NewName,
+const RenameOptions ) {
+  llvm::Optional> Result;
   Server.rename(File, Pos, NewName, RenameOpts, capture(Result));
   return std::move(*Result);
 }
 
+llvm::Expected
+runPrepareRename(ClangdServer , PathRef File, Position Pos,
+ const RenameOptions ) {
+  llvm::Optional> Result;
+  Server.prepareRename(File, Pos, RenameOpts, capture(Result));
+  return std::move(*Result);
+}
+
 llvm::Expected
 runFormatFile(ClangdServer , PathRef File, StringRef Code) {
   llvm::Optional> Result;
Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -502,8 +502,8 @@
   auto RenameResult =
   rename({RenamePos, NewName, AST, testPath(TU.Filename)});
   ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError();
-  ASSERT_EQ(1u, RenameResult->size());
-  EXPECT_EQ(applyEdits(std::move(*RenameResult)).front().second,
+  ASSERT_EQ(1u, RenameResult->Edits.size());
+  EXPECT_EQ(applyEdits(std::move(RenameResult->Edits)).front().second,
 expectedResult(Code, NewName));
 }
   }
@@ -653,8 +653,8 @@
 } else {
   EXPECT_TRUE(bool(Results)) << "rename returned an error: "
  << llvm::toString(Results.takeError());
-  ASSERT_EQ(1u, Results->size());
-  EXPECT_EQ(applyEdits(std::move(*Results)).front().second,
+  ASSERT_EQ(1u, Results->Edits.size());
+  EXPECT_EQ(applyEdits(std::move(Results->Edits)).front().second,
 expectedResult(T, NewName));
 }
   }
@@ -683,8 +683,8 @@
   auto RenameResult =
   rename({Code.point(), NewName, AST, testPath(TU.Filename)});
   ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError() << Code.point();
-  ASSERT_EQ(1u, RenameResult->size());
-  EXPECT_EQ(applyEdits(std::move(*RenameResult)).front().second,
+  ASSERT_EQ(1u, RenameResult->Edits.size());
+  EXPECT_EQ(applyEdits(std::move(RenameResult->Edits)).front().second,
 expectedResult(Code, NewName));
 }
 
@@ -703,6 +703,42 @@
   testing::HasSubstr("not a supported kind"));
 }
 
+TEST(RenameTest, PrepareRename) {
+  Annotations FooH("void func();");
+  Annotations FooCC(R"cpp(
+#include "foo.h"
+void [[fu^nc]]() {}
+  )cpp");
+  std::string FooHPath = testPath("foo.h");
+  std::string FooCCPath = testPath("foo.cc");

[PATCH] D88472: [WIP][clangd] Support non-renaming alias underlying decls in TargetDecl.

2020-09-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/unittests/XRefsTests.cpp:1120
   namespace ns { class [[Foo]] {}; }
-  using ns::F^oo;
+  using ns::[[F^oo]];
 )cpp",

sammccall wrote:
> hokein wrote:
> > this seems a small regression, I think it is fine.
> I can't follow why this is different from the second case of
> 
> TEST_F(TargetDeclTest, UsingDecl), where the usingdecl is not reported at all.
I think you over-look it, the second case of `TEST_F(TargetDeclTest, 
UsingDecl)` does report the using-decl.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88472

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


[PATCH] D88472: [WIP][clangd] Support non-renaming alias underlying decls in TargetDecl.

2020-09-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 295238.
hokein added a comment.

refine the patch based on the offline discussion:

- don't set the Underlying bits for using-declaration's underlying decl.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88472

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/FindTarget.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.cpp
  clang-tools-extra/clangd/unittests/XRefsTests.cpp

Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp
===
--- clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -1118,17 +1118,17 @@
   // decls.
   R"cpp(
   namespace ns { class [[Foo]] {}; }
-  using ns::F^oo;
+  using ns::[[F^oo]];
 )cpp",
 
   R"cpp(
   namespace ns { int [[x]](char); int [[x]](double); }
-  using ns::^x;
+  using ns::[[^x]];
 )cpp",
 
   R"cpp(
   namespace ns { int [[x]](char); int x(double); }
-  using ns::x;
+  using ns::[[x]];
   int y = ^x('a');
 )cpp",
 
@@ -1156,7 +1156,7 @@
   };
   template 
   struct Derived : Base {
-using Base::w^aldo;
+using Base::[[w^aldo]];
   };
 )cpp",
   };
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -182,7 +182,7 @@
   )cpp";
   // f(char) is not referenced!
   EXPECT_DECLS("DeclRefExpr", {"using foo::f", Rel::Alias},
-   {"int f(int)", Rel::Underlying});
+   {"int f(int)"});
 
   Code = R"cpp(
 namespace foo {
@@ -193,8 +193,8 @@
   )cpp";
   // All overloads are referenced.
   EXPECT_DECLS("UsingDecl", {"using foo::f", Rel::Alias},
-   {"int f(int)", Rel::Underlying},
-   {"int f(char)", Rel::Underlying});
+   {"int f(int)" },
+   {"int f(char)"});
 
   Code = R"cpp(
 struct X {
@@ -206,7 +206,7 @@
 int x = Y().[[foo]]();
   )cpp";
   EXPECT_DECLS("MemberExpr", {"using X::foo", Rel::Alias},
-   {"int foo()", Rel::Underlying});
+   {"int foo()"});
 
   Code = R"cpp(
   template 
@@ -219,7 +219,7 @@
   };
 )cpp";
   EXPECT_DECLS("UnresolvedUsingValueDecl", {"using Base::waldo", Rel::Alias},
-   {"void waldo()", Rel::Underlying});
+   {"void waldo()"});
 }
 
 TEST_F(TargetDeclTest, ConstructorInitList) {
Index: clang-tools-extra/clangd/XRefs.cpp
===
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -343,18 +343,6 @@
   }
 }
 
-// Give the underlying decl if navigation is triggered on a non-renaming
-// alias.
-if (llvm::isa(D) || llvm::isa(D)) {
-  // FIXME: address more complicated cases. TargetDecl(... Underlying) gives
-  // all overload candidates, we only want the targeted one if the cursor is
-  // on an using-alias usage, workround it with getDeclAtPosition.
-  llvm::for_each(
-  getDeclAtPosition(AST, CurLoc, DeclRelation::Underlying, NodeKind),
-  [&](const NamedDecl *UD) { AddResultDecl(UD); });
-  continue;
-}
-
 // Special case: if the class name is selected, also map Objective-C
 // categories and category implementations back to their class interface.
 //
@@ -1144,17 +1132,6 @@
 DeclRelation::TemplatePattern | DeclRelation::Alias;
 std::vector Decls =
 getDeclAtPosition(AST, *CurLoc, Relations);
-std::vector NonrenamingAliasUnderlyingDecls;
-// If the results include a *non-renaming* alias, get its
-// underlying decls as well. (See similar logic in locateASTReferent()).
-for (const NamedDecl *D : Decls) {
-  if (llvm::isa(D) || llvm::isa(D)) {
-for (const NamedDecl *AD :
- getDeclAtPosition(AST, *CurLoc, DeclRelation::Underlying))
-  NonrenamingAliasUnderlyingDecls.push_back(AD);
-  }
-}
-llvm::copy(NonrenamingAliasUnderlyingDecls, std::back_inserter(Decls));
 
 // We traverse the AST to find references in the main file.
 auto MainFileRefs = findRefs(Decls, AST);
Index: clang-tools-extra/clangd/FindTarget.h
===
--- clang-tools-extra/clangd/FindTarget.h
+++ clang-tools-extra/clangd/FindTarget.h
@@ -102,13 +102,20 @@
   TemplatePattern,
 
   // Alias options apply when the declaration is an alias.
-  // e.g. namespace clang { [[StringRef]] S; }
+  // e.g. namespace client { [[X]] x; }
 
   /// This declaration is an alias that was referred to.
-  /// e.g. using llvm::StringRef (the UsingDecl 

[PATCH] D88469: [clangd] Heuristic resolution for dependent type and template names

2020-09-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/FindTarget.cpp:128
 const auto ValueFilter = [](const NamedDecl *D) { return isa(D); };
+const auto TypeFilter = [](const NamedDecl *D) { return !isa(D); };
 

nridge wrote:
> hokein wrote:
> > why not using `isa(D)`?
> Heh. When I wrote this, I searched for `TypeDecl` via `workspaceSymbols`, did 
> not see it in the first few results, and concluded that there is no such type.
> 
> Now I see it is there, just further down (and below **partial** matches like 
> `CFConstantStringTypeDecl`). Maybe I should file a `workspaceSymbols` bug 
> about this :)
yeah, I reproduced that, I think it is probably a ranking bug -- but if you 
type `clang::TypeDecl`, you will get it from the first result. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88469

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


[PATCH] D88472: [WIP][clangd] Support non-renaming alias underlying decls in TargetDecl.

2020-09-29 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/FindTarget.h:112
+  /// Underlying declarations for renaming alias (typedef decl, type alias 
decl)
+  AliasUnderlying,
+  /// Underlying declarations for non-renaming alias, decltype, etc.

The previous `Alias` vs `Underlying` were pretty nice, but they were not enough 
to support our non-renaming-alias-underlying case. Looking for the feedback on 
the API change here.  



Comment at: clang-tools-extra/clangd/unittests/XRefsTests.cpp:1120
   namespace ns { class [[Foo]] {}; }
-  using ns::F^oo;
+  using ns::[[F^oo]];
 )cpp",

this seems a small regression, I think it is fine.



Comment at: clang-tools-extra/clangd/unittests/XRefsTests.cpp:1130
   namespace ns { int [[x]](char); int x(double); }
-  using ns::x;
+  using ns::[[x]];
   int y = ^x('a');

I think it is an improvement.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88472

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


[PATCH] D88472: [WIP][clangd] Support non-renaming alias underlying decls in TargetDecl.

2020-09-29 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
Herald added subscribers: cfe-commits, usaxena95, kadircet, arphaman.
Herald added a project: clang.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

Extend the TargetDecl API to fix the workaround in 
https://reviews.llvm.org/D87225 and
https://reviews.llvm.org/D74054.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D88472

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/FindTarget.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.cpp
  clang-tools-extra/clangd/unittests/XRefsTests.cpp

Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp
===
--- clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -1090,7 +1090,6 @@
   R"cpp(
   template  struct function {};
   template  using [[callback]] = function;
-
   c^allback foo;
 )cpp",
 
@@ -1118,17 +1117,17 @@
   // decls.
   R"cpp(
   namespace ns { class [[Foo]] {}; }
-  using ns::F^oo;
+  using ns::[[F^oo]];
 )cpp",
 
   R"cpp(
   namespace ns { int [[x]](char); int [[x]](double); }
-  using ns::^x;
+  using ns::[[^x]];
 )cpp",
 
   R"cpp(
   namespace ns { int [[x]](char); int x(double); }
-  using ns::x;
+  using ns::[[x]];
   int y = ^x('a');
 )cpp",
 
@@ -1156,7 +1155,7 @@
   };
   template 
   struct Derived : Base {
-using Base::w^aldo;
+using Base::[[w^aldo]];
   };
 )cpp",
   };
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -182,7 +182,7 @@
   )cpp";
   // f(char) is not referenced!
   EXPECT_DECLS("DeclRefExpr", {"using foo::f", Rel::Alias},
-   {"int f(int)", Rel::Underlying});
+   {"int f(int)", Rel::NonAliasUnderlying});
 
   Code = R"cpp(
 namespace foo {
@@ -193,8 +193,8 @@
   )cpp";
   // All overloads are referenced.
   EXPECT_DECLS("UsingDecl", {"using foo::f", Rel::Alias},
-   {"int f(int)", Rel::Underlying},
-   {"int f(char)", Rel::Underlying});
+   {"int f(int)", Rel::NonAliasUnderlying},
+   {"int f(char)", Rel::NonAliasUnderlying});
 
   Code = R"cpp(
 struct X {
@@ -206,7 +206,7 @@
 int x = Y().[[foo]]();
   )cpp";
   EXPECT_DECLS("MemberExpr", {"using X::foo", Rel::Alias},
-   {"int foo()", Rel::Underlying});
+   {"int foo()", Rel::NonAliasUnderlying});
 
   Code = R"cpp(
   template 
@@ -219,7 +219,7 @@
   };
 )cpp";
   EXPECT_DECLS("UnresolvedUsingValueDecl", {"using Base::waldo", Rel::Alias},
-   {"void waldo()", Rel::Underlying});
+   {"void waldo()", Rel::NonAliasUnderlying});
 }
 
 TEST_F(TargetDeclTest, ConstructorInitList) {
@@ -275,7 +275,7 @@
 int y = [[b]]::x;
   )cpp";
   EXPECT_DECLS("NestedNameSpecifierLoc", {"namespace b = a", Rel::Alias},
-   {"namespace a", Rel::Underlying});
+   {"namespace a", Rel::AliasUnderlying});
 }
 
 TEST_F(TargetDeclTest, Types) {
@@ -291,14 +291,14 @@
 [[X]] x;
   )cpp";
   EXPECT_DECLS("TypedefTypeLoc", {"typedef S X", Rel::Alias},
-   {"struct S", Rel::Underlying});
+   {"struct S", Rel::AliasUnderlying});
   Code = R"cpp(
 namespace ns { struct S{}; }
 typedef ns::S X;
 [[X]] x;
   )cpp";
   EXPECT_DECLS("TypedefTypeLoc", {"typedef ns::S X", Rel::Alias},
-   {"struct S", Rel::Underlying});
+   {"struct S", Rel::AliasUnderlying});
 
   // FIXME: Auto-completion in a template requires disabling delayed template
   // parsing.
@@ -325,7 +325,7 @@
 S X;
 [[decltype]](X) Y;
   )cpp";
-  EXPECT_DECLS("DecltypeTypeLoc", {"struct S", Rel::Underlying});
+  EXPECT_DECLS("DecltypeTypeLoc", {"struct S", Rel::NonAliasUnderlying});
 
   Code = R"cpp(
 struct S{};
@@ -534,8 +534,9 @@
   )cpp";
   EXPECT_DECLS("TemplateSpecializationTypeLoc",
{"template<> class SmallVector",
-Rel::TemplateInstantiation | Rel::Underlying},
-   {"class SmallVector", Rel::TemplatePattern | Rel::Underlying},
+Rel::TemplateInstantiation | DeclRelation::AliasUnderlying},
+   {"class SmallVector",
+Rel::TemplatePattern | DeclRelation::AliasUnderlying},
{"using TinyVector = SmallVector",
 Rel::Alias | Rel::TemplatePattern});
 }
Index: clang-tools-extra/clangd/XRefs.cpp
===
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -314,8 +314,9 @@
   };
 
   // Emit all symbol 

[PATCH] D88469: [clangd] Heuristic resolution for dependent type and template names

2020-09-29 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/FindTarget.cpp:128
 const auto ValueFilter = [](const NamedDecl *D) { return isa(D); };
+const auto TypeFilter = [](const NamedDecl *D) { return !isa(D); };
 

why not using `isa(D)`?



Comment at: clang-tools-extra/clangd/unittests/FindTargetTests.cpp:743
+template 
+void foo(typename A::[[B]]);
+  )cpp";

can you try to add a nested struct C in B, and verify `typename 
A::B::[[C]])` still works?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88469

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


  1   2   3   4   5   6   7   8   9   10   >