summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clangd/CodeComplete.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clangd/CodeComplete.cpp')
-rw-r--r--clang-tools-extra/clangd/CodeComplete.cpp34
1 files changed, 31 insertions, 3 deletions
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index f8a4a4598f8..77e0a8d5e78 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -44,6 +44,8 @@
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/ExternalPreprocessorSource.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/DeclSpec.h"
@@ -1017,6 +1019,24 @@ struct SemaCompleteInput {
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;
};
+void loadMainFilePreambleMacros(const Preprocessor &PP,
+ const PreambleData &Preamble) {
+ // The ExternalPreprocessorSource has our macros, if we know where to look.
+ // We can read all the macros using PreambleMacros->ReadDefinedMacros(),
+ // but this includes transitively included files, so may deserialize a lot.
+ ExternalPreprocessorSource *PreambleMacros = PP.getExternalSource();
+ // As we have the names of the macros, we can look up their IdentifierInfo
+ // and then use this to load just the macros we want.
+ IdentifierInfoLookup *PreambleIdentifiers =
+ PP.getIdentifierTable().getExternalIdentifierLookup();
+ if (!PreambleIdentifiers || !PreambleMacros)
+ return;
+ for (const auto& MacroName : Preamble.MainFileMacros)
+ if (auto *II = PreambleIdentifiers->get(MacroName))
+ if (II->isOutOfDate())
+ PreambleMacros->updateOutOfDateIdentifier(*II);
+}
+
// Invokes Sema code completion on a file.
// If \p Includes is set, it will be updated based on the compiler invocation.
bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
@@ -1058,9 +1078,9 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
// However, if we're completing *inside* the preamble section of the draft,
// overriding the preamble will break sema completion. Fortunately we can just
// skip all includes in this case; these completions are really simple.
- bool CompletingInPreamble =
- ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0).Size >
- Input.Offset;
+ PreambleBounds PreambleRegion =
+ ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0);
+ bool CompletingInPreamble = PreambleRegion.Size > Input.Offset;
// NOTE: we must call BeginSourceFile after prepareCompilerInstance. Otherwise
// the remapped buffers do not get freed.
IgnoreDiagnostics DummyDiagsConsumer;
@@ -1078,6 +1098,14 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
Input.FileName);
return false;
}
+ // Macros can be defined within the preamble region of the main file.
+ // They don't fall nicely into our index/Sema dichotomy:
+ // - they're not indexed for completion (they're not available across files)
+ // - but Sema code complete won't see them: as part of the preamble, they're
+ // deserialized only when mentioned.
+ // Force them to be deserialized so SemaCodeComplete sees them.
+ if (Input.Preamble)
+ loadMainFilePreambleMacros(Clang->getPreprocessor(), *Input.Preamble);
if (Includes)
Clang->getPreprocessor().addPPCallbacks(
collectIncludeStructureCallback(Clang->getSourceManager(), Includes));
OpenPOWER on IntegriCloud