aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp')
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp82
1 files changed, 73 insertions, 9 deletions
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index 6ff028cf6980..7644a5e1423e 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -85,7 +85,7 @@
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Reproducer.h"
+#include "lldb/Utility/ReproducerProvider.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StringList.h"
@@ -302,6 +302,55 @@ static void SetupModuleHeaderPaths(CompilerInstance *compiler,
search_opts.ImplicitModuleMaps = true;
}
+/// Iff the given identifier is a C++ keyword, remove it from the
+/// identifier table (i.e., make the token a normal identifier).
+static void RemoveCppKeyword(IdentifierTable &idents, llvm::StringRef token) {
+ // FIXME: 'using' is used by LLDB for local variables, so we can't remove
+ // this keyword without breaking this functionality.
+ if (token == "using")
+ return;
+ // GCC's '__null' is used by LLDB to define NULL/Nil/nil.
+ if (token == "__null")
+ return;
+
+ LangOptions cpp_lang_opts;
+ cpp_lang_opts.CPlusPlus = true;
+ cpp_lang_opts.CPlusPlus11 = true;
+ cpp_lang_opts.CPlusPlus20 = true;
+
+ clang::IdentifierInfo &ii = idents.get(token);
+ // The identifier has to be a C++-exclusive keyword. if not, then there is
+ // nothing to do.
+ if (!ii.isCPlusPlusKeyword(cpp_lang_opts))
+ return;
+ // If the token is already an identifier, then there is nothing to do.
+ if (ii.getTokenID() == clang::tok::identifier)
+ return;
+ // Otherwise the token is a C++ keyword, so turn it back into a normal
+ // identifier.
+ ii.revertTokenIDToIdentifier();
+}
+
+/// Remove all C++ keywords from the given identifier table.
+static void RemoveAllCppKeywords(IdentifierTable &idents) {
+#define KEYWORD(NAME, FLAGS) RemoveCppKeyword(idents, llvm::StringRef(#NAME));
+#include "clang/Basic/TokenKinds.def"
+}
+
+/// Configures Clang diagnostics for the expression parser.
+static void SetupDefaultClangDiagnostics(CompilerInstance &compiler) {
+ // List of Clang warning groups that are not useful when parsing expressions.
+ const std::vector<const char *> groupsToIgnore = {
+ "unused-value",
+ "odr",
+ };
+ for (const char *group : groupsToIgnore) {
+ compiler.getDiagnostics().setSeverityForGroup(
+ clang::diag::Flavor::WarningOrError, group,
+ clang::diag::Severity::Ignored, SourceLocation());
+ }
+}
+
//===----------------------------------------------------------------------===//
// Implementation of ClangExpressionParser
//===----------------------------------------------------------------------===//
@@ -454,6 +503,10 @@ ClangExpressionParser::ClangExpressionParser(
// 4. Create and install the target on the compiler.
m_compiler->createDiagnostics();
+ // Limit the number of error diagnostics we emit.
+ // A value of 0 means no limit for both LLDB and Clang.
+ m_compiler->getDiagnostics().setErrorLimit(target_sp->GetExprErrorLimit());
+
auto target_info = TargetInfo::CreateTargetInfo(
m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts);
if (log) {
@@ -598,12 +651,7 @@ ClangExpressionParser::ClangExpressionParser(
m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo);
// Disable some warnings.
- m_compiler->getDiagnostics().setSeverityForGroup(
- clang::diag::Flavor::WarningOrError, "unused-value",
- clang::diag::Severity::Ignored, SourceLocation());
- m_compiler->getDiagnostics().setSeverityForGroup(
- clang::diag::Flavor::WarningOrError, "odr",
- clang::diag::Severity::Ignored, SourceLocation());
+ SetupDefaultClangDiagnostics(*m_compiler);
// Inform the target of the language options
//
@@ -623,6 +671,21 @@ ClangExpressionParser::ClangExpressionParser(
m_compiler->createSourceManager(m_compiler->getFileManager());
m_compiler->createPreprocessor(TU_Complete);
+ switch (language) {
+ case lldb::eLanguageTypeC:
+ case lldb::eLanguageTypeC89:
+ case lldb::eLanguageTypeC99:
+ case lldb::eLanguageTypeC11:
+ case lldb::eLanguageTypeObjC:
+ // This is not a C++ expression but we enabled C++ as explained above.
+ // Remove all C++ keywords from the PP so that the user can still use
+ // variables that have C++ keywords as names (e.g. 'int template;').
+ RemoveAllCppKeywords(m_compiler->getPreprocessor().getIdentifierTable());
+ break;
+ default:
+ break;
+ }
+
if (ClangModulesDeclVendor *decl_vendor =
target_sp->GetClangModulesDeclVendor()) {
if (auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
@@ -1010,8 +1073,8 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
if (file.Write(expr_text, bytes_written).Success()) {
if (bytes_written == expr_text_len) {
file.Close();
- if (auto fileEntry =
- m_compiler->getFileManager().getFile(result_path)) {
+ if (auto fileEntry = m_compiler->getFileManager().getOptionalFileRef(
+ result_path)) {
source_mgr.setMainFileID(source_mgr.createFileID(
*fileEntry,
SourceLocation(), SrcMgr::C_User));
@@ -1074,6 +1137,7 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap();
if (decl_map) {
decl_map->InstallCodeGenerator(&m_compiler->getASTConsumer());
+ decl_map->InstallDiagnosticManager(diagnostic_manager);
clang::ExternalASTSource *ast_source = decl_map->CreateProxy();