[clang-tools-extra] 6b2fed3 - [clangd] Upgrade vlog() to log() for preamble build stats

2022-08-01 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2022-08-01T15:08:21+02:00
New Revision: 6b2fed3ab4193cfb50c4e60fb4cd19c7e6b3603f

URL: 
https://github.com/llvm/llvm-project/commit/6b2fed3ab4193cfb50c4e60fb4cd19c7e6b3603f
DIFF: 
https://github.com/llvm/llvm-project/commit/6b2fed3ab4193cfb50c4e60fb4cd19c7e6b3603f.diff

LOG: [clangd] Upgrade vlog() to log() for preamble build stats

This is very useful information for better understanding performance and
preamble builds don't happen that often, so it's not that spammy.

Differential Revision: https://reviews.llvm.org/D130636

Added: 


Modified: 
clang-tools-extra/clangd/Preamble.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/Preamble.cpp 
b/clang-tools-extra/clangd/Preamble.cpp
index 9fc249afcc224..337f71bed9bae 100644
--- a/clang-tools-extra/clangd/Preamble.cpp
+++ b/clang-tools-extra/clangd/Preamble.cpp
@@ -552,7 +552,7 @@ buildPreamble(PathRef FileName, CompilerInvocation CI,
   }
 
   if (BuiltPreamble) {
-vlog("Built preamble of size {0} for file {1} version {2} in {3} seconds",
+log("Built preamble of size {0} for file {1} version {2} in {3} seconds",
  BuiltPreamble->getSize(), FileName, Inputs.Version,
  PreambleTimer.getTime());
 std::vector Diags = PreambleDiagnostics.take();



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


[clang] cab3cfd - [clang] Do not crash on "requires" after a fatal error occurred.

2022-07-14 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2022-07-14T15:45:32+02:00
New Revision: cab3cfd013cf92c441c3acbfcc1844b267ab8659

URL: 
https://github.com/llvm/llvm-project/commit/cab3cfd013cf92c441c3acbfcc1844b267ab8659
DIFF: 
https://github.com/llvm/llvm-project/commit/cab3cfd013cf92c441c3acbfcc1844b267ab8659.diff

LOG: [clang] Do not crash on "requires" after a fatal error occurred.

The code would assume that SubstExpr() cannot fail on concept
specialization. This is incorret - we give up on some things after fatal
error occurred, since there's no value in doing futher work that the
user will not see anyway. In this case, this lead to crash.

The fatal error is simulated in tests with -ferror-limit=1, but this
could happen in other cases too.

Fixes https://github.com/llvm/llvm-project/issues/55401

Differential Revision: https://reviews.llvm.org/D129499

Added: 
clang/test/SemaCXX/concept-fatal-error.cpp

Modified: 
clang/lib/Sema/SemaExprCXX.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 11f33c7c63633..5331193de863d 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -9006,14 +9006,14 @@ Sema::BuildExprRequirement(
 cast(TPL->getParam(0))->getTypeConstraint()
 ->getImmediatelyDeclaredConstraint();
 ExprResult Constraint = SubstExpr(IDC, MLTAL);
-assert(!Constraint.isInvalid() &&
-   "Substitution cannot fail as it is simply putting a type template "
-   "argument into a concept specialization expression's parameter.");
-
-SubstitutedConstraintExpr =
-cast(Constraint.get());
-if (!SubstitutedConstraintExpr->isSatisfied())
-  Status = concepts::ExprRequirement::SS_ConstraintsNotSatisfied;
+if (Constraint.isInvalid()) {
+  Status = concepts::ExprRequirement::SS_ExprSubstitutionFailure;
+} else {
+  SubstitutedConstraintExpr =
+  cast(Constraint.get());
+  if (!SubstitutedConstraintExpr->isSatisfied())
+Status = concepts::ExprRequirement::SS_ConstraintsNotSatisfied;
+}
   }
   return new (Context) concepts::ExprRequirement(E, IsSimple, NoexceptLoc,
  ReturnTypeRequirement, Status,

diff  --git a/clang/test/SemaCXX/concept-fatal-error.cpp 
b/clang/test/SemaCXX/concept-fatal-error.cpp
new file mode 100644
index 0..c299b39fdeb23
--- /dev/null
+++ b/clang/test/SemaCXX/concept-fatal-error.cpp
@@ -0,0 +1,10 @@
+// RUN: not %clang_cc1 -fsyntax-only -std=c++20 -ferror-limit 1 -verify %s
+
+template 
+concept f = requires { 42; };
+struct h {
+  // The missing semicolon will trigger an error and -ferror-limit=1 will make 
it fatal
+  // We test that we do not crash in such cases (#55401)
+  int i = requires { { i } f } // expected-error {{expected ';' at end of 
declaration list}}
+   // expected-error@* {{too many errros emitted}}
+};



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


[clang-tools-extra] ad46aae - [clangd] Add beforeExecute() callback to FeatureModules.

2022-04-21 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2022-04-21T18:03:39+02:00
New Revision: ad46aaede6e4d5a6951fc9827da994d3fbe1af44

URL: 
https://github.com/llvm/llvm-project/commit/ad46aaede6e4d5a6951fc9827da994d3fbe1af44
DIFF: 
https://github.com/llvm/llvm-project/commit/ad46aaede6e4d5a6951fc9827da994d3fbe1af44.diff

LOG: [clangd] Add beforeExecute() callback to FeatureModules.

It runs immediatelly before FrontendAction::Execute() with a mutable
CompilerInstance, allowing FeatureModules to register callbacks, remap
files, etc.

Differential Revision: https://reviews.llvm.org/D124176

Added: 


Modified: 
clang-tools-extra/clangd/FeatureModule.h
clang-tools-extra/clangd/ParsedAST.cpp
clang-tools-extra/clangd/Preamble.cpp
clang-tools-extra/clangd/unittests/FeatureModulesTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/FeatureModule.h 
b/clang-tools-extra/clangd/FeatureModule.h
index 8f07b18412671..43007a297469b 100644
--- a/clang-tools-extra/clangd/FeatureModule.h
+++ b/clang-tools-extra/clangd/FeatureModule.h
@@ -20,6 +20,7 @@
 #include 
 
 namespace clang {
+class CompilerInstance;
 namespace clangd {
 struct Diag;
 class LSPBinder;
@@ -105,6 +106,11 @@ class FeatureModule {
 /// Listeners are destroyed once the AST is built.
 virtual ~ASTListener() = default;
 
+/// Called before every AST build, both for main file and preamble. The 
call
+/// happens immediately before FrontendAction::Execute(), with Preprocessor
+/// set up already and after BeginSourceFile() on main file was called.
+virtual void beforeExecute(CompilerInstance &CI) {}
+
 /// Called everytime a diagnostic is encountered. Modules can use this
 /// modify the final diagnostic, or store some information to surface code
 /// actions later on.

diff  --git a/clang-tools-extra/clangd/ParsedAST.cpp 
b/clang-tools-extra/clangd/ParsedAST.cpp
index ef744d1f893b0..235362b5d599c 100644
--- a/clang-tools-extra/clangd/ParsedAST.cpp
+++ b/clang-tools-extra/clangd/ParsedAST.cpp
@@ -550,6 +550,12 @@ ParsedAST::build(llvm::StringRef Filename, const 
ParseInputs &Inputs,
   // Collect tokens of the main file.
   syntax::TokenCollector CollectTokens(Clang->getPreprocessor());
 
+  // To remain consistent with preamble builds, these callbacks must be called
+  // exactly here, after preprocessor is initialized and BeginSourceFile() was
+  // called already.
+  for (const auto &L : ASTListeners)
+L->beforeExecute(*Clang);
+
   if (llvm::Error Err = Action->Execute())
 log("Execute() failed when building AST for {0}: {1}", MainInput.getFile(),
 toString(std::move(Err)));

diff  --git a/clang-tools-extra/clangd/Preamble.cpp 
b/clang-tools-extra/clangd/Preamble.cpp
index 0cc5b65a94d64..5ecd6f3a0bdf1 100644
--- a/clang-tools-extra/clangd/Preamble.cpp
+++ b/clang-tools-extra/clangd/Preamble.cpp
@@ -64,9 +64,12 @@ bool compileCommandsAreEqual(const tooling::CompileCommand 
&LHS,
 
 class CppFilePreambleCallbacks : public PreambleCallbacks {
 public:
-  CppFilePreambleCallbacks(PathRef File, PreambleParsedCallback ParsedCallback,
-   PreambleBuildStats *Stats)
-  : File(File), ParsedCallback(ParsedCallback), Stats(Stats) {}
+  CppFilePreambleCallbacks(
+  PathRef File, PreambleParsedCallback ParsedCallback,
+  PreambleBuildStats *Stats,
+  std::function BeforeExecuteCallback)
+  : File(File), ParsedCallback(ParsedCallback), Stats(Stats),
+BeforeExecuteCallback(std::move(BeforeExecuteCallback)) {}
 
   IncludeStructure takeIncludes() { return std::move(Includes); }
 
@@ -115,6 +118,8 @@ class CppFilePreambleCallbacks : public PreambleCallbacks {
 LangOpts = &CI.getLangOpts();
 SourceMgr = &CI.getSourceManager();
 Includes.collect(CI);
+if (BeforeExecuteCallback)
+  BeforeExecuteCallback(CI);
   }
 
   std::unique_ptr createPPCallbacks() override {
@@ -156,6 +161,7 @@ class CppFilePreambleCallbacks : public PreambleCallbacks {
   const clang::LangOptions *LangOpts = nullptr;
   const SourceManager *SourceMgr = nullptr;
   PreambleBuildStats *Stats;
+  std::function BeforeExecuteCallback;
 };
 
 // Represents directives other than includes, where basic textual information 
is
@@ -477,7 +483,11 @@ buildPreamble(PathRef FileName, CompilerInvocation CI,
   // to read back. We rely on dynamic index for the comments instead.
   CI.getPreprocessorOpts().WriteCommentListToPCH = false;
 
-  CppFilePreambleCallbacks CapturedInfo(FileName, PreambleCallback, Stats);
+  CppFilePreambleCallbacks CapturedInfo(FileName, PreambleCallback, Stats,
+[&ASTListeners](CompilerInstance &CI) {
+  for (const auto &L : ASTListeners)
+L->beforeExecute(CI);
+});
   auto VFS = Inputs.TFS->view(Inputs.CompileCom

[clang] 7e45912 - [clang] Do not crash on arrow operator on dependent type.

2022-03-25 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2022-03-25T15:48:08+01:00
New Revision: 7e459126185f4d5115e6e2166a866aba1369d024

URL: 
https://github.com/llvm/llvm-project/commit/7e459126185f4d5115e6e2166a866aba1369d024
DIFF: 
https://github.com/llvm/llvm-project/commit/7e459126185f4d5115e6e2166a866aba1369d024.diff

LOG: [clang] Do not crash on arrow operator on dependent type.

There seems to be more than one way to get to that state. I included to
example cases in the test, both were noticed recently.

There is room for improvement, for example by creating RecoveryExpr in
place of the bad initializer, but for now let's stop the crashes.

Differential Revision: https://reviews.llvm.org/D121824

Added: 


Modified: 
clang/lib/Sema/TreeTransform.h
clang/test/SemaCXX/arrow-operator.cpp

Removed: 




diff  --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index fb830ef2a118a..1ee457b0566ae 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -14757,6 +14757,10 @@ 
TreeTransform::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
   return getSema().CreateBuiltinArraySubscriptExpr(
   First, Callee->getBeginLoc(), Second, OpLoc);
   } else if (Op == OO_Arrow) {
+// It is possible that the type refers to a RecoveryExpr created earlier
+// in the tree transformation.
+if (First->getType()->isDependentType())
+  return ExprError();
 // -> is never a builtin operation.
 return SemaRef.BuildOverloadedArrowExpr(nullptr, First, OpLoc);
   } else if (Second == nullptr || isPostIncDec) {

diff  --git a/clang/test/SemaCXX/arrow-operator.cpp 
b/clang/test/SemaCXX/arrow-operator.cpp
index 3e32a6ba33eb2..c6d2a99251be4 100644
--- a/clang/test/SemaCXX/arrow-operator.cpp
+++ b/clang/test/SemaCXX/arrow-operator.cpp
@@ -65,3 +65,51 @@ void test() {
 }
 
 } // namespace arrow_suggest
+
+namespace no_crash_dependent_type {
+
+template 
+struct A {
+  void call();
+  A *operator->();
+};
+
+template 
+void foo() {
+  // The "requires an initializer" error seems unnecessary.
+  A &x = blah[7]; // expected-error {{use of undeclared identifier 
'blah'}} \
+// expected-error {{requires an initializer}}
+  // x is dependent.
+  x->call();
+}
+
+void test() {
+  foo(); // expected-note {{requested here}}
+}
+
+} // namespace no_crash_dependent_type
+
+namespace clangd_issue_1073_no_crash_dependent_type {
+
+template  struct Ptr {
+  T *operator->();
+};
+
+struct Struct {
+  int len;
+};
+
+template 
+struct TemplateStruct {
+  Ptr val(); // expected-note {{declared here}}
+};
+
+template 
+void templateFunc(const TemplateStruct &ts) {
+  Ptr ptr = ts.val(); // expected-error {{function is not marked 
const}}
+  auto foo = ptr->len;
+}
+
+template void templateFunc<0>(const TemplateStruct<0> &); // expected-note 
{{requested here}}
+
+} // namespace clangd_issue_1073_no_crash_dependent_type



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


[clang-tools-extra] 6009d0d - [clangd] Track time spent in filesystem ops during preamble builds

2022-03-21 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2022-03-21T18:33:01+01:00
New Revision: 6009d0d5801d8f4ff45b425f3fe3792e93aec553

URL: 
https://github.com/llvm/llvm-project/commit/6009d0d5801d8f4ff45b425f3fe3792e93aec553
DIFF: 
https://github.com/llvm/llvm-project/commit/6009d0d5801d8f4ff45b425f3fe3792e93aec553.diff

LOG: [clangd] Track time spent in filesystem ops during preamble builds

In some deployments, for example when running on FUSE or using some
network-based VFS implementation, the filesystem operations might add up
to a significant fraction of preamble build time. This change allows us
to track time spent in FS operations to better understand the problem.

Differential Revision: https://reviews.llvm.org/D121712

Added: 


Modified: 
clang-tools-extra/clangd/Preamble.cpp
clang-tools-extra/clangd/Preamble.h
clang-tools-extra/clangd/TUScheduler.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/Preamble.cpp 
b/clang-tools-extra/clangd/Preamble.cpp
index ea518f099689e..aab6dc78092f7 100644
--- a/clang-tools-extra/clangd/Preamble.cpp
+++ b/clang-tools-extra/clangd/Preamble.cpp
@@ -312,12 +312,98 @@ bool isMainFile(llvm::StringRef FileName, const 
SourceManager &SM) {
   return FE && *FE == SM.getFileEntryForID(SM.getMainFileID());
 }
 
+// Accumulating wall time timer. Similar to llvm::Timer, but much cheaper,
+// it only tracks wall time.
+// Since this is a generic timer, We may want to move this to support/ if we
+// find a use case outside of FS time tracking.
+class WallTimer {
+public:
+  WallTimer() : TotalTime(std::chrono::steady_clock::duration::zero()) {}
+  // [Re-]Start the timer.
+  void startTimer() { StartTime = std::chrono::steady_clock::now(); }
+  // Stop the timer and update total time.
+  void stopTimer() {
+TotalTime += std::chrono::steady_clock::now() - StartTime;
+  }
+  // Return total time, in seconds.
+  double getTime() { return std::chrono::duration(TotalTime).count(); }
+
+private:
+  std::chrono::steady_clock::duration TotalTime;
+  std::chrono::steady_clock::time_point StartTime;
+};
+
+class WallTimerRegion {
+public:
+  WallTimerRegion(WallTimer &T) : T(T) { T.startTimer(); }
+  ~WallTimerRegion() { T.stopTimer(); }
+
+private:
+  WallTimer &T;
+};
+
+// Used by TimerFS, tracks time spent in status() and getBuffer() calls while
+// proxying to underlying File implementation.
+class TimerFile : public llvm::vfs::File {
+public:
+  TimerFile(WallTimer &Timer, std::unique_ptr InnerFile)
+  : Timer(Timer), InnerFile(std::move(InnerFile)) {}
+
+  llvm::ErrorOr status() override {
+WallTimerRegion T(Timer);
+return InnerFile->status();
+  }
+  llvm::ErrorOr>
+  getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
+bool IsVolatile) override {
+WallTimerRegion T(Timer);
+return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
+IsVolatile);
+  }
+  std::error_code close() override {
+WallTimerRegion T(Timer);
+return InnerFile->close();
+  }
+
+private:
+  WallTimer &Timer;
+  std::unique_ptr InnerFile;
+};
+
+// A wrapper for FileSystems that tracks the amount of time spent in status()
+// and openFileForRead() calls.
+class TimerFS : public llvm::vfs::ProxyFileSystem {
+public:
+  TimerFS(llvm::IntrusiveRefCntPtr FS)
+  : ProxyFileSystem(std::move(FS)) {}
+
+  llvm::ErrorOr>
+  openFileForRead(const llvm::Twine &Path) override {
+WallTimerRegion T(Timer);
+auto FileOr = getUnderlyingFS().openFileForRead(Path);
+if (!FileOr)
+  return FileOr;
+return std::make_unique(Timer, std::move(FileOr.get()));
+  }
+
+  llvm::ErrorOr status(const llvm::Twine &Path) override {
+WallTimerRegion T(Timer);
+return getUnderlyingFS().status(Path);
+  }
+
+  double getTime() { return Timer.getTime(); }
+
+private:
+  WallTimer Timer;
+};
+
 } // namespace
 
 std::shared_ptr
 buildPreamble(PathRef FileName, CompilerInvocation CI,
   const ParseInputs &Inputs, bool StoreInMemory,
-  PreambleParsedCallback PreambleCallback) {
+  PreambleParsedCallback PreambleCallback,
+  PreambleBuildStats *Stats) {
   // Note that we don't need to copy the input contents, preamble can live
   // without those.
   auto ContentsBuffer =
@@ -375,18 +461,25 @@ buildPreamble(PathRef FileName, CompilerInvocation CI,
   llvm::SmallString<32> AbsFileName(FileName);
   VFS->makeAbsolute(AbsFileName);
   auto StatCache = std::make_unique(AbsFileName);
+  auto StatCacheFS = StatCache->getProducingFS(VFS);
+  llvm::IntrusiveRefCntPtr TimedFS(new TimerFS(StatCacheFS));
+
+  WallTimer PreambleTimer;
+  PreambleTimer.startTimer();
   auto BuiltPreamble = PrecompiledPreamble::Build(
   CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine,
-  StatCache->getProducingFS(VFS),
-  std::make_shared(), StoreInMemory, CapturedInfo);
+  St

[clang] 8f4ea36 - [clang] Improve laziness of resolving module map headers.

2022-03-01 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2022-03-01T15:56:23+01:00
New Revision: 8f4ea36bfe4caf7d08f9778ee2a347b78f02bc0f

URL: 
https://github.com/llvm/llvm-project/commit/8f4ea36bfe4caf7d08f9778ee2a347b78f02bc0f
DIFF: 
https://github.com/llvm/llvm-project/commit/8f4ea36bfe4caf7d08f9778ee2a347b78f02bc0f.diff

LOG: [clang] Improve laziness of resolving module map headers.

clang has support for lazy headers in module maps - if size and/or
modtime and provided in the cppmap file, headers are only resolved when
an include directive for a file with that size/modtime is encoutered.

Before this change, the lazy resolution was all-or-nothing per module.
That means as soon as even one file in that module potentially matched
an include, all lazy files in that module were resolved. With this
change, only files with matching size/modtime will be resolved.

The goal is to avoid unnecessary stat() calls on non-included files,
which is especially valuable on networked file systems, with higher
latency.

Differential Revision: https://reviews.llvm.org/D120569

Added: 


Modified: 
clang/include/clang/Lex/ModuleMap.h
clang/lib/Frontend/FrontendAction.cpp
clang/lib/Lex/ModuleMap.cpp
clang/lib/Serialization/ASTWriter.cpp

Removed: 




diff  --git a/clang/include/clang/Lex/ModuleMap.h 
b/clang/include/clang/Lex/ModuleMap.h
index 26169ae9cee95..538dcc7c4bec1 100644
--- a/clang/include/clang/Lex/ModuleMap.h
+++ b/clang/include/clang/Lex/ModuleMap.h
@@ -456,8 +456,11 @@ class ModuleMap {
   /// is effectively internal, but is exposed so HeaderSearch can call it.
   void resolveHeaderDirectives(const FileEntry *File) const;
 
-  /// Resolve all lazy header directives for the specified module.
-  void resolveHeaderDirectives(Module *Mod) const;
+  /// Resolve lazy header directives for the specified module. If File is
+  /// provided, only headers with same size and modtime are resolved. If File
+  /// is not set, all headers are resolved.
+  void resolveHeaderDirectives(Module *Mod,
+   llvm::Optional File) const;
 
   /// Reports errors if a module must not include a specific file.
   ///

diff  --git a/clang/lib/Frontend/FrontendAction.cpp 
b/clang/lib/Frontend/FrontendAction.cpp
index c5b9e80356db4..b8f92381613a3 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -331,7 +331,7 @@ static std::error_code collectModuleHeaderIncludes(
 return std::error_code();
 
   // Resolve all lazy header directives to header files.
-  ModMap.resolveHeaderDirectives(Module);
+  ModMap.resolveHeaderDirectives(Module, /*File=*/llvm::None);
 
   // If any headers are missing, we can't build this module. In most cases,
   // diagnostics for this should have already been produced; we only get here

diff  --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index 0b136aeb580fe..824b2bb192909 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -482,7 +482,7 @@ void ModuleMap::diagnoseHeaderInclusion(Module 
*RequestingModule,
 
   if (RequestingModule) {
 resolveUses(RequestingModule, /*Complain=*/false);
-resolveHeaderDirectives(RequestingModule);
+resolveHeaderDirectives(RequestingModule, /*File=*/llvm::None);
   }
 
   bool Excluded = false;
@@ -1191,25 +1191,35 @@ void ModuleMap::resolveHeaderDirectives(const FileEntry 
*File) const {
   auto BySize = LazyHeadersBySize.find(File->getSize());
   if (BySize != LazyHeadersBySize.end()) {
 for (auto *M : BySize->second)
-  resolveHeaderDirectives(M);
+  resolveHeaderDirectives(M, File);
 LazyHeadersBySize.erase(BySize);
   }
 
   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
   if (ByModTime != LazyHeadersByModTime.end()) {
 for (auto *M : ByModTime->second)
-  resolveHeaderDirectives(M);
+  resolveHeaderDirectives(M, File);
 LazyHeadersByModTime.erase(ByModTime);
   }
 }
 
-void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
+void ModuleMap::resolveHeaderDirectives(
+Module *Mod, llvm::Optional File) const {
   bool NeedsFramework = false;
-  for (auto &Header : Mod->UnresolvedHeaders)
-// This operation is logically const; we're just changing how we represent
-// the header information for this file.
-const_cast(this)->resolveHeader(Mod, Header, NeedsFramework);
-  Mod->UnresolvedHeaders.clear();
+  SmallVector NewHeaders;
+  const auto Size = File ? File.getValue()->getSize() : 0;
+  const auto ModTime = File ? File.getValue()->getModificationTime() : 0;
+
+  for (auto &Header : Mod->UnresolvedHeaders) {
+if (File && ((Header.ModTime && Header.ModTime != ModTime) ||
+ (Header.Size && Header.Size != Size)))
+  NewHeaders.push_back(Header);
+else
+  // This operation is logically const; we're just changing how we 
represent
+  // the header information for

[clang-tools-extra] 55a7931 - [clang][clangd] Improve signature help for variadic functions.

2021-11-18 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-11-18T15:50:47+01:00
New Revision: 55a79318c60d8a39329195f43bf43b89da9a638e

URL: 
https://github.com/llvm/llvm-project/commit/55a79318c60d8a39329195f43bf43b89da9a638e
DIFF: 
https://github.com/llvm/llvm-project/commit/55a79318c60d8a39329195f43bf43b89da9a638e.diff

LOG: [clang][clangd] Improve signature help for variadic functions.

This covers both C-style variadic functions and template variadic w/
parameter packs.

Previously we would return no signatures when working with template
variadic functions once activeParameter reached the position of the
parameter pack (except when it was the only param, then we'd still
show it when no arguments were given). With this commit, we now show
signathure help correctly.

Additionally, this commit fixes the activeParameter value in LSP output
of clangd in the presence of variadic functions (both kinds). LSP does
not allow the activeParamter to be higher than the number of parameters
in the active signature. With "..." or parameter pack being just one
argument, for all but first argument passed to "..." we'd report
incorrect activeParameter value. Clients such as VSCode would then treat
it as 0, as suggested in the spec) and highlight the wrong parameter.

In the future, we should add support for per-signature activeParamter
value, which exists in LSP since 3.16.0. This is not part of this
commit.

Differential Revision: https://reviews.llvm.org/D111318

Added: 
clang/test/CodeCompletion/variadic-template.cpp

Modified: 
clang-tools-extra/clangd/CodeComplete.cpp
clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
clang/include/clang/Sema/Overload.h
clang/lib/Sema/SemaCodeComplete.cpp
clang/lib/Sema/SemaOverload.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/CodeComplete.cpp 
b/clang-tools-extra/clangd/CodeComplete.cpp
index f033b5ec001d8..ac6c3b077d472 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -872,6 +872,28 @@ struct ScoredSignature {
   SignatureQualitySignals Quality;
 };
 
+// Returns the index of the parameter matching argument number "Arg.
+// This is usually just "Arg", except for variadic functions/templates, where
+// "Arg" might be higher than the number of parameters. When that happens, we
+// assume the last parameter is variadic and assume all further args are
+// part of it.
+int paramIndexForArg(const CodeCompleteConsumer::OverloadCandidate &Candidate,
+ int Arg) {
+  int NumParams = 0;
+  if (const auto *F = Candidate.getFunction()) {
+NumParams = F->getNumParams();
+if (F->isVariadic())
+  ++NumParams;
+  } else if (auto *T = Candidate.getFunctionType()) {
+if (auto *Proto = T->getAs()) {
+  NumParams = Proto->getNumParams();
+  if (Proto->isVariadic())
+++NumParams;
+}
+  }
+  return std::min(Arg, std::max(NumParams - 1, 0));
+}
+
 class SignatureHelpCollector final : public CodeCompleteConsumer {
 public:
   SignatureHelpCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,
@@ -902,7 +924,9 @@ class SignatureHelpCollector final : public 
CodeCompleteConsumer {
 SigHelp.activeSignature = 0;
 assert(CurrentArg <= (unsigned)std::numeric_limits::max() &&
"too many arguments");
+
 SigHelp.activeParameter = static_cast(CurrentArg);
+
 for (unsigned I = 0; I < NumCandidates; ++I) {
   OverloadCandidate Candidate = Candidates[I];
   // We want to avoid showing instantiated signatures, because they may be
@@ -912,6 +936,14 @@ class SignatureHelpCollector final : public 
CodeCompleteConsumer {
 if (auto *Pattern = Func->getTemplateInstantiationPattern())
   Candidate = OverloadCandidate(Pattern);
   }
+  if (static_cast(I) == SigHelp.activeSignature) {
+// The activeParameter in LSP relates to the activeSignature. There is
+// another, per-signature field, but we currently do not use it and not
+// all clients might support it.
+// FIXME: Add support for per-signature activeParameter field.
+SigHelp.activeParameter =
+paramIndexForArg(Candidate, SigHelp.activeParameter);
+  }
 
   const auto *CCS = Candidate.CreateSignatureString(
   CurrentArg, S, *Allocator, CCTUInfo, true);

diff  --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp 
b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index 81dfdcb371fb4..5612a0b17fbba 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -2622,6 +2622,104 @@ TEST(SignatureHelpTest, ConstructorInitializeFields) {
   }
 }
 
+TEST(SignatureHelpTest, Variadic) {
+  const std::string Header = R"cpp(
+void fun(int x, ...) {}
+void test() {)cpp";
+  const std::string ExpectedSig = "fun([[int x]], [[...]]) -> vo

[clang] 6d09aae - Revert "[clang] Add early exit when checking for const init of arrays."

2021-11-10 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-11-10T20:59:35+01:00
New Revision: 6d09aaecdfe51e13fc64d539aa7c9a790de341d7

URL: 
https://github.com/llvm/llvm-project/commit/6d09aaecdfe51e13fc64d539aa7c9a790de341d7
DIFF: 
https://github.com/llvm/llvm-project/commit/6d09aaecdfe51e13fc64d539aa7c9a790de341d7.diff

LOG: Revert "[clang] Add early exit when checking for const init of arrays."

This reverts commit 48bb5f4cbe8d5951c1153e469dc6713a122b7fa3.

Several breakages, including ARM (fixed later, but not sufficient) and
MSan (to be diagnosed later).

Differential Revision: https://reviews.llvm.org/D113599

Added: 


Modified: 
clang/lib/AST/ExprConstant.cpp

Removed: 
clang/test/SemaCXX/PR51712-large-array-constexpr-check-oom.cpp



diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index a6da3d3fbea2d..fe96db9ca918e 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -10596,55 +10596,28 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const 
CXXConstructExpr *E,
   bool HadZeroInit = Value->hasValue();
 
   if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(Type)) {
-unsigned FinalSize = CAT->getSize().getZExtValue();
+unsigned N = CAT->getSize().getZExtValue();
 
 // Preserve the array filler if we had prior zero-initialization.
 APValue Filler =
   HadZeroInit && Value->hasArrayFiller() ? Value->getArrayFiller()
  : APValue();
 
-*Value = APValue(APValue::UninitArray(), 0, FinalSize);
-if (FinalSize == 0)
-  return true;
+*Value = APValue(APValue::UninitArray(), N, N);
+
+if (HadZeroInit)
+  for (unsigned I = 0; I != N; ++I)
+Value->getArrayInitializedElt(I) = Filler;
 
+// Initialize the elements.
 LValue ArrayElt = Subobject;
 ArrayElt.addArray(Info, E, CAT);
-// We do the whole initialization in two passes, first for just one 
element,
-// then for the whole array. It's possible we may find out we can't do 
const
-// init in the first pass, in which case we avoid allocating a potentially
-// large array. We don't do more passes because expanding array requires
-// copying the data, which is wasteful.
-for (const unsigned N : {1u, FinalSize}) {
-  unsigned OldElts = Value->getArrayInitializedElts();
-  if (OldElts == N)
-break;
-
-  // Expand the array to appropriate size.
-  APValue NewValue(APValue::UninitArray(), N, FinalSize);
-  for (unsigned I = 0; I < OldElts; ++I)
-NewValue.getArrayInitializedElt(I).swap(
-Value->getArrayInitializedElt(I));
-  Value->swap(NewValue);
-
-  if (HadZeroInit)
-for (unsigned I = OldElts; I < N; ++I)
-  Value->getArrayInitializedElt(I) = Filler;
-
-  // Initialize the elements.
-  for (unsigned I = OldElts; I < N; ++I) {
-if (!VisitCXXConstructExpr(E, ArrayElt,
-   &Value->getArrayInitializedElt(I),
-   CAT->getElementType()) ||
-!HandleLValueArrayAdjustment(Info, E, ArrayElt,
- CAT->getElementType(), 1))
-  return false;
-// When checking for const initilization any diagnostic is considered
-// an error.
-if (Info.EvalStatus.Diag && !Info.EvalStatus.Diag->empty() &&
-!Info.keepEvaluatingAfterFailure())
-  return false;
-  }
-}
+for (unsigned I = 0; I != N; ++I)
+  if (!VisitCXXConstructExpr(E, ArrayElt, 
&Value->getArrayInitializedElt(I),
+ CAT->getElementType()) ||
+  !HandleLValueArrayAdjustment(Info, E, ArrayElt, 
CAT->getElementType(),
+   1))
+return false;
 
 return true;
   }

diff  --git a/clang/test/SemaCXX/PR51712-large-array-constexpr-check-oom.cpp 
b/clang/test/SemaCXX/PR51712-large-array-constexpr-check-oom.cpp
deleted file mode 100644
index 1bbc1b5c863c0..0
--- a/clang/test/SemaCXX/PR51712-large-array-constexpr-check-oom.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-// REQUIRES: shell
-// UNSUPPORTED: win32
-// RUN: ulimit -v 1048576
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -triple=x86_64 %s
-// expected-no-diagnostics
-
-// This used to require too much memory and crash with OOM.
-struct {
-  int a, b, c, d;
-} arr[1<<30];
-



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


[clang] 581a6a8 - [clang] Fix armv7-quick build by hardcoding -triple=x86_64 in OOM test.

2021-11-10 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-11-10T19:24:06+01:00
New Revision: 581a6a8118f55d2662e180880558db95f808b0dc

URL: 
https://github.com/llvm/llvm-project/commit/581a6a8118f55d2662e180880558db95f808b0dc
DIFF: 
https://github.com/llvm/llvm-project/commit/581a6a8118f55d2662e180880558db95f808b0dc.diff

LOG: [clang] Fix armv7-quick build by hardcoding -triple=x86_64 in OOM test.

The test was added in 48bb5f4cbe8d5951c1153e469dc6713a122b7fa3 and it
creates a very large array, which is too large for ARM. Making the array
smaller is not a good option, since we would need a very low ulimit and
could then hit it for other reasons.

Should fix the https://lab.llvm.org/buildbot/#/builders/171/builds/5851
failure.

Differential Revision: https://reviews.llvm.org/D113583

Added: 


Modified: 
clang/test/SemaCXX/PR51712-large-array-constexpr-check-oom.cpp

Removed: 




diff  --git a/clang/test/SemaCXX/PR51712-large-array-constexpr-check-oom.cpp 
b/clang/test/SemaCXX/PR51712-large-array-constexpr-check-oom.cpp
index 4504c0caed55..1bbc1b5c863c 100644
--- a/clang/test/SemaCXX/PR51712-large-array-constexpr-check-oom.cpp
+++ b/clang/test/SemaCXX/PR51712-large-array-constexpr-check-oom.cpp
@@ -1,7 +1,7 @@
 // REQUIRES: shell
 // UNSUPPORTED: win32
 // RUN: ulimit -v 1048576
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -triple=x86_64 %s
 // expected-no-diagnostics
 
 // This used to require too much memory and crash with OOM.



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


[clang] 48bb5f4 - [clang] Add early exit when checking for const init of arrays.

2021-11-10 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-11-10T18:11:21+01:00
New Revision: 48bb5f4cbe8d5951c1153e469dc6713a122b7fa3

URL: 
https://github.com/llvm/llvm-project/commit/48bb5f4cbe8d5951c1153e469dc6713a122b7fa3
DIFF: 
https://github.com/llvm/llvm-project/commit/48bb5f4cbe8d5951c1153e469dc6713a122b7fa3.diff

LOG: [clang] Add early exit when checking for const init of arrays.

Before this commit, on code like:

  struct S { ... };
  S arr[1000];

while checking if arr is constexpr, clang would reserve memory for
arr before running constructor for S. If S turned out to not have a
valid constexpr c-tor, clang would still try to initialize each element
(and, in case the c-tor was trivial, even skipping the constexpr step
limit), only to discard that whole APValue later, since the first
element generated a diagnostic.

With this change, we start by allocating just 1 element in the array to
try out the c-tor and take an early exit if any diagnostics are
generated, avoiding possibly large memory allocation and a lot of work
initializing to-be-discarded APValues.

Fixes 51712 and 51843.

In the future we may want to be smarter about large possibly-constexrp
arrays and maybe make the allocation lazy.

Differential Revision: https://reviews.llvm.org/D113120

Added: 
clang/test/SemaCXX/PR51712-large-array-constexpr-check-oom.cpp

Modified: 
clang/lib/AST/ExprConstant.cpp

Removed: 




diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index fa0d22064f0eb..a6da3d3fbea2d 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -10596,28 +10596,55 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const 
CXXConstructExpr *E,
   bool HadZeroInit = Value->hasValue();
 
   if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(Type)) {
-unsigned N = CAT->getSize().getZExtValue();
+unsigned FinalSize = CAT->getSize().getZExtValue();
 
 // Preserve the array filler if we had prior zero-initialization.
 APValue Filler =
   HadZeroInit && Value->hasArrayFiller() ? Value->getArrayFiller()
  : APValue();
 
-*Value = APValue(APValue::UninitArray(), N, N);
-
-if (HadZeroInit)
-  for (unsigned I = 0; I != N; ++I)
-Value->getArrayInitializedElt(I) = Filler;
+*Value = APValue(APValue::UninitArray(), 0, FinalSize);
+if (FinalSize == 0)
+  return true;
 
-// Initialize the elements.
 LValue ArrayElt = Subobject;
 ArrayElt.addArray(Info, E, CAT);
-for (unsigned I = 0; I != N; ++I)
-  if (!VisitCXXConstructExpr(E, ArrayElt, 
&Value->getArrayInitializedElt(I),
- CAT->getElementType()) ||
-  !HandleLValueArrayAdjustment(Info, E, ArrayElt,
-   CAT->getElementType(), 1))
-return false;
+// We do the whole initialization in two passes, first for just one 
element,
+// then for the whole array. It's possible we may find out we can't do 
const
+// init in the first pass, in which case we avoid allocating a potentially
+// large array. We don't do more passes because expanding array requires
+// copying the data, which is wasteful.
+for (const unsigned N : {1u, FinalSize}) {
+  unsigned OldElts = Value->getArrayInitializedElts();
+  if (OldElts == N)
+break;
+
+  // Expand the array to appropriate size.
+  APValue NewValue(APValue::UninitArray(), N, FinalSize);
+  for (unsigned I = 0; I < OldElts; ++I)
+NewValue.getArrayInitializedElt(I).swap(
+Value->getArrayInitializedElt(I));
+  Value->swap(NewValue);
+
+  if (HadZeroInit)
+for (unsigned I = OldElts; I < N; ++I)
+  Value->getArrayInitializedElt(I) = Filler;
+
+  // Initialize the elements.
+  for (unsigned I = OldElts; I < N; ++I) {
+if (!VisitCXXConstructExpr(E, ArrayElt,
+   &Value->getArrayInitializedElt(I),
+   CAT->getElementType()) ||
+!HandleLValueArrayAdjustment(Info, E, ArrayElt,
+ CAT->getElementType(), 1))
+  return false;
+// When checking for const initilization any diagnostic is considered
+// an error.
+if (Info.EvalStatus.Diag && !Info.EvalStatus.Diag->empty() &&
+!Info.keepEvaluatingAfterFailure())
+  return false;
+  }
+}
 
 return true;
   }

diff  --git a/clang/test/SemaCXX/PR51712-large-array-constexpr-check-oom.cpp 
b/clang/test/SemaCXX/PR51712-large-array-constexpr-check-oom.cpp
new file mode 100644
index 0..4504c0caed55f
--- /dev/null
+++ b/clang/test/SemaCXX/PR51712-large-array-constexpr-check-oom.cpp
@@ -0,0 +1,11 @@
+// REQUIRES: shell
+// UNSUPPORTED: win32
+// RUN: ulimit -v 1048576
+// RUN: %clang_cc1 -std=c++11 -fs

[clang] 7a2b1bd - [clang] Do not crash in APValue::prettyPrint() on forward-decl structs.

2021-11-10 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-11-10T17:17:00+01:00
New Revision: 7a2b1bdb4c8a099ebc38b7f802988244ad21fcc0

URL: 
https://github.com/llvm/llvm-project/commit/7a2b1bdb4c8a099ebc38b7f802988244ad21fcc0
DIFF: 
https://github.com/llvm/llvm-project/commit/7a2b1bdb4c8a099ebc38b7f802988244ad21fcc0.diff

LOG: [clang] Do not crash in APValue::prettyPrint() on forward-decl structs.

The call to getTypeSizeInChars() is replaced with
getTypeSizeInCharsIfKnown(), which does not crash on forward declared
structs. This only affects printing.

Differential Revision: https://reviews.llvm.org/D113570

Added: 


Modified: 
clang-tools-extra/clangd/unittests/HoverTests.cpp
clang/lib/AST/APValue.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp 
b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 2e33ce4c5d101..53df965fef2fa 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -2963,6 +2963,20 @@ TEST(Hover, SpaceshipTemplateNoCrash) {
   EXPECT_EQ(HI->Documentation, "Foo bar baz");
 }
 
+TEST(Hover, ForwardStructNoCrash) {
+  Annotations T(R"cpp(
+  struct Foo;
+  int bar;
+  auto baz = (Fo^o*)&bar;
+)cpp");
+
+  TestTU TU = TestTU::withCode(T.code());
+  auto AST = TU.build();
+  auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
+  ASSERT_TRUE(HI);
+  EXPECT_EQ(*HI->Value, "&bar");
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang

diff  --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp
index 9a9233bc1ea74..ef333c7711663 100644
--- a/clang/lib/AST/APValue.cpp
+++ b/clang/lib/AST/APValue.cpp
@@ -700,7 +700,9 @@ void APValue::printPretty(raw_ostream &Out, const 
PrintingPolicy &Policy,
 if (!hasLValuePath()) {
   // No lvalue path: just print the offset.
   CharUnits O = getLValueOffset();
-  CharUnits S = Ctx ? Ctx->getTypeSizeInChars(InnerTy) : CharUnits::Zero();
+  CharUnits S = Ctx ? Ctx->getTypeSizeInCharsIfKnown(InnerTy).getValueOr(
+  CharUnits::Zero())
+: CharUnits::Zero();
   if (!O.isZero()) {
 if (IsReference)
   Out << "*(";



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


[clang-tools-extra] 97fbc97 - [clangd] Find definition of ClassTemplate without going through index.

2021-11-04 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-11-04T15:25:21+01:00
New Revision: 97fbc975fab19be68eb6a643ddac850ef71c2ecd

URL: 
https://github.com/llvm/llvm-project/commit/97fbc975fab19be68eb6a643ddac850ef71c2ecd
DIFF: 
https://github.com/llvm/llvm-project/commit/97fbc975fab19be68eb6a643ddac850ef71c2ecd.diff

LOG: [clangd] Find definition of ClassTemplate without going through index.

I noticed that, while go-to-def works on cases like:

namespace ns {
  template struct Foo {};
}
using ::ns::Fo^o;

it only works because of the FileIndex. We can get definition location
directly from AST too.

Differential Revision: https://reviews.llvm.org/D113029

Added: 


Modified: 
clang-tools-extra/clangd/XRefs.cpp
clang-tools-extra/clangd/unittests/XRefsTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/XRefs.cpp 
b/clang-tools-extra/clangd/XRefs.cpp
index 85c6b7b771fce..b29d29e5104ee 100644
--- a/clang-tools-extra/clangd/XRefs.cpp
+++ b/clang-tools-extra/clangd/XRefs.cpp
@@ -80,6 +80,9 @@ const NamedDecl *getDefinition(const NamedDecl *D) {
 return VD->getDefinition();
   if (const auto *FD = dyn_cast(D))
 return FD->getDefinition();
+  if (const auto *CTD = dyn_cast(D))
+if (const auto *RD = CTD->getTemplatedDecl())
+  return RD->getDefinition();
   // Objective-C classes can have three types of declarations:
   //
   // - forward declaration: @class MyClass;

diff  --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp 
b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
index 802367645c859..d567e0d77b39c 100644
--- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -675,7 +675,7 @@ TEST(LocateSymbol, All) {
 
   R"cpp(// Declaration of explicit template specialization
 template 
-struct $decl[[Foo]] {};
+struct $decl[[$def[[Foo {};
 
 template <>
 struct Fo^o {};
@@ -683,12 +683,25 @@ TEST(LocateSymbol, All) {
 
   R"cpp(// Declaration of partial template specialization
 template 
-struct $decl[[Foo]] {};
+struct $decl[[$def[[Foo {};
 
 template 
 struct Fo^o {};
   )cpp",
 
+  R"cpp(// Definition on ClassTemplateDecl
+namespace ns {
+  // Forward declaration.
+  template
+  struct $decl[[Foo]];
+
+  template 
+  struct $def[[Foo]] {};
+}
+
+using ::ns::Fo^o;
+  )cpp",
+
   R"cpp(// auto builtin type (not supported)
 ^auto x = 42;
   )cpp",



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


[clang-tools-extra] 2174524 - [clangd] AddUsing: Fix support for template specializations.

2021-10-26 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-10-26T17:32:33+02:00
New Revision: 2174524116a8379fb7a6453253524ec972b158df

URL: 
https://github.com/llvm/llvm-project/commit/2174524116a8379fb7a6453253524ec972b158df
DIFF: 
https://github.com/llvm/llvm-project/commit/2174524116a8379fb7a6453253524ec972b158df.diff

LOG: [clangd] AddUsing: Fix support for template specializations.

Before this change, we would add "using std::vector" instead of
just "using std::vector;", which would not even compile.

Fixes https://github.com/clangd/clangd/issues/904

Differential Revision: https://reviews.llvm.org/D112530

Added: 


Modified: 
clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp 
b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
index a8c937a951df..c1adbdde6199 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
@@ -278,8 +278,13 @@ bool AddUsing::prepare(const Selection &Inputs) {
   if (!QualifierToRemove)
 return false;
 
-  auto SpelledTokens =
-  TB.spelledForExpanded(TB.expandedTokens(E.getSourceRange()));
+  auto NameRange = E.getSourceRange();
+  if (auto T = E.getNamedTypeLoc().getAs()) 
{
+// Remove the template arguments from the name.
+NameRange.setEnd(T.getLAngleLoc().getLocWithOffset(-1));
+  }
+
+  auto SpelledTokens = TB.spelledForExpanded(TB.expandedTokens(NameRange));
   if (!SpelledTokens)
 return false;
   auto SpelledRange = syntax::Token::range(SM, SpelledTokens->front(),

diff  --git a/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp 
b/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp
index c0c66dbc14d7..b0c2d71328bd 100644
--- a/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp
+++ b/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp
@@ -444,6 +444,17 @@ one::t^wo::cc c;
 #include "test.hpp"
 using one::two::cc;using one::two::ee::ee_one;
 cc c;
+)cpp"},
+// Template (like std::vector).
+{R"cpp(
+#include "test.hpp"
+one::v^ec foo;
+)cpp",
+ R"cpp(
+#include "test.hpp"
+using one::vec;
+
+vec foo;
 )cpp"}};
   llvm::StringMap EditedFiles;
   for (const auto &Case : Cases) {
@@ -461,6 +472,7 @@ class cc {
 };
 }
 using uu = two::cc;
+template struct vec {};
 })cpp";
   EXPECT_EQ(apply(SubCase, &EditedFiles), Case.ExpectedSource);
 }



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


[clang-tools-extra] e8f4a01 - [clangd] Fix a hover crash on templated spaceship operator.

2021-10-26 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-10-26T17:28:40+02:00
New Revision: e8f4a01189143854f30e2bb622baa729a42f152d

URL: 
https://github.com/llvm/llvm-project/commit/e8f4a01189143854f30e2bb622baa729a42f152d
DIFF: 
https://github.com/llvm/llvm-project/commit/e8f4a01189143854f30e2bb622baa729a42f152d.diff

LOG: [clangd] Fix a hover crash on templated spaceship operator.

We make assumption that:
getDeclForComment(getDeclForComment(X)) == getDeclForComment(X)
but this is not true if you have a template
instantionation of a template instantiation, which is the case when, for
example, you have a <=> operator in a templated class.

This fix makes getDeclForComment() call itself recursively to ensure
this property is always true.

Fixes https://github.com/clangd/clangd/issues/901

Differential Revision: https://reviews.llvm.org/D112527

Added: 


Modified: 
clang-tools-extra/clangd/Hover.cpp
clang-tools-extra/clangd/unittests/HoverTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/Hover.cpp 
b/clang-tools-extra/clangd/Hover.cpp
index 8ef7d20c1d53..4285b3595059 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -262,24 +262,30 @@ const FunctionDecl *getUnderlyingFunction(const Decl *D) {
 // Returns the decl that should be used for querying comments, either from 
index
 // or AST.
 const NamedDecl *getDeclForComment(const NamedDecl *D) {
+  const NamedDecl *DeclForComment = D;
   if (const auto *TSD = llvm::dyn_cast(D)) {
 // Template may not be instantiated e.g. if the type didn't need to be
 // complete; fallback to primary template.
 if (TSD->getTemplateSpecializationKind() == TSK_Undeclared)
-  return TSD->getSpecializedTemplate();
-if (const auto *TIP = TSD->getTemplateInstantiationPattern())
-  return TIP;
-  }
-  if (const auto *TSD = llvm::dyn_cast(D)) {
+  DeclForComment = TSD->getSpecializedTemplate();
+else if (const auto *TIP = TSD->getTemplateInstantiationPattern())
+  DeclForComment = TIP;
+  } else if (const auto *TSD =
+ llvm::dyn_cast(D)) {
 if (TSD->getTemplateSpecializationKind() == TSK_Undeclared)
-  return TSD->getSpecializedTemplate();
-if (const auto *TIP = TSD->getTemplateInstantiationPattern())
-  return TIP;
-  }
-  if (const auto *FD = D->getAsFunction())
+  DeclForComment = TSD->getSpecializedTemplate();
+else if (const auto *TIP = TSD->getTemplateInstantiationPattern())
+  DeclForComment = TIP;
+  } else if (const auto *FD = D->getAsFunction())
 if (const auto *TIP = FD->getTemplateInstantiationPattern())
-  return TIP;
-  return D;
+  DeclForComment = TIP;
+  // Ensure that getDeclForComment(getDeclForComment(X)) = 
getDeclForComment(X).
+  // This is usually not needed, but in strange cases of comparision operators
+  // being instantiated from spasceship operater, which itself is a template
+  // instantiation the recursrive call is necessary.
+  if (D != DeclForComment)
+DeclForComment = getDeclForComment(DeclForComment);
+  return DeclForComment;
 }
 
 // Look up information about D from the index, and add it to Hover.

diff  --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp 
b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 6395da91463a..2e33ce4c5d10 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -2934,6 +2934,35 @@ Value = val
 def)pt";
   EXPECT_EQ(HI.present().asPlainText(), ExpectedPlaintext);
 }
+
+TEST(Hover, SpaceshipTemplateNoCrash) {
+  Annotations T(R"cpp(
+  namespace std {
+  struct strong_ordering {
+int n;
+constexpr operator int() const { return n; }
+static const strong_ordering equal, greater, less;
+  };
+  constexpr strong_ordering strong_ordering::equal = {0};
+  constexpr strong_ordering strong_ordering::greater = {1};
+  constexpr strong_ordering strong_ordering::less = {-1};
+  }
+
+  template 
+  struct S {
+// Foo bar baz
+friend auto operator<=>(S, S) = default;
+  };
+  static_assert(S() =^= S());
+)cpp");
+
+  TestTU TU = TestTU::withCode(T.code());
+  TU.ExtraArgs.push_back("-std=c++20");
+  auto AST = TU.build();
+  auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
+  EXPECT_EQ(HI->Documentation, "Foo bar baz");
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang



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


[clang-tools-extra] 8fbac4e - [clangd] Add code completion of param name on /* inside function calls.

2021-10-19 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-10-19T12:49:46+02:00
New Revision: 8fbac4e88ac3dde30310bb63b234045075cd338b

URL: 
https://github.com/llvm/llvm-project/commit/8fbac4e88ac3dde30310bb63b234045075cd338b
DIFF: 
https://github.com/llvm/llvm-project/commit/8fbac4e88ac3dde30310bb63b234045075cd338b.diff

LOG: [clangd] Add code completion of param name on /* inside function calls.

For example, if you have:
  void foo(int bar);
  foo(/*^
it should auto-complete to "bar=".

Because Sema callbacks for code completion in comments happen before we
have an AST we need to cheat in clangd by detecting completion on /*
before, moving cursor back by two characters, then running a simplified
verion of SignatureHelp to extract argument name(s) from possible
overloads.

Differential Revision: https://reviews.llvm.org/D110823

Added: 


Modified: 
clang-tools-extra/clangd/ClangdLSPServer.cpp
clang-tools-extra/clangd/CodeComplete.cpp
clang-tools-extra/clangd/test/initialize-params.test
clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp 
b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index a9debfd2a6ed5..c01a4286884b8 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -542,7 +542,7 @@ void ClangdLSPServer::onInitialize(const InitializeParams 
&Params,
  "^", "&",  "#", "?", ".", "=", "\"", "'", "|"}},
{"resolveProvider", false},
// We do extra checks, e.g. that > is part of ->.
-   {"triggerCharacters", {".", "<", ">", ":", "\"", "/"}},
+   {"triggerCharacters", {".", "<", ">", ":", "\"", "/", "*"}},
}},
   {"semanticTokensProvider",
llvm::json::Object{

diff  --git a/clang-tools-extra/clangd/CodeComplete.cpp 
b/clang-tools-extra/clangd/CodeComplete.cpp
index 2d01a163431e2..8c4b292d4 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -1098,6 +1098,50 @@ class SignatureHelpCollector final : public 
CodeCompleteConsumer {
   const SymbolIndex *Index;
 }; // SignatureHelpCollector
 
+// Used only for completion of C-style comments in function call (i.e.
+// /*foo=*/7). Similar to SignatureHelpCollector, but needs to do less work.
+class ParamNameCollector final : public CodeCompleteConsumer {
+public:
+  ParamNameCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,
+ std::set &ParamNames)
+  : CodeCompleteConsumer(CodeCompleteOpts),
+Allocator(std::make_shared()),
+CCTUInfo(Allocator), ParamNames(ParamNames) {}
+
+  void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
+ OverloadCandidate *Candidates,
+ unsigned NumCandidates,
+ SourceLocation OpenParLoc) override {
+assert(CurrentArg <= (unsigned)std::numeric_limits::max() &&
+   "too many arguments");
+
+for (unsigned I = 0; I < NumCandidates; ++I) {
+  OverloadCandidate Candidate = Candidates[I];
+  auto *Func = Candidate.getFunction();
+  if (!Func || Func->getNumParams() <= CurrentArg)
+continue;
+  auto *PVD = Func->getParamDecl(CurrentArg);
+  if (!PVD)
+continue;
+  auto *Ident = PVD->getIdentifier();
+  if (!Ident)
+continue;
+  auto Name = Ident->getName();
+  if (!Name.empty())
+ParamNames.insert(Name.str());
+}
+  }
+
+private:
+  GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }
+
+  CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
+
+  std::shared_ptr Allocator;
+  CodeCompletionTUInfo CCTUInfo;
+  std::set &ParamNames;
+};
+
 struct SemaCompleteInput {
   PathRef FileName;
   size_t Offset;
@@ -1860,6 +1904,59 @@ CompletionPrefix guessCompletionPrefix(llvm::StringRef 
Content,
   return Result;
 }
 
+// Code complete the argument name on "/*" inside function call.
+// Offset should be pointing to the start of the comment, i.e.:
+// foo(^/*, rather than foo(/*^) where the cursor probably is.
+CodeCompleteResult codeCompleteComment(PathRef FileName, unsigned Offset,
+   llvm::StringRef Prefix,
+   const PreambleData *Preamble,
+   const ParseInputs &ParseInput) {
+  if (Preamble == nullptr) // Can't run without Sema.
+return CodeCompleteResult();
+
+  clang::CodeCompleteOptions Options;
+  Options.IncludeGlobals = false;
+  Options.IncludeMacros = false;
+  Options.IncludeCodePatterns = false;
+  Options.IncludeBriefComments = false;
+  std::set ParamNames;
+  // We want to see signatures coming from newly introduced includes, hence a
+  // full patch.
+  semaCodeComplete(
+  std::make_uniq

[clang-tools-extra] fba563e - [clangd] TargetFinder: Fix assert-crash on TemplateExpansion args.

2021-10-13 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-10-13T13:15:36+02:00
New Revision: fba563e92b6412f49e7e49299d3d27f04f2e1400

URL: 
https://github.com/llvm/llvm-project/commit/fba563e92b6412f49e7e49299d3d27f04f2e1400
DIFF: 
https://github.com/llvm/llvm-project/commit/fba563e92b6412f49e7e49299d3d27f04f2e1400.diff

LOG: [clangd] TargetFinder: Fix assert-crash on TemplateExpansion args.

Previously we would call getAsTemplate() when kind == TemplateExpansion,
which triggers an assertion. The call is now replaced with
getAsTemplateOrTemplatePattern(), which is exactly the same as
getAsTemplate(), except it allows calls when kind == TemplateExpansion.

No change in behavior for no-assert builds.

Differential Revision: https://reviews.llvm.org/D111648

Added: 


Modified: 
clang-tools-extra/clangd/FindTarget.cpp
clang-tools-extra/clangd/unittests/FindTargetTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/FindTarget.cpp 
b/clang-tools-extra/clangd/FindTarget.cpp
index 8419043f4462a..82e4dfeccf43d 100644
--- a/clang-tools-extra/clangd/FindTarget.cpp
+++ b/clang-tools-extra/clangd/FindTarget.cpp
@@ -507,7 +507,8 @@ struct TargetFinder {
 // DeclRefExpr).
 if (Arg.getKind() == TemplateArgument::Template ||
 Arg.getKind() == TemplateArgument::TemplateExpansion) {
-  if (TemplateDecl *TD = Arg.getAsTemplate().getAsTemplateDecl()) {
+  if (TemplateDecl *TD =
+  Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) {
 report(TD, Flags);
   }
 }

diff  --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp 
b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index 14cb15a7644b0..9620db9838ae2 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -341,6 +341,15 @@ TEST_F(TargetDeclTest, Types) {
   EXPECT_DECLS("TemplateSpecializationTypeLoc", "template  class T");
   Flags.clear();
 
+  Code = R"cpp(
+  template class ...T>
+  class C {
+C<[[T...]]> foo;
+};
+  )cpp";
+  EXPECT_DECLS("TemplateArgumentLoc", {"template  class ...T"});
+  Flags.clear();
+
   Code = R"cpp(
 struct S{};
 S X;



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


[clang] 08128fe - [clang] Make member var invalid when static initializer is invalid.

2021-08-03 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-08-03T11:52:52+02:00
New Revision: 08128fe7059e20b3f97ae5abbdeff2e6f6c711ed

URL: 
https://github.com/llvm/llvm-project/commit/08128fe7059e20b3f97ae5abbdeff2e6f6c711ed
DIFF: 
https://github.com/llvm/llvm-project/commit/08128fe7059e20b3f97ae5abbdeff2e6f6c711ed.diff

LOG: [clang] Make member var invalid when static initializer is invalid.

Previously we would show an error, but keep the member, and also the
CXXRrecordDecl, valid. This could lead to crashes when attempting to
access the record layout or size.

Differential Revision: https://reviews.llvm.org/D105478

Added: 
clang/test/AST/ast-dump-undeduced-expr.cpp

Modified: 
clang/lib/Parse/ParseDeclCXX.cpp
clang/test/SemaCXX/crash-auto-36064.cpp
clang/test/SemaCXX/cxx11-crashes.cpp

Removed: 




diff  --git a/clang/lib/Parse/ParseDeclCXX.cpp 
b/clang/lib/Parse/ParseDeclCXX.cpp
index ca5c013a51fe0..760600a3ea3ca 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -2989,9 +2989,11 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier 
AS,
   ExprResult Init = ParseCXXMemberInitializer(
   ThisDecl, DeclaratorInfo.isDeclarationOfFunction(), EqualLoc);
 
-  if (Init.isInvalid())
+  if (Init.isInvalid()) {
+if (ThisDecl)
+  Actions.ActOnUninitializedDecl(ThisDecl);
 SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
-  else if (ThisDecl)
+  } else if (ThisDecl)
 Actions.AddInitializerToDecl(ThisDecl, Init.get(), 
EqualLoc.isInvalid());
 } else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static)
   // No initializer.

diff  --git a/clang/test/AST/ast-dump-undeduced-expr.cpp 
b/clang/test/AST/ast-dump-undeduced-expr.cpp
new file mode 100644
index 0..d404db9285974
--- /dev/null
+++ b/clang/test/AST/ast-dump-undeduced-expr.cpp
@@ -0,0 +1,7 @@
+// RUN: not %clang_cc1 -triple x86_64-unknown-unknown -ast-dump %s | FileCheck 
%s
+
+struct Foo {
+  static constexpr auto Bar = ;
+};
+
+// CHECK: -VarDecl {{.*}} invalid Bar 'const auto' static constexpr

diff  --git a/clang/test/SemaCXX/crash-auto-36064.cpp 
b/clang/test/SemaCXX/crash-auto-36064.cpp
index 5678cd8b730b8..a34e5eea51cb0 100644
--- a/clang/test/SemaCXX/crash-auto-36064.cpp
+++ b/clang/test/SemaCXX/crash-auto-36064.cpp
@@ -1,8 +1,9 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
-template  // expected-error{{new expression for 
type 'auto' requires a constructor argument}}
+template 
 struct b;
 struct d {
   static auto c = ;  // expected-error{{expected expression}}
+ // expected-error@-1 {{declaration of 
variable 'c' with deduced type 'auto' requires an initializer}}
+
   decltype(b); // expected-error{{expected '(' for 
function-style cast or type construction}}
- // expected-note@-1{{while substituting prior 
template arguments into non-type template parameter [with A = auto]}}
 };

diff  --git a/clang/test/SemaCXX/cxx11-crashes.cpp 
b/clang/test/SemaCXX/cxx11-crashes.cpp
index d60782df35f45..e63a9be956942 100644
--- a/clang/test/SemaCXX/cxx11-crashes.cpp
+++ b/clang/test/SemaCXX/cxx11-crashes.cpp
@@ -104,3 +104,22 @@ namespace pr29091 {
   bool baz() { return __has_nothrow_constructor(B); }
   bool qux() { return __has_nothrow_copy(B); }
 }
+
+namespace undeduced_field {
+template
+struct Foo {
+  typedef T type;
+};
+
+struct Bar {
+  Bar();
+  // The missing expression makes A undeduced.
+  static constexpr auto A = ;  // expected-error {{expected expression}}
+   // expected-error@-1 {{declaration of variable 
'A' with deduced type 'const auto' requires an initializer}}
+
+  Foo::type B;  // The type of B is also undeduced (wrapped in 
Elaborated).
+};
+
+// This used to crash when trying to get the layout of B.
+Bar x;
+}



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


[clang] 49eba8b - [clang] Do not crash when ArgTy is null in CheckArgAlignment

2021-06-10 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-06-10T16:54:15+02:00
New Revision: 49eba8bf1780684f1173a455b909ce37008eaa09

URL: 
https://github.com/llvm/llvm-project/commit/49eba8bf1780684f1173a455b909ce37008eaa09
DIFF: 
https://github.com/llvm/llvm-project/commit/49eba8bf1780684f1173a455b909ce37008eaa09.diff

LOG: [clang] Do not crash when ArgTy is null in CheckArgAlignment

This can happen around RecoveryExpr.

Differential Revision: https://reviews.llvm.org/D103825

Added: 


Modified: 
clang/lib/Sema/SemaChecking.cpp
clang/test/SemaCXX/recovery-expr-type.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 99110c6b5d8dd..86c888548077e 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -4571,8 +4571,9 @@ void Sema::CheckArgAlignment(SourceLocation Loc, 
NamedDecl *FDecl,
 
   // Find expected alignment, and the actual alignment of the passed object.
   // getTypeAlignInChars requires complete types
-  if (ParamTy->isIncompleteType() || ArgTy->isIncompleteType() ||
-  ParamTy->isUndeducedType() || ArgTy->isUndeducedType())
+  if (ArgTy.isNull() || ParamTy->isIncompleteType() ||
+  ArgTy->isIncompleteType() || ParamTy->isUndeducedType() ||
+  ArgTy->isUndeducedType())
 return;
 
   CharUnits ParamAlign = Context.getTypeAlignInChars(ParamTy);
@@ -4654,6 +4655,9 @@ void Sema::checkCall(NamedDecl *FDecl, const 
FunctionProtoType *Proto,
 for (unsigned ArgIdx = 0; ArgIdx < N; ++ArgIdx) {
   // Args[ArgIdx] can be null in malformed code.
   if (const Expr *Arg = Args[ArgIdx]) {
+if (Arg->containsErrors())
+  continue;
+
 QualType ParamTy = Proto->getParamType(ArgIdx);
 QualType ArgTy = Arg->getType();
 CheckArgAlignment(Arg->getExprLoc(), FDecl, std::to_string(ArgIdx + 1),

diff  --git a/clang/test/SemaCXX/recovery-expr-type.cpp 
b/clang/test/SemaCXX/recovery-expr-type.cpp
index 8bdf83e9512fd..d3ac772db0089 100644
--- a/clang/test/SemaCXX/recovery-expr-type.cpp
+++ b/clang/test/SemaCXX/recovery-expr-type.cpp
@@ -136,3 +136,9 @@ void baz() {
   bar(S(123)); // expected-error {{no matching conversion}}
 }
 } // namespace test11
+
+namespace test12 {
+// Verify we do not crash.
+void fun(int *foo = no_such_function()); // expected-error {{undeclared 
identifier}}
+void baz() { fun(); }
+} // namespace test12



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


[clang] a959374 - [clang] Make CXXDefaultArgExpr inherit dependence from the inner Expr

2021-06-10 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-06-10T14:51:08+02:00
New Revision: a95937452f237fad10e6b7e43154c17c6b8476c4

URL: 
https://github.com/llvm/llvm-project/commit/a95937452f237fad10e6b7e43154c17c6b8476c4
DIFF: 
https://github.com/llvm/llvm-project/commit/a95937452f237fad10e6b7e43154c17c6b8476c4.diff

LOG: [clang] Make CXXDefaultArgExpr inherit dependence from the inner Expr

Before this change, CXXDefaultArgExpr would always have
ExprDependence::None. This can lead to issues when, for example, the
inner expression is RecoveryExpr and yet containsErrors() on the default
expression is false.

Differential Revision: https://reviews.llvm.org/D103982

Added: 
clang/test/AST/ast-dump-default-arg-dep.cpp

Modified: 
clang/include/clang/AST/ComputeDependence.h
clang/include/clang/AST/ExprCXX.h
clang/lib/AST/ComputeDependence.cpp

Removed: 




diff  --git a/clang/include/clang/AST/ComputeDependence.h 
b/clang/include/clang/AST/ComputeDependence.h
index 7dde42ee71ba0..8db09e6b57d0f 100644
--- a/clang/include/clang/AST/ComputeDependence.h
+++ b/clang/include/clang/AST/ComputeDependence.h
@@ -71,6 +71,7 @@ class OverloadExpr;
 class DependentScopeDeclRefExpr;
 class CXXConstructExpr;
 class CXXDefaultInitExpr;
+class CXXDefaultArgExpr;
 class LambdaExpr;
 class CXXUnresolvedConstructExpr;
 class CXXDependentScopeMemberExpr;
@@ -156,6 +157,7 @@ ExprDependence computeDependence(OverloadExpr *E, bool 
KnownDependent,
 ExprDependence computeDependence(DependentScopeDeclRefExpr *E);
 ExprDependence computeDependence(CXXConstructExpr *E);
 ExprDependence computeDependence(CXXDefaultInitExpr *E);
+ExprDependence computeDependence(CXXDefaultArgExpr *E);
 ExprDependence computeDependence(LambdaExpr *E,
  bool ContainsUnexpandedParameterPack);
 ExprDependence computeDependence(CXXUnresolvedConstructExpr *E);

diff  --git a/clang/include/clang/AST/ExprCXX.h 
b/clang/include/clang/AST/ExprCXX.h
index c46f9bd7f4db0..2626f9b925962 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -1257,7 +1257,7 @@ class CXXDefaultArgExpr final : public Expr {
  Param->getDefaultArg()->getObjectKind()),
 Param(Param), UsedContext(UsedContext) {
 CXXDefaultArgExprBits.Loc = Loc;
-setDependence(ExprDependence::None);
+setDependence(computeDependence(this));
   }
 
 public:

diff  --git a/clang/lib/AST/ComputeDependence.cpp 
b/clang/lib/AST/ComputeDependence.cpp
index 1a5d2f7075fb5..5648cf2103d64 100644
--- a/clang/lib/AST/ComputeDependence.cpp
+++ b/clang/lib/AST/ComputeDependence.cpp
@@ -748,6 +748,10 @@ ExprDependence clang::computeDependence(CXXDefaultInitExpr 
*E) {
   return E->getExpr()->getDependence();
 }
 
+ExprDependence clang::computeDependence(CXXDefaultArgExpr *E) {
+  return E->getExpr()->getDependence();
+}
+
 ExprDependence clang::computeDependence(LambdaExpr *E,
 bool ContainsUnexpandedParameterPack) {
   auto D = toExprDependence(E->getType()->getDependence());

diff  --git a/clang/test/AST/ast-dump-default-arg-dep.cpp 
b/clang/test/AST/ast-dump-default-arg-dep.cpp
new file mode 100644
index 0..a804ac120fca4
--- /dev/null
+++ b/clang/test/AST/ast-dump-default-arg-dep.cpp
@@ -0,0 +1,10 @@
+// RUN: not %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -ast-dump 
-frecovery-ast %s | FileCheck %s
+
+// CXXDefaultArgExpr should inherit dependence from the inner Expr, in this 
case
+// RecoveryExpr.
+void fun(int arg = foo());
+
+void test() {
+  fun();
+}
+// CHECK: -CXXDefaultArgExpr 0x{{[^ ]*}} <> '' 
contains-errors lvalue



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


[clang] 721476e - [clang] Fix a crash during code completion

2021-06-07 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-06-07T13:29:58+02:00
New Revision: 721476e6b2119a93033903109b54f429b6e8c91b

URL: 
https://github.com/llvm/llvm-project/commit/721476e6b2119a93033903109b54f429b6e8c91b
DIFF: 
https://github.com/llvm/llvm-project/commit/721476e6b2119a93033903109b54f429b6e8c91b.diff

LOG: [clang] Fix a crash during code completion

During code completion, lookupInDeclContext() calls
CodeCompletionDeclConsumer::FoundDecl(),which can mutate StoredDeclsMap,
over which lookupInDeclContext() iterates. This can lead to invalidation
of iterators and an assert()-crash.

Example code where this happens:
 #include 
 int main() {
   std::list;
   std::^
 }
with code completion on ^ with -std=c++20.

I do not have a repro case that does not need standard library.

This fix stores pointers to NamedDecls in a temporary vector, then
visits them outside of the main loop, when StoredDeclsMap iterators are
gone.

Differential Revision: https://reviews.llvm.org/D103472

Added: 


Modified: 
clang/lib/Sema/SemaLookup.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index db6a01543d76..4b3d7de04bf7 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -3835,6 +3835,7 @@ class LookupVisibleHelper {
 if (CXXRecordDecl *Class = dyn_cast(Ctx))
   Result.getSema().ForceDeclarationOfImplicitMembers(Class);
 
+llvm::SmallVector DeclsToVisit;
 // We sometimes skip loading namespace-level results (they tend to be 
huge).
 bool Load = LoadExternal ||
 !(isa(Ctx) || isa(Ctx));
@@ -3844,12 +3845,21 @@ class LookupVisibleHelper {
   : Ctx->noload_lookups(/*PreserveInternalState=*/false)) {
   for (auto *D : R) {
 if (auto *ND = Result.getAcceptableDecl(D)) {
-  Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
-  Visited.add(ND);
+  // Rather than visit immediatelly, we put ND into a vector and visit
+  // all decls, in order, outside of this loop. The reason is that
+  // Consumer.FoundDecl() may invalidate the iterators used in the two
+  // loops above.
+  DeclsToVisit.push_back(ND);
 }
   }
 }
 
+for (auto *ND : DeclsToVisit) {
+  Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
+  Visited.add(ND);
+}
+DeclsToVisit.clear();
+
 // Traverse using directives for qualified name lookup.
 if (QualifiedNameLookup) {
   ShadowContextRAII Shadow(Visited);



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


[clang-tools-extra] eba3ee0 - [clangd] Run code completion on each token coverd by --check-lines

2021-06-04 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-06-04T17:51:42+02:00
New Revision: eba3ee04d450230f7ac1f88b1abd7b09c600c82d

URL: 
https://github.com/llvm/llvm-project/commit/eba3ee04d450230f7ac1f88b1abd7b09c600c82d
DIFF: 
https://github.com/llvm/llvm-project/commit/eba3ee04d450230f7ac1f88b1abd7b09c600c82d.diff

LOG: [clangd] Run code completion on each token coverd by --check-lines

In --check mode we do not run code completion because it is too slow,
especially on larger files. With the introducation of --check-lines we
can narrow down the scope and thus we can afford to do code completion.

We vlog() the top completion result, but that's not really the point.
The most value will come from being able to reproduce crashes that occur
during code completion and require preamble build or index (and thus are
more difficult to reproduce with -code-complete-at).

Differential Revision: https://reviews.llvm.org/D103538

Added: 


Modified: 
clang-tools-extra/clangd/tool/Check.cpp
clang-tools-extra/clangd/tool/ClangdMain.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/tool/Check.cpp 
b/clang-tools-extra/clangd/tool/Check.cpp
index 89487bd8607f1..88eb945d20d43 100644
--- a/clang-tools-extra/clangd/tool/Check.cpp
+++ b/clang-tools-extra/clangd/tool/Check.cpp
@@ -193,10 +193,15 @@ class Checker {
 
   // Run AST-based features at each token in the file.
   void testLocationFeatures(
-  llvm::function_ref ShouldCheckLine) {
+  llvm::function_ref ShouldCheckLine,
+  const bool EnableCodeCompletion) {
 log("Testing features at each token (may be slow in large files)");
 auto &SM = AST->getSourceManager();
 auto SpelledTokens = AST->getTokens().spelledTokens(SM.getMainFileID());
+
+CodeCompleteOptions CCOpts = Opts.CodeComplete;
+CCOpts.Index = &Index;
+
 for (const auto &Tok : SpelledTokens) {
   unsigned Start = AST->getSourceManager().getFileOffset(Tok.location());
   unsigned End = Start + Tok.length();
@@ -233,8 +238,12 @@ class Checker {
   auto Hover = getHover(*AST, Pos, Style, &Index);
   vlog("hover: {0}", Hover.hasValue());
 
-  // FIXME: it'd be nice to include code completion, but it's too slow.
-  // Maybe in combination with a line restriction?
+  if (EnableCodeCompletion) {
+Position EndPos = offsetToPosition(Inputs.Contents, End);
+auto CC = codeComplete(File, EndPos, Preamble.get(), Inputs, CCOpts);
+vlog("code completion: {0}",
+ CC.Completions.empty() ? "" : CC.Completions[0].Name);
+  }
 }
   }
 };
@@ -243,7 +252,8 @@ class Checker {
 
 bool check(llvm::StringRef File,
llvm::function_ref ShouldCheckLine,
-   const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts) {
+   const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts,
+   bool EnableCodeCompletion) {
   llvm::SmallString<0> FakeFile;
   llvm::Optional Contents;
   if (File.empty()) {
@@ -267,7 +277,7 @@ bool check(llvm::StringRef File,
   if (!C.buildCommand(TFS) || !C.buildInvocation(TFS, Contents) ||
   !C.buildAST())
 return false;
-  C.testLocationFeatures(ShouldCheckLine);
+  C.testLocationFeatures(ShouldCheckLine, EnableCodeCompletion);
 
   log("All checks completed, {0} errors", C.ErrCount);
   return C.ErrCount == 0;

diff  --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp 
b/clang-tools-extra/clangd/tool/ClangdMain.cpp
index f0aa89b8091fb..0f9e5c89e42c8 100644
--- a/clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -62,7 +62,8 @@ namespace clangd {
 // Implemented in Check.cpp.
 bool check(const llvm::StringRef File,
llvm::function_ref ShouldCheckLine,
-   const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts);
+   const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts,
+   bool EnableCodeCompletion);
 
 namespace {
 
@@ -929,7 +930,11 @@ clangd accepts flags on the commandline, and in the 
CLANGD_FLAGS environment var
   uint32_t Line = Pos.line + 1; // Position::line is 0-based.
   return Line >= Begin && Line <= End;
 };
-return check(Path, ShouldCheckLine, TFS, Opts)
+// For now code completion is enabled any time the range is limited via
+// --check-lines. If it turns out to be to slow, we can introduce a
+// dedicated flag for that instead.
+return check(Path, ShouldCheckLine, TFS, Opts,
+ /*EnableCodeCompletion=*/!CheckFileLines.empty())
? 0
: static_cast(ErrorResultCode::CheckFailed);
   }



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


[clang] fbfcfdb - [clang] Fix assert() crash when checking undeduced arg alignment

2021-04-30 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-04-30T16:24:33+02:00
New Revision: fbfcfdbf6828b8d36f4ec0ff5f4eac11fb1411a5

URL: 
https://github.com/llvm/llvm-project/commit/fbfcfdbf6828b8d36f4ec0ff5f4eac11fb1411a5
DIFF: 
https://github.com/llvm/llvm-project/commit/fbfcfdbf6828b8d36f4ec0ff5f4eac11fb1411a5.diff

LOG: [clang] Fix assert() crash when checking undeduced arg alignment

There already was a check for undeduced and incomplete types, but it
failed to trigger when outer type (SubstTemplateTypeParm in test) looked
fine, but inner type was not.

Differential Revision: https://reviews.llvm.org/D100667

Added: 


Modified: 
clang/lib/Sema/SemaChecking.cpp
clang/lib/Sema/SemaExpr.cpp
clang/test/SemaCXX/recovery-expr-type.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 7b6e0541aa4d7..38cda657bac8b 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -4540,8 +4540,7 @@ void Sema::CheckArgAlignment(SourceLocation Loc, 
NamedDecl *FDecl,
 
   // Find expected alignment, and the actual alignment of the passed object.
   // getTypeAlignInChars requires complete types
-  if (ParamTy->isIncompleteType() || ArgTy->isIncompleteType() ||
-  ParamTy->isUndeducedType() || ArgTy->isUndeducedType())
+  if (ParamTy->isIncompleteType() || ArgTy->isIncompleteType())
 return;
 
   CharUnits ParamAlign = Context.getTypeAlignInChars(ParamTy);

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index e0f46a0ead40a..73d7675eb189f 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -19662,8 +19662,10 @@ ExprResult Sema::CreateRecoveryExpr(SourceLocation 
Begin, SourceLocation End,
   if (isSFINAEContext())
 return ExprError();
 
-  if (T.isNull() || !Context.getLangOpts().RecoveryASTType)
+  if (T.isNull() || T->isUndeducedType() ||
+  !Context.getLangOpts().RecoveryASTType)
 // We don't know the concrete type, fallback to dependent type.
 T = Context.DependentTy;
+
   return RecoveryExpr::Create(Context, T, Begin, End, SubExprs);
 }

diff  --git a/clang/test/SemaCXX/recovery-expr-type.cpp 
b/clang/test/SemaCXX/recovery-expr-type.cpp
index ed18b7f262cdc..8bdf83e9512fd 100644
--- a/clang/test/SemaCXX/recovery-expr-type.cpp
+++ b/clang/test/SemaCXX/recovery-expr-type.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -frecovery-ast 
-frecovery-ast-type -o - %s -fsyntax-only -verify
+// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -frecovery-ast 
-frecovery-ast-type -o - %s -std=gnu++17 -fsyntax-only -verify
 
 namespace test0 {
 struct Indestructible {
@@ -26,7 +26,7 @@ namespace test2 {
 void foo(); // expected-note 3{{requires 0 arguments}}
 void func() {
   // verify that "field has incomplete type" diagnostic is suppressed.
-  typeof(foo(42)) var; // expected-error {{no matching function}}
+  typeof(foo(42)) var; // expected-error {{no matching function}} \
 
   // FIXME: suppress the "cannot initialize a variable" diagnostic.
   int a = foo(1); // expected-error {{no matching function}} \
@@ -116,3 +116,23 @@ int f(); // expected-note {{candidate}}
 template const int k = f(T()); // expected-error {{no matching 
function}}
 static_assert(k == 1, ""); // expected-note {{instantiation of}}
 }
+
+namespace test11 {
+// Verify we do not assert()-fail here.
+template  void foo(T &t);
+template 
+void bar(T t) {
+  foo(t);
+}
+
+template 
+struct S { // expected-note {{candidate}}
+  S(T t);  // expected-note {{candidate}}
+  ~S();
+};
+template  S(T t) -> S;
+
+void baz() {
+  bar(S(123)); // expected-error {{no matching conversion}}
+}
+} // namespace test11



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


[clang] ddfbdbf - [clang] Do not crash on template specialization following a fatal error

2021-04-23 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-04-23T13:34:05+02:00
New Revision: ddfbdbfefae04ea71391a38ed5e9cb6975f6630b

URL: 
https://github.com/llvm/llvm-project/commit/ddfbdbfefae04ea71391a38ed5e9cb6975f6630b
DIFF: 
https://github.com/llvm/llvm-project/commit/ddfbdbfefae04ea71391a38ed5e9cb6975f6630b.diff

LOG: [clang] Do not crash on template specialization following a fatal error

There was a missing isInvalid() check leading to an attempt to
instantiate template with an empty instantiation stack.

Differential Revision: https://reviews.llvm.org/D100675

Added: 
clang/test/SemaCXX/template-specialization-fatal.cpp

Modified: 
clang/lib/Sema/SemaTemplateDeduction.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index d755696c698c6..7d548e4f8dee1 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -5466,6 +5466,9 @@ static bool isAtLeastAsSpecializedAs(Sema &S, QualType 
T1, QualType T2,
Deduced.end());
   Sema::InstantiatingTemplate Inst(S, Info.getLocation(), P2, DeducedArgs,
Info);
+  if (Inst.isInvalid())
+return false;
+
   auto *TST1 = T1->castAs();
   bool AtLeastAsSpecialized;
   S.runWithSufficientStackSpace(Info.getLocation(), [&] {

diff  --git a/clang/test/SemaCXX/template-specialization-fatal.cpp 
b/clang/test/SemaCXX/template-specialization-fatal.cpp
new file mode 100644
index 0..2191e54c8f162
--- /dev/null
+++ b/clang/test/SemaCXX/template-specialization-fatal.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s
+// Verify clang doesn't assert()-fail on template specialization happening 
after
+// fatal error.
+
+#include "not_found.h" // expected-error {{'not_found.h' file not found}}
+
+template 
+struct foo {};
+
+template 
+struct foo(0)(static_cast(0)()))> {};



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


[clang-tools-extra] 3b4936b - [clangd] Add --check-lines to restrict --check to specific lines

2021-04-09 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-04-09T13:47:20+02:00
New Revision: 3b4936ba290594cda4e53169958fe11c83119657

URL: 
https://github.com/llvm/llvm-project/commit/3b4936ba290594cda4e53169958fe11c83119657
DIFF: 
https://github.com/llvm/llvm-project/commit/3b4936ba290594cda4e53169958fe11c83119657.diff

LOG: [clangd] Add --check-lines to restrict --check to specific lines

This will allow us to add code completion, which is too expensive at
every token, to --check too.

Differential Revision: https://reviews.llvm.org/D98970

Added: 
clang-tools-extra/clangd/test/check-lines.test

Modified: 
clang-tools-extra/clangd/tool/Check.cpp
clang-tools-extra/clangd/tool/ClangdMain.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/test/check-lines.test 
b/clang-tools-extra/clangd/test/check-lines.test
new file mode 100644
index ..bfd30dd6104f
--- /dev/null
+++ b/clang-tools-extra/clangd/test/check-lines.test
@@ -0,0 +1,15 @@
+// RUN: cp %s %t.cpp
+// RUN: not clangd -check=%t.cpp -check-lines=6-14 2>&1 | FileCheck 
-strict-whitespace %s
+// RUN: not clangd -check=%t.cpp -check-lines=14 2>&1 | FileCheck 
-strict-whitespace %s
+
+// CHECK: Testing on source file {{.*}}check-lines.test
+// CHECK: internal (cc1) args are: -cc1
+// CHECK: Building preamble...
+// CHECK: Building AST...
+// CHECK: Testing features at each token
+// CHECK: tweak: ExpandAutoType ==> FAIL
+// CHECK: All checks completed, 1 errors
+
+void fun();
+auto x = fun; // This line is tested
+auto y = fun; // This line is not tested

diff  --git a/clang-tools-extra/clangd/tool/Check.cpp 
b/clang-tools-extra/clangd/tool/Check.cpp
index 20b86daff8af..0138ae3eb13b 100644
--- a/clang-tools-extra/clangd/tool/Check.cpp
+++ b/clang-tools-extra/clangd/tool/Check.cpp
@@ -192,14 +192,19 @@ class Checker {
   }
 
   // Run AST-based features at each token in the file.
-  void testLocationFeatures() {
+  void testLocationFeatures(
+  llvm::function_ref ShouldCheckLine) {
 log("Testing features at each token (may be slow in large files)");
-auto SpelledTokens =
-
AST->getTokens().spelledTokens(AST->getSourceManager().getMainFileID());
+auto &SM = AST->getSourceManager();
+auto SpelledTokens = AST->getTokens().spelledTokens(SM.getMainFileID());
 for (const auto &Tok : SpelledTokens) {
   unsigned Start = AST->getSourceManager().getFileOffset(Tok.location());
   unsigned End = Start + Tok.length();
   Position Pos = offsetToPosition(Inputs.Contents, Start);
+
+  if (!ShouldCheckLine(Pos))
+continue;
+
   // FIXME: dumping the tokens may leak sensitive code into bug reports.
   // Add an option to turn this off, once we decide how options work.
   vlog("  {0} {1}", Pos, Tok.text(AST->getSourceManager()));
@@ -229,8 +234,9 @@ class Checker {
 
 } // namespace
 
-bool check(llvm::StringRef File, const ThreadsafeFS &TFS,
-   const ClangdLSPServer::Options &Opts) {
+bool check(llvm::StringRef File,
+   llvm::function_ref ShouldCheckLine,
+   const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts) {
   llvm::SmallString<0> FakeFile;
   llvm::Optional Contents;
   if (File.empty()) {
@@ -254,7 +260,7 @@ bool check(llvm::StringRef File, const ThreadsafeFS &TFS,
   if (!C.buildCommand(TFS) || !C.buildInvocation(TFS, Contents) ||
   !C.buildAST())
 return false;
-  C.testLocationFeatures();
+  C.testLocationFeatures(ShouldCheckLine);
 
   log("All checks completed, {0} errors", C.ErrCount);
   return C.ErrCount == 0;

diff  --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp 
b/clang-tools-extra/clangd/tool/ClangdMain.cpp
index c48821cba2c7..6dd13a503887 100644
--- a/clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -60,8 +60,9 @@ namespace clang {
 namespace clangd {
 
 // Implemented in Check.cpp.
-bool check(const llvm::StringRef File, const ThreadsafeFS &TFS,
-   const ClangdLSPServer::Options &Opts);
+bool check(const llvm::StringRef File,
+   llvm::function_ref ShouldCheckLine,
+   const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts);
 
 namespace {
 
@@ -347,6 +348,17 @@ opt CheckFile{
 ValueOptional,
 };
 
+opt CheckFileLines{
+"check-lines",
+cat(Misc),
+desc("If specified, limits the range of tokens in -check file on which "
+ "various features are tested. Example --check-lines=3-7 restricts "
+ "testing to lines 3 to 7 (inclusive) or --check-lines=5 to restrict "
+ "to one line. Default is testing entire file."),
+init(""),
+ValueOptional,
+};
+
 enum PCHStorageFlag { Disk, Memory };
 opt PCHStorage{
 "pch-storage",
@@ -883,10 +895,33 @@ clangd accepts flags on the commandline, and in the 
CLANGD_FLAGS environment var
 llvm::SmallString<256> Path;
 llvm::sys::fs::real_path(CheckFile, Path, /*expand_tilde=*/t

[clang] 4e1c487 - [clang] Fix crash when creating deduction guide.

2021-03-09 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-03-09T16:57:56+01:00
New Revision: 4e1c487004a29ec9bc56fd47fc30336d033c57dd

URL: 
https://github.com/llvm/llvm-project/commit/4e1c487004a29ec9bc56fd47fc30336d033c57dd
DIFF: 
https://github.com/llvm/llvm-project/commit/4e1c487004a29ec9bc56fd47fc30336d033c57dd.diff

LOG: [clang] Fix crash when creating deduction guide.

We used to trigger assertion when transforming c-tor with unparsed
default argument. Now we ignore such constructors for this purpose.

Differential Revision: https://reviews.llvm.org/D97965

Added: 


Modified: 
clang/lib/Sema/SemaTemplate.cpp
clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 12880b95b9c6..7a65c2a6fe2c 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -2494,6 +2494,12 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl 
*Template,
 if (!CD || (!FTD && CD->isFunctionTemplateSpecialization()))
   continue;
 
+// Cannot make a deduction guide when unparsed arguments are present.
+if (std::any_of(CD->param_begin(), CD->param_end(), [](ParmVarDecl *P) {
+  return !P || P->hasUnparsedDefaultArg();
+}))
+  continue;
+
 Transform.transformConstructor(FTD, CD);
 AddedAny = true;
   }

diff  --git a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp 
b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
index 305cc3e976b0..161944f9e64f 100644
--- a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -416,6 +416,17 @@ B b(0, {});
 
 }
 
+namespace no_crash_on_default_arg {
+class A {
+  template  class B {
+B(int c = 1);
+  };
+  // This used to crash due to unparsed default arg above. The diagnostic could
+  // be improved, but the point of this test is to simply check we do not 
crash.
+  B(); // expected-error {{deduction guide declaration without trailing return 
type}}
+};
+} // namespace no_crash_on_default_arg
+
 #pragma clang diagnostic push
 #pragma clang diagnostic warning "-Wctad-maybe-unsupported"
 namespace test_implicit_ctad_warning {



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


[clang] 0005438 - [clangd] Fix a crash when indexing invalid ObjC method declaration

2021-01-25 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-01-25T15:43:11+01:00
New Revision: 00054382b95a9d95e2df6457e7fe1fca2323d287

URL: 
https://github.com/llvm/llvm-project/commit/00054382b95a9d95e2df6457e7fe1fca2323d287
DIFF: 
https://github.com/llvm/llvm-project/commit/00054382b95a9d95e2df6457e7fe1fca2323d287.diff

LOG: [clangd] Fix a crash when indexing invalid ObjC method declaration

This fix will make us not crash, but ideally we would handle this case
better.

Differential Revision: https://reviews.llvm.org/D94919

Added: 


Modified: 
clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
clang/lib/Sema/SemaCodeComplete.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp 
b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
index 7e36cff7afa6..924cfd03cba7 100644
--- a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1838,6 +1838,20 @@ TEST_F(SymbolCollectorTest, UndefOfModuleMacro) {
   EXPECT_THAT(TU.headerSymbols(), Not(Contains(QName("X";
 }
 
+TEST_F(SymbolCollectorTest, NoCrashOnObjCMethodCStyleParam) {
+  auto TU = TestTU::withCode(R"objc(
+@interface Foo
+- (void)fun:(bool)foo, bool bar;
+@end
+  )objc");
+  TU.ExtraArgs.push_back("-xobjective-c++");
+
+  TU.build();
+  // We mostly care about not crashing.
+  EXPECT_THAT(TU.headerSymbols(),
+  UnorderedElementsAre(QName("Foo"), QName("Foo::fun:")));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang

diff  --git a/clang/lib/Sema/SemaCodeComplete.cpp 
b/clang/lib/Sema/SemaCodeComplete.cpp
index d77c9e43a9bd..c2785fd60fc2 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -3529,9 +3529,11 @@ CodeCompletionString 
*CodeCompletionResult::createCodeCompletionStringForDecl(
 Result.AddTypedTextChunk("");
 }
 unsigned Idx = 0;
+// The extra Idx < Sel.getNumArgs() check is needed due to legacy C-style
+// method parameters.
 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
   PEnd = Method->param_end();
- P != PEnd; (void)++P, ++Idx) {
+ P != PEnd && Idx < Sel.getNumArgs(); (void)++P, ++Idx) {
   if (Idx > 0) {
 std::string Keyword;
 if (Idx > StartParameter)



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


[clang] d462aa5 - [clang] Fix a nullptr dereference bug on invalid code

2021-01-25 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-01-25T15:02:25+01:00
New Revision: d462aa5a619ab9fdf8b024e48c19bc8820fe8781

URL: 
https://github.com/llvm/llvm-project/commit/d462aa5a619ab9fdf8b024e48c19bc8820fe8781
DIFF: 
https://github.com/llvm/llvm-project/commit/d462aa5a619ab9fdf8b024e48c19bc8820fe8781.diff

LOG: [clang] Fix a nullptr dereference bug on invalid code

When working with invalid code, we would try to dereference a nullptr
while deducing template arguments in some dependend code operating on a
lambda with invalid return type.

Differential Revision: https://reviews.llvm.org/D95145

Added: 
clang/test/SemaCXX/subst-func-type-invalid-ret-type.cpp

Modified: 
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index d3d6df5e0064..dc1e0ef60cac 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4189,6 +4189,9 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl 
*D,
   for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc.getNumParams();
OldIdx != NumOldParams; ++OldIdx) {
 ParmVarDecl *OldParam = OldProtoLoc.getParam(OldIdx);
+if (!OldParam)
+  return nullptr;
+
 LocalInstantiationScope *Scope = SemaRef.CurrentInstantiationScope;
 
 Optional NumArgumentsInExpansion;

diff  --git a/clang/test/SemaCXX/subst-func-type-invalid-ret-type.cpp 
b/clang/test/SemaCXX/subst-func-type-invalid-ret-type.cpp
new file mode 100644
index ..c783ff50
--- /dev/null
+++ b/clang/test/SemaCXX/subst-func-type-invalid-ret-type.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang -fsyntax-only -std=c++17 %s -Xclang -verify
+
+// The important part is that we do not crash.
+
+template T declval();
+
+template 
+auto Call(T x) -> decltype(declval()(0)) {} // expected-note{{candidate 
template ignored}}
+
+class Status {};
+
+void fun() {
+  // The Status() (instead of Status) here used to cause a crash.
+  Call([](auto x) -> Status() {}); // expected-error{{function cannot return 
function type 'Status ()}}
+  // expected-error@-1{{no matching function for call to 'Call'}}
+}



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


[clang] a6f9077 - [clang] Check for nullptr when instantiating late attrs

2021-01-19 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-01-19T13:43:15+01:00
New Revision: a6f9077b16da90204b296acd4f840769e83460ac

URL: 
https://github.com/llvm/llvm-project/commit/a6f9077b16da90204b296acd4f840769e83460ac
DIFF: 
https://github.com/llvm/llvm-project/commit/a6f9077b16da90204b296acd4f840769e83460ac.diff

LOG: [clang] Check for nullptr when instantiating late attrs

This was already done in SemaTemplateInstantiateDecl.cpp, but not in
SemaTemplateInstantiate.cpp.

Anecdotally I've seen some clangd crashes where coredumps point to this
being a problem, but I cannot reproduce this so far.

Differential Revision: https://reviews.llvm.org/D94933

Added: 


Modified: 
clang/lib/Sema/SemaTemplateInstantiate.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index cb74f08830c8..7679063ead71 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2796,7 +2796,8 @@ Sema::InstantiateClass(SourceLocation 
PointOfInstantiation,
 
 Attr *NewAttr =
   instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs);
-I->NewDecl->addAttr(NewAttr);
+if (NewAttr)
+  I->NewDecl->addAttr(NewAttr);
 LocalInstantiationScope::deleteScopes(I->Scope,
   Instantiator.getStartingScope());
   }



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


[clang] 196cc96 - [clang] Allow LifetimeExtendedTemporary to have no access specifier

2021-01-18 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-01-18T19:19:57+01:00
New Revision: 196cc96f9a643d1cb828f48ef15ec30d0de24df7

URL: 
https://github.com/llvm/llvm-project/commit/196cc96f9a643d1cb828f48ef15ec30d0de24df7
DIFF: 
https://github.com/llvm/llvm-project/commit/196cc96f9a643d1cb828f48ef15ec30d0de24df7.diff

LOG: [clang] Allow LifetimeExtendedTemporary to have no access specifier

The check only runs in debug mode during serialization, but
assert()-fail on:
  struct S { const int& x = 7; };
in C++ mode.

Differential Revision: https://reviews.llvm.org/D94804

Added: 


Modified: 
clang/lib/AST/DeclBase.cpp
clang/test/PCH/cxx-reference.h

Removed: 




diff  --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 0656efae5489..dc59f3dd1f15 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -971,21 +971,19 @@ bool Decl::AccessDeclContextSanity() const {
   // 5. it's invalid
   // 6. it's a C++0x static_assert.
   // 7. it's a block literal declaration
-  if (isa(this) ||
-  isa(this) ||
-  isa(this) ||
-  !getDeclContext() ||
-  !isa(getDeclContext()) ||
-  isInvalidDecl() ||
-  isa(this) ||
-  isa(this) ||
+  // 8. it's a temporary with lifetime extended due to being default value.
+  if (isa(this) || isa(this) ||
+  isa(this) || !getDeclContext() ||
+  !isa(getDeclContext()) || isInvalidDecl() ||
+  isa(this) || isa(this) ||
   // FIXME: a ParmVarDecl can have ClassTemplateSpecialization
   // as DeclContext (?).
   isa(this) ||
   // FIXME: a ClassTemplateSpecialization or CXXRecordDecl can have
   // AS_none as access specifier.
   isa(this) ||
-  isa(this))
+  isa(this) ||
+  isa(this))
 return true;
 
   assert(Access != AS_none &&

diff  --git a/clang/test/PCH/cxx-reference.h b/clang/test/PCH/cxx-reference.h
index b46a3671a325..a65d3feee072 100644
--- a/clang/test/PCH/cxx-reference.h
+++ b/clang/test/PCH/cxx-reference.h
@@ -11,3 +11,7 @@ LR &lrlr = c;
 LR &&rrlr = c;
 RR &lrrr = c;
 RR && = 'c';
+
+struct S {
+  const int &x = 1; // LifetimeExtendedTemporary inside struct
+};



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


[clang-tools-extra] c77c3d1 - [clangd] Set correct CWD when using compile_flags.txt

2021-01-15 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-01-15T14:26:24+01:00
New Revision: c77c3d1d18cdd58989f9d35bbf6c31f5fda0a125

URL: 
https://github.com/llvm/llvm-project/commit/c77c3d1d18cdd58989f9d35bbf6c31f5fda0a125
DIFF: 
https://github.com/llvm/llvm-project/commit/c77c3d1d18cdd58989f9d35bbf6c31f5fda0a125.diff

LOG: [clangd] Set correct CWD when using compile_flags.txt

This fixes a bug where clangd would attempt to set CWD to the
compile_flags.txt file itself.

Differential Revision: https://reviews.llvm.org/D94699

Added: 


Modified: 
clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp 
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index d983f76e227f..fde4e56ac72d 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -271,7 +271,8 @@ parseJSON(PathRef Path, llvm::StringRef Data, std::string 
&Error) {
 }
 static std::unique_ptr
 parseFixed(PathRef Path, llvm::StringRef Data, std::string &Error) {
-  return tooling::FixedCompilationDatabase::loadFromBuffer(Path, Data, Error);
+  return tooling::FixedCompilationDatabase::loadFromBuffer(
+  llvm::sys::path::parent_path(Path), Data, Error);
 }
 
 bool DirectoryBasedGlobalCompilationDatabase::DirectoryCache::load(

diff  --git 
a/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp 
b/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp
index 63b1b731656a..fbb85684af5f 100644
--- a/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp
+++ b/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp
@@ -279,6 +279,17 @@ TEST(GlobalCompilationDatabaseTest, BuildDir) {
   << "x/build/compile_flags.json only applicable to x/";
 }
 
+TEST(GlobalCompilationDatabaseTest, CompileFlagsDirectory) {
+  MockFS FS;
+  FS.Files[testPath("x/compile_flags.txt")] = "-DFOO";
+  DirectoryBasedGlobalCompilationDatabase CDB(FS);
+  auto Commands = CDB.getCompileCommand(testPath("x/y.cpp"));
+  ASSERT_TRUE(Commands.hasValue());
+  EXPECT_THAT(Commands.getValue().CommandLine, Contains("-DFOO"));
+  // Make sure we pick the right working directory.
+  EXPECT_EQ(testPath("x"), Commands.getValue().Directory);
+}
+
 TEST(GlobalCompilationDatabaseTest, NonCanonicalFilenames) {
   OverlayCDB DB(nullptr);
   std::vector DiscoveredFiles;



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


[clang-tools-extra] aeaeb9e - [clangd] Make ExpandAutoType not available on template params.

2021-01-15 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-01-15T14:19:05+01:00
New Revision: aeaeb9e6bdc90d9c4b839ac0e4edc6255021cced

URL: 
https://github.com/llvm/llvm-project/commit/aeaeb9e6bdc90d9c4b839ac0e4edc6255021cced
DIFF: 
https://github.com/llvm/llvm-project/commit/aeaeb9e6bdc90d9c4b839ac0e4edc6255021cced.diff

LOG: [clangd] Make ExpandAutoType not available on template params.

We cannot expand auto when used inside a template param (C++17 feature),
so do not offer it there.

Differential Revision: https://reviews.llvm.org/D94719

Added: 


Modified: 
clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp
clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp 
b/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp
index cb87cc764bc3..3776e1c3505d 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp
@@ -82,6 +82,15 @@ bool isDeducedAsLambda(const SelectionTree::Node *Node, 
SourceLocation Loc) {
   return false;
 }
 
+// Returns true iff "auto" in Node is really part of the template parameter,
+// which we cannot expand.
+bool isTemplateParam(const SelectionTree::Node *Node) {
+  if (Node->Parent)
+if (Node->Parent->ASTNode.get())
+  return true;
+  return false;
+}
+
 bool ExpandAutoType::prepare(const Selection& Inputs) {
   CachedLocation = llvm::None;
   if (auto *Node = Inputs.ASTSelection.commonAncestor()) {
@@ -90,7 +99,8 @@ bool ExpandAutoType::prepare(const Selection& Inputs) {
 // Code in apply() does handle 'decltype(auto)' yet.
 if (!Result.getTypePtr()->isDecltypeAuto() &&
 !isStructuredBindingType(Node) &&
-!isDeducedAsLambda(Node, Result.getBeginLoc()))
+!isDeducedAsLambda(Node, Result.getBeginLoc()) &&
+!isTemplateParam(Node))
   CachedLocation = Result;
   }
 }

diff  --git a/clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp 
b/clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
index 6c96ecc2332f..5554b68b31c7 100644
--- a/clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
+++ b/clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
@@ -80,6 +80,9 @@ TEST_F(ExpandAutoTypeTest, Test) {
   // unknown types in a template should not be replaced
   EXPECT_THAT(apply("template  void x() { ^auto y = T::z(); }"),
   StartsWith("fail: Could not deduce type for 'auto' type"));
+
+  ExtraArgs.push_back("-std=c++17");
+  EXPECT_UNAVAILABLE("template  class Y;");
 }
 
 } // namespace



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


[clang] a71877e - [clang] Do not crash when CXXRecordDecl has a non-CXXRecordDecl base.

2021-01-14 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-01-14T21:20:06+01:00
New Revision: a71877edfbb7094584f6d20d93f6091e7d374024

URL: 
https://github.com/llvm/llvm-project/commit/a71877edfbb7094584f6d20d93f6091e7d374024
DIFF: 
https://github.com/llvm/llvm-project/commit/a71877edfbb7094584f6d20d93f6091e7d374024.diff

LOG: [clang] Do not crash when CXXRecordDecl has a non-CXXRecordDecl base.

This can happen on some invalid code, like the included test case.

Differential Revision: https://reviews.llvm.org/D94704

Added: 


Modified: 
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/SemaTemplate/temp_class_spec.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 27679ac6f8d3..8bfaa46162bc 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5520,8 +5520,9 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Bases.
   for (const auto &Base : ClassDecl->bases()) {
-// Bases are always records in a well-formed non-dependent class.
 const RecordType *RT = Base.getType()->getAs();
+if (!RT)
+  continue;
 
 // Remember direct virtual bases.
 if (Base.isVirtual()) {

diff  --git a/clang/test/SemaTemplate/temp_class_spec.cpp 
b/clang/test/SemaTemplate/temp_class_spec.cpp
index 8a07fd7292c2..f92c52e9624e 100644
--- a/clang/test/SemaTemplate/temp_class_spec.cpp
+++ b/clang/test/SemaTemplate/temp_class_spec.cpp
@@ -361,3 +361,17 @@ namespace PR6181 {
   };
   
 }
+
+// Check that we do not crash on invalid code that leads to invalid base.
+namespace {
+template 
+class Foo {};
+
+template 
+class Bar;
+
+template 
+class Bar<0> : public Foo { // expected-error{{partial specialization of 
'Bar' does not use any of its template parameters}}
+  Bar() : Foo() {}
+};
+} // namespace



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


[clang-tools-extra] 2e1bb79 - [clangd] Add missing "override" to fix the build.

2021-01-08 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-01-08T17:24:47+01:00
New Revision: 2e1bb7940a4ddc847cebd25092d10f40866a7fad

URL: 
https://github.com/llvm/llvm-project/commit/2e1bb7940a4ddc847cebd25092d10f40866a7fad
DIFF: 
https://github.com/llvm/llvm-project/commit/2e1bb7940a4ddc847cebd25092d10f40866a7fad.diff

LOG: [clangd] Add missing "override" to fix the build.

Follow-up to d4af86581e80ef0f7a6f4a4fff1c97260a726e71

Differential Revision: https://reviews.llvm.org/D94314

Added: 


Modified: 
clang-tools-extra/clangd/AST.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/AST.cpp 
b/clang-tools-extra/clangd/AST.cpp
index 16298f3e0326..8af4cbb19a3d 100644
--- a/clang-tools-extra/clangd/AST.cpp
+++ b/clang-tools-extra/clangd/AST.cpp
@@ -310,7 +310,7 @@ std::string printType(const QualType QT, const DeclContext 
&CurContext) {
   public:
 PrintCB(const DeclContext *CurContext) : CurContext(CurContext) {}
 virtual ~PrintCB() {}
-virtual bool isScopeVisible(const DeclContext *DC) const {
+virtual bool isScopeVisible(const DeclContext *DC) const override {
   return DC->Encloses(CurContext);
 }
 



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


[clang] d4af865 - [clangd] Fix type printing in the presence of qualifiers

2021-01-08 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2021-01-08T17:00:39+01:00
New Revision: d4af86581e80ef0f7a6f4a4fff1c97260a726e71

URL: 
https://github.com/llvm/llvm-project/commit/d4af86581e80ef0f7a6f4a4fff1c97260a726e71
DIFF: 
https://github.com/llvm/llvm-project/commit/d4af86581e80ef0f7a6f4a4fff1c97260a726e71.diff

LOG: [clangd] Fix type printing in the presence of qualifiers

When printing QualType with qualifiers like "const", or pointing to an
elaborated type, we would print garbage like:
  std::const std::vector&
with the initial std:: being calculated correctly, but inserted in the
wrong place and the second std:: not removed (due to elaborated type).

This affected, among others, ExtractFunction and ExpandAuto tweaks.

This change introduces a new callback to PrintingPolicy, which allows us
to influence the printing of namespace qualifiers. In the future, the
same callback can be used to improve handling of "using namespace"
directives as well.

Fixes:
  https://github.com/clangd/clangd/issues/640 (ExtractFunction)
  https://github.com/clangd/clangd/issues/264 (ExpandAuto)
  First point of https://github.com/clangd/clangd/issues/524

Differential Revision: https://reviews.llvm.org/D94259

Added: 


Modified: 
clang-tools-extra/clangd/AST.cpp
clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
clang-tools-extra/clangd/unittests/tweaks/ExtractFunctionTests.cpp
clang/include/clang/AST/PrettyPrinter.h
clang/lib/AST/TypePrinter.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/AST.cpp 
b/clang-tools-extra/clangd/AST.cpp
index 39ab48843b28..16298f3e0326 100644
--- a/clang-tools-extra/clangd/AST.cpp
+++ b/clang-tools-extra/clangd/AST.cpp
@@ -299,19 +299,27 @@ SymbolID getSymbolID(const llvm::StringRef MacroName, 
const MacroInfo *MI,
   return SymbolID(USR);
 }
 
-// FIXME: This should be handled while printing underlying decls instead.
 std::string printType(const QualType QT, const DeclContext &CurContext) {
   std::string Result;
   llvm::raw_string_ostream OS(Result);
-  auto Decls =
-  explicitReferenceTargets(DynTypedNode::create(QT), DeclRelation::Alias);
-  if (!Decls.empty())
-OS << getQualification(CurContext.getParentASTContext(), &CurContext,
-   Decls.front(),
-   
/*VisibleNamespaces=*/llvm::ArrayRef{});
   PrintingPolicy PP(CurContext.getParentASTContext().getPrintingPolicy());
-  PP.SuppressScope = true;
   PP.SuppressTagKeyword = true;
+  PP.SuppressUnwrittenScope = true;
+
+  class PrintCB : public PrintingCallbacks {
+  public:
+PrintCB(const DeclContext *CurContext) : CurContext(CurContext) {}
+virtual ~PrintCB() {}
+virtual bool isScopeVisible(const DeclContext *DC) const {
+  return DC->Encloses(CurContext);
+}
+
+  private:
+const DeclContext *CurContext;
+  };
+  PrintCB PCB(&CurContext);
+  PP.Callbacks = &PCB;
+
   QT.print(OS, PP);
   return OS.str();
 }

diff  --git a/clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp 
b/clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
index ba783e551e84..6c96ecc2332f 100644
--- a/clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
+++ b/clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
@@ -65,6 +65,11 @@ TEST_F(ExpandAutoTypeTest, Test) {
   EXPECT_EQ(apply(R"cpp(au^to x = "test";)cpp"),
 R"cpp(const char * x = "test";)cpp");
 
+  EXPECT_EQ(apply("ns::Class * foo() { au^to c = foo(); }"),
+"ns::Class * foo() { ns::Class * c = foo(); }");
+  EXPECT_EQ(apply("void ns::Func() { au^to x = new ns::Class::Nested{}; }"),
+"void ns::Func() { Class::Nested * x = new ns::Class::Nested{}; 
}");
+
   EXPECT_UNAVAILABLE("dec^ltype(au^to) x = 10;");
   // expanding types in structured bindings is syntactically invalid.
   EXPECT_UNAVAILABLE("const ^auto &[x,y] = (int[]){1,2};");

diff  --git 
a/clang-tools-extra/clangd/unittests/tweaks/ExtractFunctionTests.cpp 
b/clang-tools-extra/clangd/unittests/tweaks/ExtractFunctionTests.cpp
index 2033b479896b..94cc4b0a0d84 100644
--- a/clang-tools-extra/clangd/unittests/tweaks/ExtractFunctionTests.cpp
+++ b/clang-tools-extra/clangd/unittests/tweaks/ExtractFunctionTests.cpp
@@ -97,6 +97,22 @@ void f(const int c) {
 })cpp";
   EXPECT_EQ(apply(ConstCheckInput), ConstCheckOutput);
 
+  // Check const qualifier with namespace
+  std::string ConstNamespaceCheckInput = R"cpp(
+namespace X { struct Y { int z; }; }
+int f(const X::Y &y) {
+  [[return y.z + y.z;]]
+})cpp";
+  std::string ConstNamespaceCheckOutput = R"cpp(
+namespace X { struct Y { int z; }; }
+int extracted(const X::Y &y) {
+return y.z + y.z;
+}
+int f(const X::Y &y) {
+  return extracted(y);
+})cpp";
+  EXPECT_EQ(apply(ConstNamespaceCheckInput), ConstNamespaceCheckOutput);
+
   // Don't extract when we need to make a function as a parameter.
   EXPECT_THAT(apply("void f() {

[clang-tools-extra] 0999408 - [clangd] Add error handling (elog) in code completion.

2020-12-28 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-12-28T15:22:54+01:00
New Revision: 0999408aea79dd69f182cfcb618006f6cf2b6d4e

URL: 
https://github.com/llvm/llvm-project/commit/0999408aea79dd69f182cfcb618006f6cf2b6d4e
DIFF: 
https://github.com/llvm/llvm-project/commit/0999408aea79dd69f182cfcb618006f6cf2b6d4e.diff

LOG: [clangd] Add error handling (elog) in code completion.

Differential Revision: https://reviews.llvm.org/D93220

Added: 


Modified: 
clang-tools-extra/clangd/CodeComplete.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/CodeComplete.cpp 
b/clang-tools-extra/clangd/CodeComplete.cpp
index cc6b5dbc9904..ebdbd56c286a 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -182,12 +182,18 @@ struct CompletionCandidate {
 // strings (literal or URI) mapping to the same file. We still want to
 // bundle those, so we must resolve the header to be included here.
 std::string HeaderForHash;
-if (Inserter)
-  if (auto Header = headerToInsertIfAllowed(Opts))
-if (auto HeaderFile = toHeaderFile(*Header, FileName))
+if (Inserter) {
+  if (auto Header = headerToInsertIfAllowed(Opts)) {
+if (auto HeaderFile = toHeaderFile(*Header, FileName)) {
   if (auto Spelled =
   Inserter->calculateIncludePath(*HeaderFile, FileName))
 HeaderForHash = *Spelled;
+} else {
+  vlog("Code completion header path manipulation failed {0}",
+   HeaderFile.takeError());
+}
+  }
+}
 
 llvm::SmallString<256> Scratch;
 if (IndexResult) {



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


[clang-tools-extra] 3c5bed7 - [clangd] ExpandAutoType: Do not offer code action on lambdas.

2020-12-08 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-12-08T20:03:16+01:00
New Revision: 3c5bed734f9e02bd3bc4fbd1e0acc53506823ebf

URL: 
https://github.com/llvm/llvm-project/commit/3c5bed734f9e02bd3bc4fbd1e0acc53506823ebf
DIFF: 
https://github.com/llvm/llvm-project/commit/3c5bed734f9e02bd3bc4fbd1e0acc53506823ebf.diff

LOG: [clangd] ExpandAutoType: Do not offer code action on lambdas.

We can't expand lambda types anyway. Now we simply not offer the code
action instead of showing it and then returning an error in apply().

Differential Revision: https://reviews.llvm.org/D92847

Added: 


Modified: 
clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp
clang-tools-extra/clangd/test/check-fail.test
clang-tools-extra/clangd/unittests/TweakTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp 
b/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp
index 61f68a688252..6d38eb1de82a 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp
@@ -63,6 +63,25 @@ bool isStructuredBindingType(const SelectionTree::Node *N) {
   return N && N->ASTNode.get();
 }
 
+// Returns true iff Node is a lambda, and thus should not be expanded. Loc is
+// the location of the auto type.
+bool isDeducedAsLambda(const SelectionTree::Node *Node, SourceLocation Loc) {
+  // getDeducedType() does a traversal, which we want to avoid in prepare().
+  // But at least check this isn't auto x = []{...};, which can't ever be
+  // expanded.
+  // (It would be nice if we had an efficient getDeducedType(), instead).
+  for (const auto *It = Node; It; It = It->Parent) {
+if (const auto *DD = It->ASTNode.get()) {
+  if (DD->getTypeSourceInfo() &&
+  DD->getTypeSourceInfo()->getTypeLoc().getBeginLoc() == Loc) {
+if (auto *RD = DD->getType()->getAsRecordDecl())
+  return RD->isLambda();
+  }
+}
+  }
+  return false;
+}
+
 bool ExpandAutoType::prepare(const Selection& Inputs) {
   CachedLocation = llvm::None;
   if (auto *Node = Inputs.ASTSelection.commonAncestor()) {
@@ -70,11 +89,13 @@ bool ExpandAutoType::prepare(const Selection& Inputs) {
   if (const AutoTypeLoc Result = TypeNode->getAs()) {
 // Code in apply() does handle 'decltype(auto)' yet.
 if (!Result.getTypePtr()->isDecltypeAuto() &&
-!isStructuredBindingType(Node))
+!isStructuredBindingType(Node) &&
+!isDeducedAsLambda(Node, Result.getBeginLoc()))
   CachedLocation = Result;
   }
 }
   }
+
   return (bool) CachedLocation;
 }
 

diff  --git a/clang-tools-extra/clangd/test/check-fail.test 
b/clang-tools-extra/clangd/test/check-fail.test
index 0ee777f02cc5..dd50b59b2c79 100644
--- a/clang-tools-extra/clangd/test/check-fail.test
+++ b/clang-tools-extra/clangd/test/check-fail.test
@@ -11,4 +11,5 @@
 // CHECK: All checks completed, 2 errors
 
 #include "missing.h"
-auto x = []{};
+void fun();
+auto x = fun;

diff  --git a/clang-tools-extra/clangd/unittests/TweakTests.cpp 
b/clang-tools-extra/clangd/unittests/TweakTests.cpp
index 85edd92d27da..0dcf8feb786f 100644
--- a/clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ b/clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -559,8 +559,7 @@ TEST_F(ExpandAutoTypeTest, Test) {
   EXPECT_THAT(apply("au^to x = &ns::Func;"),
   StartsWith("fail: Could not expand type of function pointer"));
   // lambda types are not replaced
-  EXPECT_THAT(apply("au^to x = []{};"),
-  StartsWith("fail: Could not expand type of lambda expression"));
+  EXPECT_UNAVAILABLE("au^to x = []{};");
   // inline namespaces
   EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
 "Visible x = inl_ns::Visible();");



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


[clang-tools-extra] f6b205d - [clangd] ExtractFunction: disable on regions that sometimes, but not always return.

2020-12-08 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-12-08T15:55:32+01:00
New Revision: f6b205dae16392382324fbca676ef6afe3920642

URL: 
https://github.com/llvm/llvm-project/commit/f6b205dae16392382324fbca676ef6afe3920642
DIFF: 
https://github.com/llvm/llvm-project/commit/f6b205dae16392382324fbca676ef6afe3920642.diff

LOG: [clangd] ExtractFunction: disable on regions that sometimes, but not 
always return.

apply() will fail in those cases, so it's better to detect it in
prepare() already and hide code action from the user.

This was especially annoying on code bases that use a lot of
RETURN_IF_ERROR-like macros.

Differential Revision: https://reviews.llvm.org/D92408

Added: 


Modified: 
clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
clang-tools-extra/clangd/unittests/TweakTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp 
b/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
index 18fe7bf39160..8eec42876d6b 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
@@ -708,6 +708,27 @@ tooling::Replacement createFunctionDefinition(const 
NewFunction &ExtractedFunc,
   return tooling::Replacement(SM, ExtractedFunc.InsertionPoint, 0, 
FunctionDef);
 }
 
+// Returns true if ExtZone contains any ReturnStmts.
+bool hasReturnStmt(const ExtractionZone &ExtZone) {
+  class ReturnStmtVisitor
+  : public clang::RecursiveASTVisitor {
+  public:
+bool VisitReturnStmt(ReturnStmt *Return) {
+  Found = true;
+  return false; // We found the answer, abort the scan.
+}
+bool Found = false;
+  };
+
+  ReturnStmtVisitor V;
+  for (const Stmt *RootStmt : ExtZone.RootStmts) {
+V.TraverseStmt(const_cast(RootStmt));
+if (V.Found)
+  break;
+  }
+  return V.Found;
+}
+
 bool ExtractFunction::prepare(const Selection &Inputs) {
   const LangOptions &LangOpts = Inputs.AST->getLangOpts();
   if (!LangOpts.CPlusPlus)
@@ -715,8 +736,12 @@ bool ExtractFunction::prepare(const Selection &Inputs) {
   const Node *CommonAnc = Inputs.ASTSelection.commonAncestor();
   const SourceManager &SM = Inputs.AST->getSourceManager();
   auto MaybeExtZone = findExtractionZone(CommonAnc, SM, LangOpts);
+  if (!MaybeExtZone ||
+  (hasReturnStmt(*MaybeExtZone) && !alwaysReturns(*MaybeExtZone)))
+return false;
+
   // FIXME: Get rid of this check once we support hoisting.
-  if (!MaybeExtZone || MaybeExtZone->requiresHoisting(SM))
+  if (MaybeExtZone->requiresHoisting(SM))
 return false;
 
   ExtZone = std::move(*MaybeExtZone);

diff  --git a/clang-tools-extra/clangd/unittests/TweakTests.cpp 
b/clang-tools-extra/clangd/unittests/TweakTests.cpp
index 07f061b3f2e3..85edd92d27da 100644
--- a/clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ b/clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -607,7 +607,11 @@ TEST_F(ExtractFunctionTest, FunctionTest) {
   // Extract certain return
   EXPECT_THAT(apply(" if(true) [[{ return; }]] "), HasSubstr("extracted"));
   // Don't extract uncertain return
-  EXPECT_THAT(apply(" if(true) [[if (false) return;]] "), StartsWith("fail"));
+  EXPECT_THAT(apply(" if(true) [[if (false) return;]] "),
+  StartsWith("unavailable"));
+  EXPECT_THAT(
+  apply("#define RETURN_IF_ERROR(x) if (x) return\nRETU^RN_IF_ERROR(4);"),
+  StartsWith("unavailable"));
 
   FileName = "a.c";
   EXPECT_THAT(apply(" for([[int i = 0;]];);"), HasSubstr("unavailable"));



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


[clang-tools-extra] c282b7d - [clangd] AddUsing: Fix a crash on ElaboratedTypes without NestedNameSpecfiiers.

2020-12-03 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-12-03T20:25:38+01:00
New Revision: c282b7de5a5de8151a19228702867e2299f1d3fe

URL: 
https://github.com/llvm/llvm-project/commit/c282b7de5a5de8151a19228702867e2299f1d3fe
DIFF: 
https://github.com/llvm/llvm-project/commit/c282b7de5a5de8151a19228702867e2299f1d3fe.diff

LOG: [clangd] AddUsing: Fix a crash on ElaboratedTypes without 
NestedNameSpecfiiers.

Differential Revision: https://reviews.llvm.org/D92579

Added: 


Modified: 
clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
clang-tools-extra/clangd/unittests/TweakTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp 
b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
index b00c2716005c7..d6a57efeeef13 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
@@ -274,6 +274,8 @@ bool AddUsing::prepare(const Selection &Inputs) {
   } else if (auto *T = Node->ASTNode.get()) {
 if (auto E = T->getAs()) {
   QualifierToRemove = E.getQualifierLoc();
+  if (!QualifierToRemove)
+return false;
 
   auto SpelledTokens =
   TB.spelledForExpanded(TB.expandedTokens(E.getSourceRange()));

diff  --git a/clang-tools-extra/clangd/unittests/TweakTests.cpp 
b/clang-tools-extra/clangd/unittests/TweakTests.cpp
index eefc50d754e2a..07f061b3f2e39 100644
--- a/clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ b/clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -2523,6 +2523,9 @@ class cc {
   // Do not offer code action on typo-corrections.
   EXPECT_UNAVAILABLE(Header + "/*error-ok*/c^c C;");
 
+  // NestedNameSpecifier, but no namespace.
+  EXPECT_UNAVAILABLE(Header + "class Foo {}; class F^oo foo;");
+
   // Check that we do not trigger in header files.
   FileName = "test.h";
   ExtraArgs.push_back("-xc++-header"); // .h file is treated a C by default.



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


[clang-tools-extra] 517828a - [clangd] Bundle code completion items when the include paths differ, but resolve to the same file.

2020-12-03 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-12-03T16:33:15+01:00
New Revision: 517828a31b0d1b7cfd1fd261046746bd8778420a

URL: 
https://github.com/llvm/llvm-project/commit/517828a31b0d1b7cfd1fd261046746bd8778420a
DIFF: 
https://github.com/llvm/llvm-project/commit/517828a31b0d1b7cfd1fd261046746bd8778420a.diff

LOG: [clangd] Bundle code completion items when the include paths differ, but 
resolve to the same file.

This can happen when, for example, merging results from an external
index that generates IncludeHeaders with full URI rather than just
literal include.

Differential Revision: https://reviews.llvm.org/D92494

Added: 


Modified: 
clang-tools-extra/clangd/CodeComplete.cpp
clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/CodeComplete.cpp 
b/clang-tools-extra/clangd/CodeComplete.cpp
index 1d85439f53af..cc6b5dbc9904 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -173,9 +173,22 @@ struct CompletionCandidate {
 
   // Returns a token identifying the overload set this is part of.
   // 0 indicates it's not part of any overload set.
-  size_t overloadSet(const CodeCompleteOptions &Opts) const {
+  size_t overloadSet(const CodeCompleteOptions &Opts, llvm::StringRef FileName,
+ IncludeInserter *Inserter) const {
 if (!Opts.BundleOverloads.getValueOr(false))
   return 0;
+
+// Depending on the index implementation, we can see 
diff erent header
+// strings (literal or URI) mapping to the same file. We still want to
+// bundle those, so we must resolve the header to be included here.
+std::string HeaderForHash;
+if (Inserter)
+  if (auto Header = headerToInsertIfAllowed(Opts))
+if (auto HeaderFile = toHeaderFile(*Header, FileName))
+  if (auto Spelled =
+  Inserter->calculateIncludePath(*HeaderFile, FileName))
+HeaderForHash = *Spelled;
+
 llvm::SmallString<256> Scratch;
 if (IndexResult) {
   switch (IndexResult->SymInfo.Kind) {
@@ -192,7 +205,7 @@ struct CompletionCandidate {
 // This could break #include insertion.
 return llvm::hash_combine(
 (IndexResult->Scope + IndexResult->Name).toStringRef(Scratch),
-headerToInsertIfAllowed(Opts).getValueOr(""));
+HeaderForHash);
   default:
 return 0;
   }
@@ -206,8 +219,7 @@ struct CompletionCandidate {
 llvm::raw_svector_ostream OS(Scratch);
 D->printQualifiedName(OS);
   }
-  return llvm::hash_combine(Scratch,
-headerToInsertIfAllowed(Opts).getValueOr(""));
+  return llvm::hash_combine(Scratch, HeaderForHash);
 }
 assert(IdentifierResult);
 return 0;
@@ -1570,7 +1582,8 @@ class CodeCompleteFlow {
 assert(IdentifierResult);
 C.Name = IdentifierResult->Name;
   }
-  if (auto OverloadSet = C.overloadSet(Opts)) {
+  if (auto OverloadSet = C.overloadSet(
+  Opts, FileName, Inserter ? Inserter.getPointer() : nullptr)) {
 auto Ret = BundleLookup.try_emplace(OverloadSet, Bundles.size());
 if (Ret.second)
   Bundles.emplace_back();

diff  --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp 
b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index a7e1c6c48143..a19c6a83e954 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1628,6 +1628,29 @@ TEST(CompletionTest, OverloadBundling) {
   EXPECT_EQ(A.SnippetSuffix, "($0)");
 }
 
+TEST(CompletionTest, OverloadBundlingSameFileDifferentURI) {
+  clangd::CodeCompleteOptions Opts;
+  Opts.BundleOverloads = true;
+
+  Symbol SymX = sym("ns::X", index::SymbolKind::Function, "@F@\\0#");
+  Symbol SymY = sym("ns::X", index::SymbolKind::Function, "@F@\\0#I#");
+  std::string BarHeader = testPath("bar.h");
+  auto BarURI = URI::create(BarHeader).toString();
+  SymX.CanonicalDeclaration.FileURI = BarURI.c_str();
+  SymY.CanonicalDeclaration.FileURI = BarURI.c_str();
+  // The include header is 
diff erent, but really it's the same file.
+  SymX.IncludeHeaders.emplace_back("\"bar.h\"", 1);
+  SymY.IncludeHeaders.emplace_back(BarURI.c_str(), 1);
+
+  auto Results = completions("void f() { ::ns::^ }", {SymX, SymY}, Opts);
+  // Expect both results are bundled, despite the 
diff erent-but-same
+  // IncludeHeader.
+  ASSERT_EQ(1u, Results.Completions.size());
+  const auto &R = Results.Completions.front();
+  EXPECT_EQ("X", R.Name);
+  EXPECT_EQ(2u, R.BundleSize);
+}
+
 TEST(CompletionTest, DocumentationFromChangedFileCrash) {
   MockFS FS;
   auto FooH = testPath("foo.h");



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

[clang-tools-extra] 9d87739 - [clangd] AddUsing: do not crash on non-namespace using decls.

2020-11-26 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-11-26T20:07:56+01:00
New Revision: 9d87739f664b5b454ff78a3016ab05a1987f0d7c

URL: 
https://github.com/llvm/llvm-project/commit/9d87739f664b5b454ff78a3016ab05a1987f0d7c
DIFF: 
https://github.com/llvm/llvm-project/commit/9d87739f664b5b454ff78a3016ab05a1987f0d7c.diff

LOG: [clangd] AddUsing: do not crash on non-namespace using decls.

Differential Revision: https://reviews.llvm.org/D92186

Added: 


Modified: 
clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
clang-tools-extra/clangd/unittests/TweakTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp 
b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
index 4b3fbc02c411..b00c2716005c 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
@@ -152,12 +152,14 @@ findInsertionPoint(const Tweak::Selection &Inputs,
 if (SM.isBeforeInTranslationUnit(Inputs.Cursor, U->getUsingLoc()))
   // "Usings" is sorted, so we're done.
   break;
-if (U->getQualifier()->getAsNamespace()->getCanonicalDecl() ==
-QualifierToRemove.getNestedNameSpecifier()
-->getAsNamespace()
-->getCanonicalDecl() &&
-U->getName() == Name) {
-  return InsertionPointData();
+if (const auto *Namespace = U->getQualifier()->getAsNamespace()) {
+  if (Namespace->getCanonicalDecl() ==
+  QualifierToRemove.getNestedNameSpecifier()
+  ->getAsNamespace()
+  ->getCanonicalDecl() &&
+  U->getName() == Name) {
+return InsertionPointData();
+  }
 }
 
 // Insertion point will be before last UsingDecl that affects cursor

diff  --git a/clang-tools-extra/clangd/unittests/TweakTests.cpp 
b/clang-tools-extra/clangd/unittests/TweakTests.cpp
index 4a2360dda739..eefc50d754e2 100644
--- a/clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ b/clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -2884,6 +2884,17 @@ using xx::yy;
 void fun() {
   yy();
 }
+)cpp"},
+// Existing using with non-namespace part.
+{R"cpp(
+#include "test.hpp"
+using one::two::ee::ee_one;
+one::t^wo::cc c;
+)cpp",
+ R"cpp(
+#include "test.hpp"
+using one::two::cc;using one::two::ee::ee_one;
+cc c;
 )cpp"}};
   llvm::StringMap EditedFiles;
   for (const auto &Case : Cases) {
@@ -2892,7 +2903,7 @@ void fun() {
 namespace one {
 void oo() {}
 namespace two {
-enum ee {};
+enum ee {ee_one};
 void ff() {}
 class cc {
 public:



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


[clang-tools-extra] f697050 - [clangd] PopulateSwitch: disable on dependent enums.

2020-11-25 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-11-25T14:12:29+01:00
New Revision: f6970503d291b7cae70fe583bed392387f93f9e4

URL: 
https://github.com/llvm/llvm-project/commit/f6970503d291b7cae70fe583bed392387f93f9e4
DIFF: 
https://github.com/llvm/llvm-project/commit/f6970503d291b7cae70fe583bed392387f93f9e4.diff

LOG: [clangd] PopulateSwitch: disable on dependent enums.

If the enum is a dependent type, we would crash somewhere in
getIntWidth(). -Wswitch diagnostic doesn't work on dependent enums
either.

Differential Revision: https://reviews.llvm.org/D92051

Added: 


Modified: 
clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
clang-tools-extra/clangd/unittests/TweakTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp 
b/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
index 852888f6a043..bae80cdecf59 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
@@ -126,7 +126,7 @@ bool PopulateSwitch::prepare(const Selection &Sel) {
 return false;
 
   EnumD = EnumT->getDecl();
-  if (!EnumD)
+  if (!EnumD || EnumD->isDependentType())
 return false;
 
   // We trigger if there are any values in the enum that aren't covered by the

diff  --git a/clang-tools-extra/clangd/unittests/TweakTests.cpp 
b/clang-tools-extra/clangd/unittests/TweakTests.cpp
index fd815d2c4c27..4a2360dda739 100644
--- a/clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ b/clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -3084,6 +3084,12 @@ TEST_F(PopulateSwitchTest, Test) {
   R""(enum Enum {A,B,b=B}; ^switch (A) {case A:case B:break;})"",
   "unavailable",
   },
+  {
+  // Enum is dependent type
+  File,
+  R""(template void f() {enum Enum {A}; ^switch (A) {}})"",
+  "unavailable",
+  },
   };
 
   for (const auto &Case : Cases) {



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


[clang-tools-extra] a200501 - [clangd] Addusing tweak: find insertion point after definition

2020-11-24 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-11-24T22:57:02+01:00
New Revision: a200501bca4dc7f3292d824f249fa21a479e9873

URL: 
https://github.com/llvm/llvm-project/commit/a200501bca4dc7f3292d824f249fa21a479e9873
DIFF: 
https://github.com/llvm/llvm-project/commit/a200501bca4dc7f3292d824f249fa21a479e9873.diff

LOG: [clangd] Addusing tweak: find insertion point after definition

When type/function is defined in the middle of the file, previuosly we
would sometimes insert a "using" line before that definition, leading to
a compilation error. With this fix, we pick a point after such
definition in translation unit.

This is not a perfect solution. For example, it still doesn't handle
"using namespace" directives. It is, however, a significant improvement.

Differential Revision: https://reviews.llvm.org/D92053

Added: 


Modified: 
clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
clang-tools-extra/clangd/unittests/TweakTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp 
b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
index b53df446c732..4b3fbc02c411 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
@@ -48,6 +48,10 @@ class AddUsing : public Tweak {
   NestedNameSpecifierLoc QualifierToRemove;
   // The name following QualifierToRemove.
   llvm::StringRef Name;
+  // If valid, the insertion point for "using" statement must come after this.
+  // This is relevant when the type is defined in the main file, to make sure
+  // the type/function is already defined at the point where "using" is added.
+  SourceLocation MustInsertAfterLoc;
 };
 REGISTER_TWEAK(AddUsing)
 
@@ -120,7 +124,8 @@ struct InsertionPointData {
 llvm::Expected
 findInsertionPoint(const Tweak::Selection &Inputs,
const NestedNameSpecifierLoc &QualifierToRemove,
-   const llvm::StringRef Name) {
+   const llvm::StringRef Name,
+   const SourceLocation MustInsertAfterLoc) {
   auto &SM = Inputs.AST->getSourceManager();
 
   // Search for all using decls that affect this point in file. We need this 
for
@@ -132,6 +137,11 @@ findInsertionPoint(const Tweak::Selection &Inputs,
   SM)
   .TraverseAST(Inputs.AST->getASTContext());
 
+  auto IsValidPoint = [&](const SourceLocation Loc) {
+return MustInsertAfterLoc.isInvalid() ||
+   SM.isBeforeInTranslationUnit(MustInsertAfterLoc, Loc);
+  };
+
   bool AlwaysFullyQualify = true;
   for (auto &U : Usings) {
 // Only "upgrade" to fully qualified is all relevant using decls are fully
@@ -149,12 +159,13 @@ findInsertionPoint(const Tweak::Selection &Inputs,
 U->getName() == Name) {
   return InsertionPointData();
 }
+
 // Insertion point will be before last UsingDecl that affects cursor
 // position. For most cases this should stick with the local convention of
 // add using inside or outside namespace.
 LastUsingLoc = U->getUsingLoc();
   }
-  if (LastUsingLoc.isValid()) {
+  if (LastUsingLoc.isValid() && IsValidPoint(LastUsingLoc)) {
 InsertionPointData Out;
 Out.Loc = LastUsingLoc;
 Out.AlwaysFullyQualify = AlwaysFullyQualify;
@@ -175,7 +186,7 @@ findInsertionPoint(const Tweak::Selection &Inputs,
 if (Tok == Toks.end() || Tok->endLocation().isInvalid()) {
   return error("Namespace with no {");
 }
-if (!Tok->endLocation().isMacroID()) {
+if (!Tok->endLocation().isMacroID() && IsValidPoint(Tok->endLocation())) {
   InsertionPointData Out;
   Out.Loc = Tok->endLocation();
   Out.Suffix = "\n";
@@ -183,15 +194,17 @@ findInsertionPoint(const Tweak::Selection &Inputs,
 }
   }
   // No using, no namespace, no idea where to insert. Try above the first
-  // top level decl.
+  // top level decl after MustInsertAfterLoc.
   auto TLDs = Inputs.AST->getLocalTopLevelDecls();
-  if (TLDs.empty()) {
-return error("Cannot find place to insert \"using\"");
+  for (const auto &TLD : TLDs) {
+if (!IsValidPoint(TLD->getBeginLoc()))
+  continue;
+InsertionPointData Out;
+Out.Loc = SM.getExpansionLoc(TLD->getBeginLoc());
+Out.Suffix = "\n\n";
+return Out;
   }
-  InsertionPointData Out;
-  Out.Loc = SM.getExpansionLoc(TLDs[0]->getBeginLoc());
-  Out.Suffix = "\n\n";
-  return Out;
+  return error("Cannot find place to insert \"using\"");
 }
 
 bool isNamespaceForbidden(const Tweak::Selection &Inputs,
@@ -254,6 +267,7 @@ bool AddUsing::prepare(const Selection &Inputs) {
 if (auto *II = D->getDecl()->getIdentifier()) {
   QualifierToRemove = D->getQualifierLoc();
   Name = II->getName();
+  MustInsertAfterLoc = D->getDecl()->getBeginLoc();
 }
   } else if (auto *T = Node->ASTNode.get()) {
 if (auto E = T->getAs()) {
@@ -271,6 +285,15 @@ bool AddUsing::prepare(const Selection &Inputs) {

[clang-tools-extra] f6e5929 - [clangd] AddUsing: Used spelled text instead of type name.

2020-11-24 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-11-24T18:59:09+01:00
New Revision: f6e59294b63e1fd0b25720f24111cd17865004be

URL: 
https://github.com/llvm/llvm-project/commit/f6e59294b63e1fd0b25720f24111cd17865004be
DIFF: 
https://github.com/llvm/llvm-project/commit/f6e59294b63e1fd0b25720f24111cd17865004be.diff

LOG: [clangd] AddUsing: Used spelled text instead of type name.

This improves the behavior related to type aliases, as well as cases of
typo correction.

Differential Revision: https://reviews.llvm.org/D91966

Added: 


Modified: 
clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
clang-tools-extra/clangd/unittests/TweakTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp 
b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
index cf8347f312a3..b53df446c732 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
@@ -43,9 +43,10 @@ class AddUsing : public Tweak {
   }
 
 private:
-  // The qualifier to remove. Set by prepare().
+  // All of the following are set by prepare().
+  // The qualifier to remove.
   NestedNameSpecifierLoc QualifierToRemove;
-  // The name following QualifierToRemove. Set by prepare().
+  // The name following QualifierToRemove.
   llvm::StringRef Name;
 };
 REGISTER_TWEAK(AddUsing)
@@ -206,8 +207,17 @@ bool isNamespaceForbidden(const Tweak::Selection &Inputs,
   return false;
 }
 
+std::string getNNSLAsString(NestedNameSpecifierLoc &NNSL,
+const PrintingPolicy &Policy) {
+  std::string Out;
+  llvm::raw_string_ostream OutStream(Out);
+  NNSL.getNestedNameSpecifier()->print(OutStream, Policy);
+  return OutStream.str();
+}
+
 bool AddUsing::prepare(const Selection &Inputs) {
   auto &SM = Inputs.AST->getSourceManager();
+  const auto &TB = Inputs.AST->getTokens();
 
   // Do not suggest "using" in header files. That way madness lies.
   if (isHeaderFile(SM.getFileEntryForID(SM.getMainFileID())->getName(),
@@ -247,11 +257,20 @@ bool AddUsing::prepare(const Selection &Inputs) {
 }
   } else if (auto *T = Node->ASTNode.get()) {
 if (auto E = T->getAs()) {
-  if (auto *BaseTypeIdentifier =
-  E.getType().getUnqualifiedType().getBaseTypeIdentifier()) {
-Name = BaseTypeIdentifier->getName();
-QualifierToRemove = E.getQualifierLoc();
-  }
+  QualifierToRemove = E.getQualifierLoc();
+
+  auto SpelledTokens =
+  TB.spelledForExpanded(TB.expandedTokens(E.getSourceRange()));
+  if (!SpelledTokens)
+return false;
+  auto SpelledRange = syntax::Token::range(SM, SpelledTokens->front(),
+   SpelledTokens->back());
+  Name = SpelledRange.text(SM);
+
+  std::string QualifierToRemoveStr = getNNSLAsString(
+  QualifierToRemove, Inputs.AST->getASTContext().getPrintingPolicy());
+  if (!Name.consume_front(QualifierToRemoveStr))
+return false; // What's spelled doesn't match the qualifier.
 }
   }
 
@@ -283,20 +302,13 @@ bool AddUsing::prepare(const Selection &Inputs) {
 
 Expected AddUsing::apply(const Selection &Inputs) {
   auto &SM = Inputs.AST->getSourceManager();
-  auto &TB = Inputs.AST->getTokens();
 
-  // Determine the length of the qualifier under the cursor, then remove it.
-  auto SpelledTokens = TB.spelledForExpanded(
-  TB.expandedTokens(QualifierToRemove.getSourceRange()));
-  if (!SpelledTokens) {
-return error("Could not determine length of the qualifier");
-  }
-  unsigned Length =
-  syntax::Token::range(SM, SpelledTokens->front(), SpelledTokens->back())
-  .length();
+  std::string QualifierToRemoveStr = getNNSLAsString(
+  QualifierToRemove, Inputs.AST->getASTContext().getPrintingPolicy());
   tooling::Replacements R;
   if (auto Err = R.add(tooling::Replacement(
-  SM, SpelledTokens->front().location(), Length, ""))) {
+  SM, SM.getSpellingLoc(QualifierToRemove.getBeginLoc()),
+  QualifierToRemoveStr.length(), ""))) {
 return std::move(Err);
   }
 
@@ -313,9 +325,8 @@ Expected AddUsing::apply(const Selection 
&Inputs) {
 if (InsertionPoint->AlwaysFullyQualify &&
 !isFullyQualified(QualifierToRemove.getNestedNameSpecifier()))
   UsingTextStream << "::";
-QualifierToRemove.getNestedNameSpecifier()->print(
-UsingTextStream, Inputs.AST->getASTContext().getPrintingPolicy());
-UsingTextStream << Name << ";" << InsertionPoint->Suffix;
+UsingTextStream << QualifierToRemoveStr << Name << ";"
+<< InsertionPoint->Suffix;
 
 assert(SM.getFileID(InsertionPoint->Loc) == SM.getMainFileID());
 if (auto Err = R.add(tooling::Replacement(SM, InsertionPoint->Loc, 0,

diff  --git a/clang-tools-extra/clangd/unittests/TweakTests.cpp 
b/clang-tools-extra/clangd/unittests/TweakTests.cpp
index 98d797aacd8f..

[clang] 95ce9fb - [clang] Do not crash on pointer wchar_t pointer assignment.

2020-11-20 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-11-20T15:27:15+01:00
New Revision: 95ce9fbc235a467b84b2ffa2571f1d1a45af9427

URL: 
https://github.com/llvm/llvm-project/commit/95ce9fbc235a467b84b2ffa2571f1d1a45af9427
DIFF: 
https://github.com/llvm/llvm-project/commit/95ce9fbc235a467b84b2ffa2571f1d1a45af9427.diff

LOG: [clang] Do not crash on pointer wchar_t pointer assignment.

wchar_t can be signed (thus hasSignedIntegerRepresentation() returns
true), but it doesn't have an unsigned type, which would lead to a crash
when trying to get it.

With this fix, we special-case WideChar types in the pointer assignment
code.

Differential Revision: https://reviews.llvm.org/D91625

Added: 


Modified: 
clang/lib/AST/ASTContext.cpp
clang/test/SemaCXX/wchar_t.cpp

Removed: 




diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 836065291fea..f54916babed7 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -10007,6 +10007,11 @@ QualType 
ASTContext::getCorrespondingUnsignedType(QualType T) const {
 return UnsignedLongLongTy;
   case BuiltinType::Int128:
 return UnsignedInt128Ty;
+  // wchar_t is special. It is either signed or not, but when it's signed,
+  // there's no matching "unsigned wchar_t". Therefore we return the unsigned
+  // version of it's underlying type instead.
+  case BuiltinType::WChar_S:
+return getUnsignedWCharType();
 
   case BuiltinType::ShortAccum:
 return UnsignedShortAccumTy;

diff  --git a/clang/test/SemaCXX/wchar_t.cpp b/clang/test/SemaCXX/wchar_t.cpp
index f8e9addf27b7..cc7c6de7b37f 100644
--- a/clang/test/SemaCXX/wchar_t.cpp
+++ b/clang/test/SemaCXX/wchar_t.cpp
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
-// RUN: %clang_cc1 -fsyntax-only -Wno-signed-unsigned-wchar 
-verify=allow-signed %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-signed-unsigned-wchar 
-verify=allow-signed -DSKIP_ERROR_TESTS %s
 // allow-signed-no-diagnostics
 wchar_t x;
 
@@ -32,3 +32,10 @@ int t(void) {
 // rdar://8040728
 wchar_t in[] = L"\x434" "\x434";  // No warning
 
+#ifndef SKIP_ERROR_TESTS
+// Verify that we do not crash when assigning wchar_t* to another pointer type.
+void assignment(wchar_t *x) {
+  char *y;
+  y = x; // expected-error {{incompatible pointer types assigning to 'char *' 
from 'wchar_t *'}}
+}
+#endif



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


[clang-tools-extra] bcd8422 - [clangd] Fix argument type (bool->float).

2020-10-07 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-10-07T17:22:00+02:00
New Revision: bcd8422d75069624dc2daf7e5ff4b4f6cbcd6b71

URL: 
https://github.com/llvm/llvm-project/commit/bcd8422d75069624dc2daf7e5ff4b4f6cbcd6b71
DIFF: 
https://github.com/llvm/llvm-project/commit/bcd8422d75069624dc2daf7e5ff4b4f6cbcd6b71.diff

LOG: [clangd] Fix argument type (bool->float).

The default value is 1.3f, but it was cast to true, which is not a good
base for code completion score.

Differential Revision: https://reviews.llvm.org/D88970

Added: 


Modified: 
clang-tools-extra/clangd/tool/ClangdMain.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp 
b/clang-tools-extra/clangd/tool/ClangdMain.cpp
index 98daaf957359..78d8355a2c5d 100644
--- a/clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -185,7 +185,7 @@ opt 
RankingModel{
 Hidden,
 };
 
-opt DecisionForestBase{
+opt DecisionForestBase{
 "decision-forest-base",
 cat(Features),
 desc("Base for exponentiating the prediction from DecisionForest."),



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


[clang-tools-extra] c894bfd - [clangd] Add option for disabling AddUsing tweak on some namespaces.

2020-09-18 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-09-18T16:46:09+02:00
New Revision: c894bfd1f580e5807fc98cc353b0834e0c5ddc21

URL: 
https://github.com/llvm/llvm-project/commit/c894bfd1f580e5807fc98cc353b0834e0c5ddc21
DIFF: 
https://github.com/llvm/llvm-project/commit/c894bfd1f580e5807fc98cc353b0834e0c5ddc21.diff

LOG: [clangd] Add option for disabling AddUsing tweak on some namespaces.

For style guides forbid "using" declarations for namespaces like "std".
With this new config option, AddUsing can be selectively disabled on
those.

Differential Revision: https://reviews.llvm.org/D87775

Added: 


Modified: 
clang-tools-extra/clangd/Config.h
clang-tools-extra/clangd/ConfigCompile.cpp
clang-tools-extra/clangd/ConfigFragment.h
clang-tools-extra/clangd/ConfigYAML.cpp
clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
clang-tools-extra/clangd/unittests/TweakTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/Config.h 
b/clang-tools-extra/clangd/Config.h
index f8dc2df51814..087dc4fb805d 100644
--- a/clang-tools-extra/clangd/Config.h
+++ b/clang-tools-extra/clangd/Config.h
@@ -62,6 +62,14 @@ struct Config {
 /// Whether this TU should be indexed.
 BackgroundPolicy Background = BackgroundPolicy::Build;
   } Index;
+
+  /// Style of the codebase.
+  struct {
+// Namespaces that should always be fully qualified, meaning no "using"
+// declarations, always spell out the whole name (with or without leading
+// ::). All nested namespaces are affected as well.
+std::vector FullyQualifiedNamespaces;
+  } Style;
 };
 
 } // namespace clangd

diff  --git a/clang-tools-extra/clangd/ConfigCompile.cpp 
b/clang-tools-extra/clangd/ConfigCompile.cpp
index 9b8a48fdaf7b..62fda5c9eacc 100644
--- a/clang-tools-extra/clangd/ConfigCompile.cpp
+++ b/clang-tools-extra/clangd/ConfigCompile.cpp
@@ -208,6 +208,25 @@ struct FragmentCompiler {
 }
   }
 
+  void compile(Fragment::StyleBlock &&F) {
+if (!F.FullyQualifiedNamespaces.empty()) {
+  std::vector FullyQualifiedNamespaces;
+  for (auto &N : F.FullyQualifiedNamespaces) {
+// Normalize the data by dropping both leading and trailing ::
+StringRef Namespace(*N);
+Namespace.consume_front("::");
+Namespace.consume_back("::");
+FullyQualifiedNamespaces.push_back(Namespace.str());
+  }
+  Out.Apply.push_back([FullyQualifiedNamespaces(
+  std::move(FullyQualifiedNamespaces))](Config &C) 
{
+C.Style.FullyQualifiedNamespaces.insert(
+C.Style.FullyQualifiedNamespaces.begin(),
+FullyQualifiedNamespaces.begin(), FullyQualifiedNamespaces.end());
+  });
+}
+  }
+
   constexpr static llvm::SourceMgr::DiagKind Error = llvm::SourceMgr::DK_Error;
   constexpr static llvm::SourceMgr::DiagKind Warning =
   llvm::SourceMgr::DK_Warning;

diff  --git a/clang-tools-extra/clangd/ConfigFragment.h 
b/clang-tools-extra/clangd/ConfigFragment.h
index 330f157326f2..5b4865e48f3a 100644
--- a/clang-tools-extra/clangd/ConfigFragment.h
+++ b/clang-tools-extra/clangd/ConfigFragment.h
@@ -161,6 +161,16 @@ struct Fragment {
 llvm::Optional> Background;
   };
   IndexBlock Index;
+
+  // Describes the style of the codebase, beyond formatting.
+  struct StyleBlock {
+// Namespaces that should always be fully qualified, meaning no "using"
+// declarations, always spell out the whole name (with or without leading
+// ::). All nested namespaces are affected as well.
+// Affects availability of the AddUsing tweak.
+std::vector> FullyQualifiedNamespaces;
+  };
+  StyleBlock Style;
 };
 
 } // namespace config

diff  --git a/clang-tools-extra/clangd/ConfigYAML.cpp 
b/clang-tools-extra/clangd/ConfigYAML.cpp
index 9988fe376648..bc7d4fdfe85b 100644
--- a/clang-tools-extra/clangd/ConfigYAML.cpp
+++ b/clang-tools-extra/clangd/ConfigYAML.cpp
@@ -39,6 +39,7 @@ class Parser {
 Dict.handle("If", [&](Node &N) { parse(F.If, N); });
 Dict.handle("CompileFlags", [&](Node &N) { parse(F.CompileFlags, N); });
 Dict.handle("Index", [&](Node &N) { parse(F.Index, N); });
+Dict.handle("Style", [&](Node &N) { parse(F.Style, N); });
 Dict.parse(N);
 return !(N.failed() || HadError);
   }
@@ -72,6 +73,15 @@ class Parser {
 Dict.parse(N);
   }
 
+  void parse(Fragment::StyleBlock &F, Node &N) {
+DictParser Dict("Style", this);
+Dict.handle("FullyQualifiedNamespaces", [&](Node &N) {
+  if (auto Values = scalarValues(N))
+F.FullyQualifiedNamespaces = std::move(*Values);
+});
+Dict.parse(N);
+  }
+
   void parse(Fragment::IndexBlock &F, Node &N) {
 DictParser Dict("Index", this);
 Dict.handle("Background",

diff  --git a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp 
b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
index d5e6e12b31aa..8c69b64c5aff 100644
--- a/clang-tools-extra/clangd/

[clang-tools-extra] 7029e5d - [clangd] Actually parse Index section of the YAML file.

2020-09-16 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-09-16T13:11:02+02:00
New Revision: 7029e5d4ca20d20982da8efe89de27acd8d7d75b

URL: 
https://github.com/llvm/llvm-project/commit/7029e5d4ca20d20982da8efe89de27acd8d7d75b
DIFF: 
https://github.com/llvm/llvm-project/commit/7029e5d4ca20d20982da8efe89de27acd8d7d75b.diff

LOG: [clangd] Actually parse Index section of the YAML file.

This fixes a bug in dbf486c0de92c76df77c1a1f815cf16533ecbb3a, which
introduced the Index section of the config, but did not register the
parse method, so it didn't work in a YAML file (but did in a test).

Differential Revision: https://reviews.llvm.org/D87710

Added: 


Modified: 
clang-tools-extra/clangd/ConfigYAML.cpp
clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/ConfigYAML.cpp 
b/clang-tools-extra/clangd/ConfigYAML.cpp
index 16639f6649c2..9988fe376648 100644
--- a/clang-tools-extra/clangd/ConfigYAML.cpp
+++ b/clang-tools-extra/clangd/ConfigYAML.cpp
@@ -38,6 +38,7 @@ class Parser {
 DictParser Dict("Config", this);
 Dict.handle("If", [&](Node &N) { parse(F.If, N); });
 Dict.handle("CompileFlags", [&](Node &N) { parse(F.CompileFlags, N); });
+Dict.handle("Index", [&](Node &N) { parse(F.Index, N); });
 Dict.parse(N);
 return !(N.failed() || HadError);
   }

diff  --git a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp 
b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
index a9526ce2367c..27b1c0cfc56d 100644
--- a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
@@ -47,16 +47,21 @@ CompileFlags: { Add: [foo, bar] }
   Add: |
 b
 az
+---
+Index:
+  Background: Skip
   )yaml";
   auto Results = Fragment::parseYAML(YAML, "config.yaml", Diags.callback());
   EXPECT_THAT(Diags.Diagnostics, IsEmpty());
-  ASSERT_EQ(Results.size(), 2u);
-  EXPECT_FALSE(Results.front().If.HasUnrecognizedCondition);
-  EXPECT_THAT(Results.front().If.PathMatch, ElementsAre(Val("abc")));
-  EXPECT_THAT(Results.front().CompileFlags.Add,
-  ElementsAre(Val("foo"), Val("bar")));
+  ASSERT_EQ(Results.size(), 3u);
+  EXPECT_FALSE(Results[0].If.HasUnrecognizedCondition);
+  EXPECT_THAT(Results[0].If.PathMatch, ElementsAre(Val("abc")));
+  EXPECT_THAT(Results[0].CompileFlags.Add, ElementsAre(Val("foo"), 
Val("bar")));
+
+  EXPECT_THAT(Results[1].CompileFlags.Add, ElementsAre(Val("b\naz\n")));
 
-  EXPECT_THAT(Results.back().CompileFlags.Add, ElementsAre(Val("b\naz\n")));
+  ASSERT_TRUE(Results[2].Index.Background);
+  EXPECT_EQ("Skip", *Results[2].Index.Background.getValue());
 }
 
 TEST(ParseYAML, Locations) {



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


[clang] eed0af6 - [clang] Exclude invalid destructors from lookups.

2020-08-26 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-08-26T19:29:30+02:00
New Revision: eed0af6179ca4fe9e60121e0829ed8d3849b1ce5

URL: 
https://github.com/llvm/llvm-project/commit/eed0af6179ca4fe9e60121e0829ed8d3849b1ce5
DIFF: 
https://github.com/llvm/llvm-project/commit/eed0af6179ca4fe9e60121e0829ed8d3849b1ce5.diff

LOG: [clang] Exclude invalid destructors from lookups.

This fixes a crash when declaring a destructor with a wrong name, then
writing result to pch file and loading it again. The PCH storage uses
DeclarationNameKey as key and it is the same key for both the invalid
destructor and the implicit one that was created because the other one
was invalid. When querying for the Foo::~Foo we end up getting
Foo::~Bar, which is then rejected and we end up with nullptr in
CXXRecordDecl::GetDestructor().

Fixes https://bugs.llvm.org/show_bug.cgi?id=47270

Differential Revision: https://reviews.llvm.org/D86624

Added: 
clang/test/PCH/cxx-invalid-destructor.cpp
clang/test/PCH/cxx-invalid-destructor.h

Modified: 
clang/lib/AST/DeclBase.cpp

Removed: 




diff  --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index da1eadd9d931d..f4314d0bd9614 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -1487,6 +1487,13 @@ static bool shouldBeHidden(NamedDecl *D) {
 if (FD->isFunctionTemplateSpecialization())
   return true;
 
+  // Hide destructors that are invalid. There should always be one destructor,
+  // but if it is an invalid decl, another one is created. We need to hide the
+  // invalid one from places that expect exactly one destructor, like the
+  // serialization code.
+  if (isa(D) && D->isInvalidDecl())
+return true;
+
   return false;
 }
 

diff  --git a/clang/test/PCH/cxx-invalid-destructor.cpp 
b/clang/test/PCH/cxx-invalid-destructor.cpp
new file mode 100644
index 0..fc89cf1f3dfc1
--- /dev/null
+++ b/clang/test/PCH/cxx-invalid-destructor.cpp
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -x c++ -std=c++11 -emit-pch -o %t 
%S/cxx-invalid-destructor.h -fallow-pch-with-compiler-errors
+// RUN: %clang_cc1 -x c++ -std=c++11 -include-pch %t 
%S/cxx-invalid-destructor.cpp -fsyntax-only -fno-validate-pch
+
+Foo f;

diff  --git a/clang/test/PCH/cxx-invalid-destructor.h 
b/clang/test/PCH/cxx-invalid-destructor.h
new file mode 100644
index 0..59095a37c203e
--- /dev/null
+++ b/clang/test/PCH/cxx-invalid-destructor.h
@@ -0,0 +1,7 @@
+struct Base {
+  ~Base();
+};
+
+struct Foo : public Base {
+  ~Base();
+};



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


[clang-tools-extra] 4d90ff5 - [clangd] When inserting "using", add "::" in front if that's the style.

2020-08-25 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-08-25T14:07:49+02:00
New Revision: 4d90ff59ac453a67ac692ffdf8242e4cfbd2b34f

URL: 
https://github.com/llvm/llvm-project/commit/4d90ff59ac453a67ac692ffdf8242e4cfbd2b34f
DIFF: 
https://github.com/llvm/llvm-project/commit/4d90ff59ac453a67ac692ffdf8242e4cfbd2b34f.diff

LOG: [clangd] When inserting "using", add "::" in front if that's the style.

We guess the style based on the existing using declarations. If there
are any and they all start with ::, we add it to the newly added one
too.

Differential Revision: https://reviews.llvm.org/D86473

Added: 


Modified: 
clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
clang-tools-extra/clangd/unittests/TweakTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp 
b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
index 9e64ceeeaead..e4900041671a 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp
@@ -86,6 +86,13 @@ class UsingFinder : public RecursiveASTVisitor {
   const SourceManager &SM;
 };
 
+bool isFullyQualified(const NestedNameSpecifier *NNS) {
+  if (!NNS)
+return false;
+  return NNS->getKind() == NestedNameSpecifier::Global ||
+ isFullyQualified(NNS->getPrefix());
+}
+
 struct InsertionPointData {
   // Location to insert the "using" statement. If invalid then the statement
   // should not be inserted at all (it already exists).
@@ -94,6 +101,9 @@ struct InsertionPointData {
   // insertion point is anchored to, we may need one or more \n to ensure
   // proper formatting.
   std::string Suffix;
+  // Whether using should be fully qualified, even if what the user typed was
+  // not. This is based on our detection of the local style.
+  bool AlwaysFullyQualify = false;
 };
 
 // Finds the best place to insert the "using" statement. Returns invalid
@@ -118,7 +128,13 @@ findInsertionPoint(const Tweak::Selection &Inputs,
   SM)
   .TraverseAST(Inputs.AST->getASTContext());
 
+  bool AlwaysFullyQualify = true;
   for (auto &U : Usings) {
+// Only "upgrade" to fully qualified is all relevant using decls are fully
+// qualified. Otherwise trust what the user typed.
+if (!isFullyQualified(U->getQualifier()))
+  AlwaysFullyQualify = false;
+
 if (SM.isBeforeInTranslationUnit(Inputs.Cursor, U->getUsingLoc()))
   // "Usings" is sorted, so we're done.
   break;
@@ -137,6 +153,7 @@ findInsertionPoint(const Tweak::Selection &Inputs,
   if (LastUsingLoc.isValid()) {
 InsertionPointData Out;
 Out.Loc = LastUsingLoc;
+Out.AlwaysFullyQualify = AlwaysFullyQualify;
 return Out;
   }
 
@@ -278,6 +295,9 @@ Expected AddUsing::apply(const Selection 
&Inputs) {
 std::string UsingText;
 llvm::raw_string_ostream UsingTextStream(UsingText);
 UsingTextStream << "using ";
+if (InsertionPoint->AlwaysFullyQualify &&
+!isFullyQualified(QualifierToRemove.getNestedNameSpecifier()))
+  UsingTextStream << "::";
 QualifierToRemove.getNestedNameSpecifier()->print(
 UsingTextStream, Inputs.AST->getASTContext().getPrintingPolicy());
 UsingTextStream << Name << ";" << InsertionPoint->Suffix;

diff  --git a/clang-tools-extra/clangd/unittests/TweakTests.cpp 
b/clang-tools-extra/clangd/unittests/TweakTests.cpp
index b4f135b3efe2..5626b7530599 100644
--- a/clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ b/clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -2723,6 +2723,63 @@ namespace foo { void fun(); }
 
 void foo::fun() {
   ff();
+})cpp"},
+// If all other using are fully qualified, add ::
+{R"cpp(
+#include "test.hpp"
+
+using ::one::two::cc;
+using ::one::two::ee;
+
+void fun() {
+  one::two::f^f();
+})cpp",
+ R"cpp(
+#include "test.hpp"
+
+using ::one::two::cc;
+using ::one::two::ff;using ::one::two::ee;
+
+void fun() {
+  ff();
+})cpp"},
+// Make sure we don't add :: if it's already there
+{R"cpp(
+#include "test.hpp"
+
+using ::one::two::cc;
+using ::one::two::ee;
+
+void fun() {
+  ::one::two::f^f();
+})cpp",
+ R"cpp(
+#include "test.hpp"
+
+using ::one::two::cc;
+using ::one::two::ff;using ::one::two::ee;
+
+void fun() {
+  ff();
+})cpp"},
+// If even one using doesn't start with ::, do not add it
+{R"cpp(
+#include "test.hpp"
+
+using ::one::two::cc;
+using one::two::ee;
+
+void fun() {
+  one::two::f^f();
+})cpp",
+ R"cpp(
+#include "test.hpp"
+
+using ::one::two::cc;
+using one::two::ff;using one::two::ee;
+
+void fun() {
+  ff();
 })cpp"}};
   llvm::StringMap EditedFiles;
   for (const auto &Case : Cases) {



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


[clang-tools-extra] b488935 - [clangd] Discard diagnostics from another SourceManager.

2020-08-21 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-08-21T13:11:21+02:00
New Revision: b4889353207aefd6f2641cef0301f78838c5b52e

URL: 
https://github.com/llvm/llvm-project/commit/b4889353207aefd6f2641cef0301f78838c5b52e
DIFF: 
https://github.com/llvm/llvm-project/commit/b4889353207aefd6f2641cef0301f78838c5b52e.diff

LOG: [clangd] Discard diagnostics from another SourceManager.

This can happen when building implicit modules, as demonstrated in test.
The CompilerInstance uses the same StoredDiags, but different
SourceManager. This used to crash clangd when it tried to relocate the
diagnostic to the main file, which, according to SourceManager from the
diagnostic, is a fake  file.

Differential Revision: https://reviews.llvm.org/D85753

Added: 


Modified: 
clang-tools-extra/clangd/Diagnostics.cpp
clang-tools-extra/clangd/Diagnostics.h
clang-tools-extra/clangd/unittests/ModulesTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/Diagnostics.cpp 
b/clang-tools-extra/clangd/Diagnostics.cpp
index 674fa0dbf9ec..afa72f9d4051 100644
--- a/clang-tools-extra/clangd/Diagnostics.cpp
+++ b/clang-tools-extra/clangd/Diagnostics.cpp
@@ -518,13 +518,17 @@ std::vector StoreDiags::take(const 
clang::tidy::ClangTidyContext *Tidy) {
 }
 
 void StoreDiags::BeginSourceFile(const LangOptions &Opts,
- const Preprocessor *) {
+ const Preprocessor *PP) {
   LangOpts = Opts;
+  if (PP) {
+OrigSrcMgr = &PP->getSourceManager();
+  }
 }
 
 void StoreDiags::EndSourceFile() {
   flushLastDiag();
   LangOpts = None;
+  OrigSrcMgr = nullptr;
 }
 
 /// Sanitizes a piece for presenting it in a synthesized fix message. Ensures
@@ -560,6 +564,16 @@ static void fillNonLocationData(DiagnosticsEngine::Level 
DiagLevel,
 
 void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
   const clang::Diagnostic &Info) {
+  // If the diagnostic was generated for a 
diff erent SourceManager, skip it.
+  // This happens when a module is imported and needs to be implicitly built.
+  // The compilation of that module will use the same StoreDiags, but 
diff erent
+  // SourceManager.
+  if (OrigSrcMgr && Info.hasSourceManager() &&
+  OrigSrcMgr != &Info.getSourceManager()) {
+IgnoreDiagnostics::log(DiagLevel, Info);
+return;
+  }
+
   DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
   bool OriginallyError =
   Info.getDiags()->getDiagnosticIDs()->isDefaultMappingAsError(

diff  --git a/clang-tools-extra/clangd/Diagnostics.h 
b/clang-tools-extra/clangd/Diagnostics.h
index 58f69287f256..4a00abfc450f 100644
--- a/clang-tools-extra/clangd/Diagnostics.h
+++ b/clang-tools-extra/clangd/Diagnostics.h
@@ -122,7 +122,8 @@ class StoreDiags : public DiagnosticConsumer {
   // The ClangTidyContext populates Source and Name for clang-tidy diagnostics.
   std::vector take(const clang::tidy::ClangTidyContext *Tidy = nullptr);
 
-  void BeginSourceFile(const LangOptions &Opts, const Preprocessor *) override;
+  void BeginSourceFile(const LangOptions &Opts,
+   const Preprocessor *PP) override;
   void EndSourceFile() override;
   void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
 const clang::Diagnostic &Info) override;
@@ -148,6 +149,7 @@ class StoreDiags : public DiagnosticConsumer {
   llvm::Optional LastDiag;
   llvm::Optional LastDiagLoc; // Valid only when LastDiag is 
set.
   bool LastDiagOriginallyError = false;  // Valid only when LastDiag is 
set.
+  SourceManager *OrigSrcMgr = nullptr;
 
   llvm::DenseSet> IncludedErrorLocations;
   bool LastPrimaryDiagnosticWasSuppressed = false;

diff  --git a/clang-tools-extra/clangd/unittests/ModulesTests.cpp 
b/clang-tools-extra/clangd/unittests/ModulesTests.cpp
index a10b9e897a48..83d6b28d6dfc 100644
--- a/clang-tools-extra/clangd/unittests/ModulesTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ModulesTests.cpp
@@ -64,6 +64,34 @@ TEST(Modules, PreambleBuildVisibility) {
   EXPECT_TRUE(TU.build().getDiagnostics().empty());
 }
 
+TEST(Modules, Diagnostic) {
+  // Produce a diagnostic while building an implicit module. Use
+  // -fmodules-strict-decluse, but any non-silenced diagnostic will do.
+  TestTU TU = TestTU::withCode(R"cpp(
+/*error-ok*/
+#include "modular.h"
+
+void bar() {}
+)cpp");
+  TU.OverlayRealFileSystemForModules = true;
+  TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("m.modulemap"));
+  TU.ExtraArgs.push_back("-fmodules");
+  TU.ExtraArgs.push_back("-fimplicit-modules");
+  TU.ExtraArgs.push_back("-fmodules-strict-decluse");
+  TU.AdditionalFiles["modular.h"] = R"cpp(
+#include "non-modular.h"
+  )cpp";
+  TU.AdditionalFiles["non-modular.h"] = "";
+  TU.AdditionalFiles["m.modulemap"] = R"modulemap(
+module M {
+  header "modular.h"
+}
+)modulemap";
+
+  // Test that we do not crash.
+  T

[clang-tools-extra] 707138d - [clangd] Remove useless stderr logging.

2020-08-20 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-08-20T14:52:04+02:00
New Revision: 707138d677861182083b3c6c3b44b76951fd36ef

URL: 
https://github.com/llvm/llvm-project/commit/707138d677861182083b3c6c3b44b76951fd36ef
DIFF: 
https://github.com/llvm/llvm-project/commit/707138d677861182083b3c6c3b44b76951fd36ef.diff

LOG: [clangd] Remove useless stderr logging.

This was accidentally added in 53b9199a5cdba8a6e294e1fb183f308ec558db22

Differential Revision: https://reviews.llvm.org/D86284

Added: 


Modified: 
clang-tools-extra/clangd/unittests/TestTU.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/unittests/TestTU.cpp 
b/clang-tools-extra/clangd/unittests/TestTU.cpp
index c468642e6338..03254f876721 100644
--- a/clang-tools-extra/clangd/unittests/TestTU.cpp
+++ b/clang-tools-extra/clangd/unittests/TestTU.cpp
@@ -74,8 +74,6 @@ void initializeModuleCache(CompilerInvocation &CI) {
   ASSERT_FALSE(
   llvm::sys::fs::createUniqueDirectory("module-cache", ModuleCachePath));
   CI.getHeaderSearchOpts().ModuleCachePath = ModuleCachePath.c_str();
-  llvm::errs() << "MC: " << ModuleCachePath << "\n";
-  llvm::errs().flush();
 }
 
 void deleteModuleCache(const std::string ModuleCachePath) {



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


[clang-tools-extra] 53b9199 - [clangd] Fix crash-bug in preamble indexing when using modules.

2020-08-20 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-08-20T14:19:52+02:00
New Revision: 53b9199a5cdba8a6e294e1fb183f308ec558db22

URL: 
https://github.com/llvm/llvm-project/commit/53b9199a5cdba8a6e294e1fb183f308ec558db22
DIFF: 
https://github.com/llvm/llvm-project/commit/53b9199a5cdba8a6e294e1fb183f308ec558db22.diff

LOG: [clangd] Fix crash-bug in preamble indexing when using modules.

When preamble contains #undef, indexing code finds the matching #define
and uses that during indexing. However, it would only look for local
definitions. If the macro was defined in a module, MacroInfo
would be nullptr and clangd would crash.

This change makes clangd ignore any #undef without a matching #define
inside the same TU.

The indexing of macros happens for preamble only, so then #undef must be
in the preamble, which is why we need two .h files in a test.

Note that clangd is currently not ready for module support, but this
brings us one step closer.

This was previously attempted in
4061d9e42cff621462931ac7df9666806c77a237, but had to be reverted due to
broken test. This version fixes that test-only bug by setting a custom module
cache path to avoid re-use of modules across test invocations.

Differential Revision: https://reviews.llvm.org/D85923

Added: 


Modified: 
clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
clang-tools-extra/clangd/unittests/TestFS.h
clang-tools-extra/clangd/unittests/TestTU.cpp
clang-tools-extra/clangd/unittests/TestTU.h
clang/lib/Index/IndexingAction.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp 
b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
index d89db8f015ce..3940946d8016 100644
--- a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1623,6 +1623,31 @@ TEST_F(SymbolCollectorTest, MacrosInHeaders) {
   EXPECT_THAT(Symbols,
   UnorderedElementsAre(AllOf(QName("X"), 
ForCodeCompletion(true;
 }
+
+// Regression test for a crash-bug we used to have.
+TEST_F(SymbolCollectorTest, UndefOfModuleMacro) {
+  auto TU = TestTU::withCode(R"cpp(#include "bar.h")cpp");
+  TU.AdditionalFiles["bar.h"] = R"cpp(
+#include "foo.h"
+#undef X
+)cpp";
+  TU.AdditionalFiles["foo.h"] = "#define X 1";
+  TU.AdditionalFiles["module.map"] = R"cpp(
+module foo {
+ header "foo.h"
+ export *
+   }
+   )cpp";
+  TU.ExtraArgs.push_back("-fmodules");
+  TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("module.map"));
+  TU.OverlayRealFileSystemForModules = true;
+
+  TU.build();
+  // We mostly care about not crashing, but verify that we didn't insert 
garbage
+  // about X too.
+  EXPECT_THAT(TU.headerSymbols(), Not(Contains(QName("X";
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang

diff  --git a/clang-tools-extra/clangd/unittests/TestFS.h 
b/clang-tools-extra/clangd/unittests/TestFS.h
index 7972fe37c7fe..82de319d96cf 100644
--- a/clang-tools-extra/clangd/unittests/TestFS.h
+++ b/clang-tools-extra/clangd/unittests/TestFS.h
@@ -34,12 +34,21 @@ buildTestFS(llvm::StringMap const &Files,
 class MockFS : public ThreadsafeFS {
 public:
   IntrusiveRefCntPtr viewImpl() const override {
-return buildTestFS(Files, Timestamps);
+auto MemFS = buildTestFS(Files, Timestamps);
+if (!OverlayRealFileSystemForModules)
+  return MemFS;
+llvm::IntrusiveRefCntPtr OverlayFileSystem =
+new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem());
+OverlayFileSystem->pushOverlay(MemFS);
+return OverlayFileSystem;
   }
 
   // If relative paths are used, they are resolved with testPath().
   llvm::StringMap Files;
   llvm::StringMap Timestamps;
+  // If true, real file system will be used as fallback for the in-memory one.
+  // This is useful for testing module support.
+  bool OverlayRealFileSystemForModules = false;
 };
 
 // A Compilation database that returns a fixed set of compile flags.

diff  --git a/clang-tools-extra/clangd/unittests/TestTU.cpp 
b/clang-tools-extra/clangd/unittests/TestTU.cpp
index 7d5c29f23393..c468642e6338 100644
--- a/clang-tools-extra/clangd/unittests/TestTU.cpp
+++ b/clang-tools-extra/clangd/unittests/TestTU.cpp
@@ -16,6 +16,7 @@
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Frontend/CompilerInvocation.h"
 #include "clang/Frontend/Utils.h"
+#include "llvm/ADT/ScopeExit.h"
 
 namespace clang {
 namespace clangd {
@@ -54,6 +55,8 @@ ParseInputs TestTU::inputs(MockFS &FS) const {
   Inputs.CompileCommand.Filename = FullFilename;
   Inputs.CompileCommand.Directory = testRoot();
   Inputs.Contents = Code;
+  if (OverlayRealFileSystemForModules)
+FS.OverlayRealFileSystemForModules = true;
   Inputs.TFS = &FS;
   Inputs.Opts = ParseOptions();
   Inputs.Opts.BuildRecoveryAST = true;
@@ -66,12 +69,31 @@ ParseInputs TestTU::inputs(MockFS &FS) const {
   return 

[clang-tools-extra] baeff98 - [clang] When loading preamble from AST file, re-export modules in Sema.

2020-08-20 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-08-20T14:19:52+02:00
New Revision: baeff989b050e0f63412c52c1b8f9d8f3e91f671

URL: 
https://github.com/llvm/llvm-project/commit/baeff989b050e0f63412c52c1b8f9d8f3e91f671
DIFF: 
https://github.com/llvm/llvm-project/commit/baeff989b050e0f63412c52c1b8f9d8f3e91f671.diff

LOG: [clang] When loading preamble from AST file, re-export modules in Sema.

This addresses a FIXME in ASTReader.

Modules were already re-exported for Preprocessor, but not for Sema.
The result was that, with -fmodules-local-submodule-visibility, all AST
nodes belonging to a module that was loaded in a premable where not
accesible from the main part of the file and a diagnostic recommending
importing those modules would be generated.

Differential Revision: https://reviews.llvm.org/D86069

Added: 
clang/test/PCH/preamble-modules.cpp

Modified: 
clang-tools-extra/clangd/unittests/ModulesTests.cpp
clang/include/clang/Sema/Sema.h
clang/lib/Serialization/ASTReader.cpp
clang/test/PCH/Inputs/modules/Foo.h

Removed: 




diff  --git a/clang-tools-extra/clangd/unittests/ModulesTests.cpp 
b/clang-tools-extra/clangd/unittests/ModulesTests.cpp
index 0098a15f64bb..a10b9e897a48 100644
--- a/clang-tools-extra/clangd/unittests/ModulesTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ModulesTests.cpp
@@ -26,7 +26,7 @@ TEST(Modules, TextualIncludeInPreamble) {
 void foo() {}
 )cpp");
   TU.ExtraArgs.push_back("-fmodule-name=M");
-  TU.ExtraArgs.push_back("-fmodule-map-file=m.modulemap");
+  TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("m.modulemap"));
   TU.AdditionalFiles["Textual.h"] = "void foo();";
   TU.AdditionalFiles["m.modulemap"] = R"modulemap(
 module M {
@@ -39,6 +39,31 @@ TEST(Modules, TextualIncludeInPreamble) {
   TU.index();
 }
 
+// Verify that visibility of AST nodes belonging to modules, but loaded from
+// preamble PCH, is restored.
+TEST(Modules, PreambleBuildVisibility) {
+  TestTU TU = TestTU::withCode(R"cpp(
+#include "module.h"
+
+foo x;
+)cpp");
+  TU.OverlayRealFileSystemForModules = true;
+  TU.ExtraArgs.push_back("-fmodules");
+  TU.ExtraArgs.push_back("-fmodules-strict-decluse");
+  TU.ExtraArgs.push_back("-Xclang");
+  TU.ExtraArgs.push_back("-fmodules-local-submodule-visibility");
+  TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("m.modulemap"));
+  TU.AdditionalFiles["module.h"] = R"cpp(
+typedef int foo;
+)cpp";
+  TU.AdditionalFiles["m.modulemap"] = R"modulemap(
+module M {
+  header "module.h"
+}
+)modulemap";
+  EXPECT_TRUE(TU.build().getDiagnostics().empty());
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 49ab94f9df14..84e66b85208e 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1912,6 +1912,12 @@ class Sema final {
 
   bool isModuleVisible(const Module *M, bool ModulePrivate = false);
 
+  // When loading a non-modular PCH files, this is used to restore module
+  // visibility.
+  void makeModuleVisible(Module *Mod, SourceLocation ImportLoc) {
+VisibleModules.setVisible(Mod, ImportLoc);
+  }
+
   /// Determine whether a declaration is visible to name lookup.
   bool isVisible(const NamedDecl *D) {
 return D->isUnconditionallyVisible() || isVisibleSlow(D);

diff  --git a/clang/lib/Serialization/ASTReader.cpp 
b/clang/lib/Serialization/ASTReader.cpp
index 21cdde9e8455..464bbc662230 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -4987,10 +4987,10 @@ void ASTReader::InitializeContext() {
 /*ImportLoc=*/Import.ImportLoc);
   if (Import.ImportLoc.isValid())
 PP.makeModuleVisible(Imported, Import.ImportLoc);
-  // FIXME: should we tell Sema to make the module visible too?
+  // This updates visibility for Preprocessor only. For Sema, which can be
+  // nullptr here, we do the same later, in UpdateSema().
 }
   }
-  ImportedModules.clear();
 }
 
 void ASTReader::finalizeForWriting() {
@@ -7943,6 +7943,15 @@ void ASTReader::UpdateSema() {
   SemaObj->FpPragmaStack.CurrentPragmaLocation = FpPragmaCurrentLocation;
 }
   }
+
+  // For non-modular AST files, restore visiblity of modules.
+  for (auto &Import : ImportedModules) {
+if (Import.ImportLoc.isInvalid())
+  continue;
+if (Module *Imported = getSubmodule(Import.ID)) {
+  SemaObj->makeModuleVisible(Imported, Import.ImportLoc);
+}
+  }
 }
 
 IdentifierInfo *ASTReader::get(StringRef Name) {

diff  --git a/clang/test/PCH/Inputs/modules/Foo.h 
b/clang/test/PCH/Inputs/modules/Foo.h
index d661dbccbc33..c93614e0683f 100644
--- a/clang/test/PCH/Inputs/modules/Foo.h
+++ b/clang/test/PCH/Inputs/modules/Foo.h
@@ -1 +1,3 @@
 void make_foo(void);
+
+typedef int MyType;

diff  --git a/clang/test/PCH/preamble-modules.cpp 
b

[clang] 73f0772 - [clangd] Revert "[clangd] Fix crash-bug in preamble indexing when using modules."

2020-08-13 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-08-13T17:09:54+02:00
New Revision: 73f0772c0baf1c7cac2995341c11d83c4d7a37f4

URL: 
https://github.com/llvm/llvm-project/commit/73f0772c0baf1c7cac2995341c11d83c4d7a37f4
DIFF: 
https://github.com/llvm/llvm-project/commit/73f0772c0baf1c7cac2995341c11d83c4d7a37f4.diff

LOG: [clangd] Revert "[clangd] Fix crash-bug in preamble indexing when using 
modules."

This reverts commit 4061d9e42cff621462931ac7df9666806c77a237.
Tests are failing in some configuration, likely due to not cleaning up
module cache path before running the test.

Differential Revision: https://reviews.llvm.org/D85907

Added: 


Modified: 
clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
clang-tools-extra/clangd/unittests/TestFS.h
clang-tools-extra/clangd/unittests/TestTU.cpp
clang-tools-extra/clangd/unittests/TestTU.h
clang/lib/Index/IndexingAction.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp 
b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
index 48a6952b2610..70a8e6832d02 100644
--- a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1610,31 +1610,6 @@ TEST_F(SymbolCollectorTest, MacrosInHeaders) {
   EXPECT_THAT(Symbols,
   UnorderedElementsAre(AllOf(QName("X"), 
ForCodeCompletion(true;
 }
-
-// Regression test for a crash-bug we used to have.
-TEST_F(SymbolCollectorTest, UndefOfModuleMacro) {
-  auto TU = TestTU::withCode(R"cpp(#include "bar.h")cpp");
-  TU.AdditionalFiles["bar.h"] = R"cpp(
-#include "foo.h"
-#undef X
-)cpp";
-  TU.AdditionalFiles["foo.h"] = "#define X 1";
-  TU.AdditionalFiles["module.map"] = R"cpp(
-module foo {
- header "foo.h"
- export *
-   }
-   )cpp";
-  TU.ExtraArgs.push_back("-fmodules");
-  TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("module.map"));
-  TU.OverlayRealFileSystemForModules = true;
-
-  TU.build();
-  // We mostly care about not crashing, but verify that we didn't insert 
garbage
-  // about X too.
-  EXPECT_THAT(TU.headerSymbols(), Not(Contains(QName("X";
-}
-
 } // namespace
 } // namespace clangd
 } // namespace clang

diff  --git a/clang-tools-extra/clangd/unittests/TestFS.h 
b/clang-tools-extra/clangd/unittests/TestFS.h
index 82de319d96cf..7972fe37c7fe 100644
--- a/clang-tools-extra/clangd/unittests/TestFS.h
+++ b/clang-tools-extra/clangd/unittests/TestFS.h
@@ -34,21 +34,12 @@ buildTestFS(llvm::StringMap const &Files,
 class MockFS : public ThreadsafeFS {
 public:
   IntrusiveRefCntPtr viewImpl() const override {
-auto MemFS = buildTestFS(Files, Timestamps);
-if (!OverlayRealFileSystemForModules)
-  return MemFS;
-llvm::IntrusiveRefCntPtr OverlayFileSystem =
-new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem());
-OverlayFileSystem->pushOverlay(MemFS);
-return OverlayFileSystem;
+return buildTestFS(Files, Timestamps);
   }
 
   // If relative paths are used, they are resolved with testPath().
   llvm::StringMap Files;
   llvm::StringMap Timestamps;
-  // If true, real file system will be used as fallback for the in-memory one.
-  // This is useful for testing module support.
-  bool OverlayRealFileSystemForModules = false;
 };
 
 // A Compilation database that returns a fixed set of compile flags.

diff  --git a/clang-tools-extra/clangd/unittests/TestTU.cpp 
b/clang-tools-extra/clangd/unittests/TestTU.cpp
index 16305400307a..7d5c29f23393 100644
--- a/clang-tools-extra/clangd/unittests/TestTU.cpp
+++ b/clang-tools-extra/clangd/unittests/TestTU.cpp
@@ -54,8 +54,6 @@ ParseInputs TestTU::inputs(MockFS &FS) const {
   Inputs.CompileCommand.Filename = FullFilename;
   Inputs.CompileCommand.Directory = testRoot();
   Inputs.Contents = Code;
-  if (OverlayRealFileSystemForModules)
-FS.OverlayRealFileSystemForModules = true;
   Inputs.TFS = &FS;
   Inputs.Opts = ParseOptions();
   Inputs.Opts.BuildRecoveryAST = true;

diff  --git a/clang-tools-extra/clangd/unittests/TestTU.h 
b/clang-tools-extra/clangd/unittests/TestTU.h
index dd0cecc406ac..06abd64dc623 100644
--- a/clang-tools-extra/clangd/unittests/TestTU.h
+++ b/clang-tools-extra/clangd/unittests/TestTU.h
@@ -66,16 +66,6 @@ struct TestTU {
   // Simulate a header guard of the header (using an #import directive).
   bool ImplicitHeaderGuard = true;
 
-  // Whether to use overlay the TestFS over the real filesystem. This is
-  // required for use of implicit modules.where the module file is written to
-  // disk and later read back.
-  // FIXME: Change the way reading/writing modules work to allow us to keep 
them
-  // in memory across multiple clang invocations, at least in tests, to
-  // eliminate the need for real file system here.
-  // Please avoid using this for things other than implicit modules. The plan 
is
-  // to eliminate this option some day

[clang] 4061d9e - [clangd] Fix crash-bug in preamble indexing when using modules.

2020-08-10 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-08-10T18:42:57+02:00
New Revision: 4061d9e42cff621462931ac7df9666806c77a237

URL: 
https://github.com/llvm/llvm-project/commit/4061d9e42cff621462931ac7df9666806c77a237
DIFF: 
https://github.com/llvm/llvm-project/commit/4061d9e42cff621462931ac7df9666806c77a237.diff

LOG: [clangd] Fix crash-bug in preamble indexing when using modules.

Summary:
When preamble contains #undef, indexing code finds the matching #define
and uses that during indexing. However, it would only look for local
definitions. If the macro was defined in a module, MacroInfo
would be nullptr and clangd would crash.

This change makes clangd ignore any #undef without a matching #define
inside the same TU.

The indexing of macros happens for preamble only, so then #undef must be
in the preamble, which is why we need two .h files in a test.

Note that clangd is currently not ready for module support, but this
brings us one step closer.

Reviewers: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, 
cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D80525

Added: 


Modified: 
clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
clang-tools-extra/clangd/unittests/TestFS.h
clang-tools-extra/clangd/unittests/TestTU.cpp
clang-tools-extra/clangd/unittests/TestTU.h
clang/lib/Index/IndexingAction.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp 
b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
index 3614ab2c5cb9..8e8f1a4f9af5 100644
--- a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1520,6 +1520,31 @@ TEST_F(SymbolCollectorTest, MacrosInHeaders) {
   EXPECT_THAT(Symbols,
   UnorderedElementsAre(AllOf(QName("X"), 
ForCodeCompletion(true;
 }
+
+// Regression test for a crash-bug we used to have.
+TEST_F(SymbolCollectorTest, UndefOfModuleMacro) {
+  auto TU = TestTU::withCode(R"cpp(#include "bar.h")cpp");
+  TU.AdditionalFiles["bar.h"] = R"cpp(
+#include "foo.h"
+#undef X
+)cpp";
+  TU.AdditionalFiles["foo.h"] = "#define X 1";
+  TU.AdditionalFiles["module.map"] = R"cpp(
+module foo {
+ header "foo.h"
+ export *
+   }
+   )cpp";
+  TU.ExtraArgs.push_back("-fmodules");
+  TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("module.map"));
+  TU.OverlayRealFileSystemForModules = true;
+
+  TU.build();
+  // We mostly care about not crashing, but verify that we didn't insert 
garbage
+  // about X too.
+  EXPECT_THAT(TU.headerSymbols(), Not(Contains(QName("X";
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang

diff  --git a/clang-tools-extra/clangd/unittests/TestFS.h 
b/clang-tools-extra/clangd/unittests/TestFS.h
index 7972fe37c7fe..82de319d96cf 100644
--- a/clang-tools-extra/clangd/unittests/TestFS.h
+++ b/clang-tools-extra/clangd/unittests/TestFS.h
@@ -34,12 +34,21 @@ buildTestFS(llvm::StringMap const &Files,
 class MockFS : public ThreadsafeFS {
 public:
   IntrusiveRefCntPtr viewImpl() const override {
-return buildTestFS(Files, Timestamps);
+auto MemFS = buildTestFS(Files, Timestamps);
+if (!OverlayRealFileSystemForModules)
+  return MemFS;
+llvm::IntrusiveRefCntPtr OverlayFileSystem =
+new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem());
+OverlayFileSystem->pushOverlay(MemFS);
+return OverlayFileSystem;
   }
 
   // If relative paths are used, they are resolved with testPath().
   llvm::StringMap Files;
   llvm::StringMap Timestamps;
+  // If true, real file system will be used as fallback for the in-memory one.
+  // This is useful for testing module support.
+  bool OverlayRealFileSystemForModules = false;
 };
 
 // A Compilation database that returns a fixed set of compile flags.

diff  --git a/clang-tools-extra/clangd/unittests/TestTU.cpp 
b/clang-tools-extra/clangd/unittests/TestTU.cpp
index 7d5c29f23393..16305400307a 100644
--- a/clang-tools-extra/clangd/unittests/TestTU.cpp
+++ b/clang-tools-extra/clangd/unittests/TestTU.cpp
@@ -54,6 +54,8 @@ ParseInputs TestTU::inputs(MockFS &FS) const {
   Inputs.CompileCommand.Filename = FullFilename;
   Inputs.CompileCommand.Directory = testRoot();
   Inputs.Contents = Code;
+  if (OverlayRealFileSystemForModules)
+FS.OverlayRealFileSystemForModules = true;
   Inputs.TFS = &FS;
   Inputs.Opts = ParseOptions();
   Inputs.Opts.BuildRecoveryAST = true;

diff  --git a/clang-tools-extra/clangd/unittests/TestTU.h 
b/clang-tools-extra/clangd/unittests/TestTU.h
index 06abd64dc623..dd0cecc406ac 100644
--- a/clang-tools-extra/clangd/unittests/TestTU.h
+++ b/clang-tools-extra/clangd/unittests/TestTU.h
@@ -66,6 +66,16 @@ struct TestTU {
   // Simulate a header guard of the header (using an #import directive).
   bool ImplicitHeaderGuard = true;
 
+  // W

[clang-tools-extra] e2d61ae - Correctly set CompilingPCH in PrecompilePreambleAction.

2020-08-10 Thread Adam Czachorowski via cfe-commits

Author: Adam Czachorowski
Date: 2020-08-10T17:49:23+02:00
New Revision: e2d61ae5733316a14783b36c84b8e7681b0e3d59

URL: 
https://github.com/llvm/llvm-project/commit/e2d61ae5733316a14783b36c84b8e7681b0e3d59
DIFF: 
https://github.com/llvm/llvm-project/commit/e2d61ae5733316a14783b36c84b8e7681b0e3d59.diff

LOG: Correctly set CompilingPCH in PrecompilePreambleAction.

This fixes a crash bug in clangd when used with modules. ASTWriter would
end up writing references to submodules into the PCH file, but upon
reading the submodules would not exists and
HeaderFileInfoTrait::ReadData would crash.

Differential Revision: https://reviews.llvm.org/D85532

Added: 
clang-tools-extra/clangd/unittests/ModulesTests.cpp

Modified: 
clang-tools-extra/clangd/unittests/CMakeLists.txt
clang/lib/Frontend/PrecompiledPreamble.cpp
clang/unittests/Frontend/ASTUnitTest.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/unittests/CMakeLists.txt 
b/clang-tools-extra/clangd/unittests/CMakeLists.txt
index c25e2b7f8103..966fa9630852 100644
--- a/clang-tools-extra/clangd/unittests/CMakeLists.txt
+++ b/clang-tools-extra/clangd/unittests/CMakeLists.txt
@@ -63,6 +63,7 @@ add_unittest(ClangdUnitTests ClangdTests
   IndexTests.cpp
   JSONTransportTests.cpp
   LSPClient.cpp
+  ModulesTests.cpp
   ParsedASTTests.cpp
   PathMappingTests.cpp
   PreambleTests.cpp

diff  --git a/clang-tools-extra/clangd/unittests/ModulesTests.cpp 
b/clang-tools-extra/clangd/unittests/ModulesTests.cpp
new file mode 100644
index ..0098a15f64bb
--- /dev/null
+++ b/clang-tools-extra/clangd/unittests/ModulesTests.cpp
@@ -0,0 +1,44 @@
+//===-- ModulesTests.cpp  ---*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "Annotations.h"
+#include "TestFS.h"
+#include "TestTU.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(Modules, TextualIncludeInPreamble) {
+  TestTU TU = TestTU::withCode(R"cpp(
+#include "Textual.h"
+
+void foo() {}
+)cpp");
+  TU.ExtraArgs.push_back("-fmodule-name=M");
+  TU.ExtraArgs.push_back("-fmodule-map-file=m.modulemap");
+  TU.AdditionalFiles["Textual.h"] = "void foo();";
+  TU.AdditionalFiles["m.modulemap"] = R"modulemap(
+module M {
+  module Textual {
+textual header "Textual.h"
+  }
+}
+)modulemap";
+  // Test that we do not crash.
+  TU.index();
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang

diff  --git a/clang/lib/Frontend/PrecompiledPreamble.cpp 
b/clang/lib/Frontend/PrecompiledPreamble.cpp
index 6cdfc595dcae..3fb61f37ae2b 100644
--- a/clang/lib/Frontend/PrecompiledPreamble.cpp
+++ b/clang/lib/Frontend/PrecompiledPreamble.cpp
@@ -208,6 +208,11 @@ class PrecompilePreambleAction : public ASTFrontendAction {
 Callbacks.AfterPCHEmitted(Writer);
   }
 
+  bool BeginSourceFileAction(CompilerInstance &CI) override {
+assert(CI.getLangOpts().CompilingPCH);
+return ASTFrontendAction::BeginSourceFileAction(CI);
+  }
+
   bool shouldEraseOutputFiles() override { return !hasEmittedPreamblePCH(); }
   bool hasCodeCompletionSupport() const override { return false; }
   bool hasASTFileSupport() const override { return false; }
@@ -396,6 +401,8 @@ llvm::ErrorOr 
PrecompiledPreamble::Build(
   auto PreambleDepCollector = std::make_shared();
   Clang->addDependencyCollector(PreambleDepCollector);
 
+  Clang->getLangOpts().CompilingPCH = true;
+
   // Remap the main source file to the preamble buffer.
   StringRef MainFilePath = FrontendOpts.Inputs[0].getFile();
   auto PreambleInputBuffer = llvm::MemoryBuffer::getMemBufferCopy(

diff  --git a/clang/unittests/Frontend/ASTUnitTest.cpp 
b/clang/unittests/Frontend/ASTUnitTest.cpp
index bdbc462e2bcb..c5b84e74cee9 100644
--- a/clang/unittests/Frontend/ASTUnitTest.cpp
+++ b/clang/unittests/Frontend/ASTUnitTest.cpp
@@ -13,6 +13,7 @@
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/CompilerInvocation.h"
 #include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Lex/HeaderSearch.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/ToolOutputFile.h"
@@ -111,4 +112,42 @@ TEST_F(ASTUnitTest, GetBufferForFileMemoryMapping) {
 llvm::MemoryBuffer::MemoryBuffer_MMap);
 }
 
+TEST_F(ASTUnitTest, ModuleTextualHeader) {
+  llvm::IntrusiveRefCntPtr InMemoryFs =
+  new llvm::vfs::InMemoryFileSystem();
+  InMemoryFs->addFile("test.cpp", 0, llvm::MemoryBuffer::getMemBuffer(R"cpp(
+  #include "Textual.h"
+  void foo() {}
+)cpp"));
+  InMemoryFs->addFile("m.modulem