aboutsummaryrefslogtreecommitdiff
path: root/clang-tools-extra
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra')
-rw-r--r--clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp3
-rw-r--r--clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp5
-rw-r--r--clang-tools-extra/clang-doc/BitcodeReader.cpp2
-rw-r--r--clang-tools-extra/clang-doc/BitcodeWriter.cpp4
-rw-r--r--clang-tools-extra/clang-doc/BitcodeWriter.h1
-rw-r--r--clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp489
-rw-r--r--clang-tools-extra/clang-doc/JSONGenerator.cpp145
-rw-r--r--clang-tools-extra/clang-doc/Representation.cpp16
-rw-r--r--clang-tools-extra/clang-doc/Representation.h10
-rw-r--r--clang-tools-extra/clang-doc/Serialize.cpp11
-rw-r--r--clang-tools-extra/clang-doc/assets/clang-doc-mustache.css4
-rw-r--r--clang-tools-extra/clang-doc/assets/class-template.mustache66
-rw-r--r--clang-tools-extra/clang-doc/assets/comment-template.mustache49
-rw-r--r--clang-tools-extra/clang-doc/assets/enum-template.mustache12
-rw-r--r--clang-tools-extra/clang-doc/assets/function-template.mustache6
-rw-r--r--clang-tools-extra/clang-doc/assets/namespace-template.mustache45
-rw-r--r--clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp2
-rw-r--r--clang-tools-extra/clang-move/tool/ClangMove.cpp5
-rw-r--r--clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp5
-rw-r--r--clang-tools-extra/clang-tidy/.clang-tidy1
-rw-r--r--clang-tools-extra/clang-tidy/ClangTidy.cpp5
-rw-r--r--clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp2
-rw-r--r--clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp3
-rw-r--r--clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt1
-rw-r--r--clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp180
-rw-r--r--clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.h31
-rw-r--r--clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp76
-rw-r--r--clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp18
-rw-r--r--clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp38
-rw-r--r--clang-tools-extra/clang-tidy/llvm/CMakeLists.txt2
-rw-r--r--clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp3
-rw-r--r--clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.cpp139
-rw-r--r--clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.h29
-rw-r--r--clang-tools-extra/clang-tidy/misc/HeaderIncludeCycleCheck.cpp76
-rw-r--r--clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp11
-rw-r--r--clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp4
-rw-r--r--clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp2
-rw-r--r--clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp5
-rw-r--r--clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp5
-rw-r--r--clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp34
-rw-r--r--clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h1
-rwxr-xr-xclang-tools-extra/clang-tidy/tool/clang-tidy-diff.py3
-rwxr-xr-xclang-tools-extra/clang-tidy/tool/run-clang-tidy.py2
-rw-r--r--clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp8
-rw-r--r--clang-tools-extra/clangd/ClangdLSPServer.cpp6
-rw-r--r--clang-tools-extra/clangd/CodeComplete.cpp6
-rw-r--r--clang-tools-extra/clangd/Config.h13
-rw-r--r--clang-tools-extra/clangd/ConfigCompile.cpp16
-rw-r--r--clang-tools-extra/clangd/ConfigFragment.h11
-rw-r--r--clang-tools-extra/clangd/ConfigYAML.cpp10
-rw-r--r--clang-tools-extra/clangd/FindSymbols.cpp12
-rw-r--r--clang-tools-extra/clangd/Hover.cpp119
-rw-r--r--clang-tools-extra/clangd/Hover.h2
-rw-r--r--clang-tools-extra/clangd/Preamble.cpp2
-rw-r--r--clang-tools-extra/clangd/SystemIncludeExtractor.cpp2
-rw-r--r--clang-tools-extra/clangd/support/Markup.cpp357
-rw-r--r--clang-tools-extra/clangd/support/Markup.h42
-rw-r--r--clang-tools-extra/clangd/test/signature-help-unescaped.test40
-rw-r--r--clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp108
-rw-r--r--clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp2
-rw-r--r--clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp5
-rw-r--r--clang-tools-extra/clangd/unittests/HoverTests.cpp137
-rw-r--r--clang-tools-extra/clangd/unittests/support/MarkupTests.cpp341
-rw-r--r--clang-tools-extra/clangd/unittests/tweaks/TweakTests.cpp2
-rw-r--r--clang-tools-extra/docs/ReleaseNotes.rst51
-rw-r--r--clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst72
-rw-r--r--clang-tools-extra/docs/clang-tidy/checks/list.rst2
-rw-r--r--clang-tools-extra/docs/clang-tidy/checks/llvm/use-new-mlir-op-builder.rst21
-rw-r--r--clang-tools-extra/docs/clang-tidy/checks/readability/qualified-auto.rst42
-rw-r--r--clang-tools-extra/modularize/ModularizeUtilities.cpp2
-rw-r--r--clang-tools-extra/test/clang-apply-replacements/basic.cpp20
-rw-r--r--clang-tools-extra/test/clang-apply-replacements/conflict.cpp20
-rw-r--r--clang-tools-extra/test/clang-apply-replacements/crlf.cpp10
-rw-r--r--clang-tools-extra/test/clang-apply-replacements/format-header.cpp20
-rw-r--r--clang-tools-extra/test/clang-apply-replacements/format.cpp18
-rw-r--r--clang-tools-extra/test/clang-apply-replacements/identical-in-TU.cpp12
-rw-r--r--clang-tools-extra/test/clang-apply-replacements/identical.cpp12
-rw-r--r--clang-tools-extra/test/clang-apply-replacements/ignore-conflict.cpp10
-rw-r--r--clang-tools-extra/test/clang-apply-replacements/invalid-files.cpp8
-rw-r--r--clang-tools-extra/test/clang-apply-replacements/order-dependent.cpp14
-rw-r--r--clang-tools-extra/test/clang-apply-replacements/relative-paths.cpp14
-rw-r--r--clang-tools-extra/test/clang-apply-replacements/yml-basic.cpp20
-rw-r--r--clang-tools-extra/test/clang-change-namespace/allow-list.cpp4
-rw-r--r--clang-tools-extra/test/clang-change-namespace/macro.cpp21
-rw-r--r--clang-tools-extra/test/clang-doc/Inputs/basic-project/include/Circle.h4
-rw-r--r--clang-tools-extra/test/clang-doc/basic-project.mustache.test384
-rw-r--r--clang-tools-extra/test/clang-doc/json/class-requires.cpp1
-rw-r--r--clang-tools-extra/test/clang-doc/json/class-template.cpp1
-rw-r--r--clang-tools-extra/test/clang-doc/json/class.cpp63
-rw-r--r--clang-tools-extra/test/clang-doc/json/compound-constraints.cpp4
-rw-r--r--clang-tools-extra/test/clang-doc/json/concept.cpp18
-rw-r--r--clang-tools-extra/test/clang-doc/json/function-requires.cpp7
-rw-r--r--clang-tools-extra/test/clang-doc/json/method-template.cpp2
-rw-r--r--clang-tools-extra/test/clang-doc/json/namespace.cpp17
-rw-r--r--clang-tools-extra/test/clang-doc/json/nested-namespace.cpp4
-rw-r--r--clang-tools-extra/test/clang-doc/mustache-index.cpp10
-rw-r--r--clang-tools-extra/test/clang-doc/mustache-separate-namespace.cpp8
-rw-r--r--clang-tools-extra/test/clang-include-fixer/include_path.cpp28
-rw-r--r--clang-tools-extra/test/clang-include-fixer/multiple_fixes.cpp12
-rw-r--r--clang-tools-extra/test/clang-include-fixer/yamldb_autodetect.cpp6
-rw-r--r--clang-tools-extra/test/clang-move/move-class.cpp42
-rw-r--r--clang-tools-extra/test/clang-move/move-enum-decl.cpp32
-rw-r--r--clang-tools-extra/test/clang-move/move-function.cpp42
-rw-r--r--clang-tools-extra/test/clang-move/move-multiple-classes.cpp18
-rw-r--r--clang-tools-extra/test/clang-move/move-template-class.cpp28
-rw-r--r--clang-tools-extra/test/clang-move/move-type-alias.cpp40
-rw-r--r--clang-tools-extra/test/clang-move/move-used-helper-decls.cpp98
-rw-r--r--clang-tools-extra/test/clang-move/move-var.cpp36
-rw-r--r--clang-tools-extra/test/clang-move/no-move-macro-helpers.cpp32
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.c54
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.cpp145
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/bugprone/signed-char-misuse-c23.c201
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/bugprone/unhandled-self-assignment.cpp206
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/llvm/use-new-mlir-op-builder.cpp76
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/misc/header-include-cycle.cpp20
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/misc/unused-parameters.cpp12
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/modernize/concat-nested-namespaces.cpp13
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/modernize/pass-by-value-header.cpp7
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/modernize/pass-by-value-multi-fixes.cpp13
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp52
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp17
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp4
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-absl.cpp6
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp25
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/portability/restrict-system-includes-transitive.cpp12
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/portability/template-virtual-member-function.cpp17
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-symlink.cpp11
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto.cpp83
-rw-r--r--clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-diff.cpp12
-rw-r--r--clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-run-with-database.cpp38
-rw-r--r--clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-store-check-profile-one-tu.cpp12
-rw-r--r--clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp18
-rw-r--r--clang-tools-extra/test/clang-tidy/infrastructure/export-relpath.cpp13
-rw-r--r--clang-tools-extra/test/clang-tidy/infrastructure/list-checks.cpp6
-rw-r--r--clang-tools-extra/test/clang-tidy/infrastructure/read_file_config.cpp12
-rw-r--r--clang-tools-extra/test/clang-tidy/infrastructure/run-clang-tidy.cpp6
-rw-r--r--clang-tools-extra/test/clang-tidy/infrastructure/static-analyzer-config.cpp2
-rw-r--r--clang-tools-extra/test/clang-tidy/infrastructure/static-analyzer.cpp4
-rw-r--r--clang-tools-extra/test/clang-tidy/infrastructure/verify-config.cpp16
-rw-r--r--clang-tools-extra/test/modularize/NoProblemsAssistant.modularize4
-rw-r--r--clang-tools-extra/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp3
-rw-r--r--clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp129
-rw-r--r--clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp25
-rw-r--r--clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp9
-rw-r--r--clang-tools-extra/unittests/clang-tidy/ClangTidyTest.h3
-rw-r--r--clang-tools-extra/unittests/include/common/VirtualFileHelper.h3
146 files changed, 3890 insertions, 1521 deletions
diff --git a/clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp b/clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp
index 062e236..76de8bd 100644
--- a/clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp
+++ b/clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp
@@ -97,8 +97,7 @@ int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv);
DiagnosticOptions DiagOpts;
- DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), DiagOpts);
+ DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts);
// Determine a formatting style from options.
auto FormatStyleOrError = format::getStyle(FormatStyleOpt, FormatStyleConfig,
diff --git a/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp b/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp
index 2a8fe2d..2efdd92 100644
--- a/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp
+++ b/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp
@@ -128,9 +128,8 @@ int main(int argc, const char **argv) {
LangOptions DefaultLangOptions;
DiagnosticOptions DiagOpts;
clang::TextDiagnosticPrinter DiagnosticPrinter(errs(), DiagOpts);
- DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), DiagOpts,
- &DiagnosticPrinter, false);
+ DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts,
+ &DiagnosticPrinter, false);
auto &FileMgr = Tool.getFiles();
SourceManager Sources(Diagnostics, FileMgr);
Rewriter Rewrite(Sources, DefaultLangOptions);
diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp
index dce34a8..4efbbd3 100644
--- a/clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -384,6 +384,8 @@ static llvm::Error parseRecord(const Record &R, unsigned ID,
return decodeRecord(R, I->Path, Blob);
case REFERENCE_FIELD:
return decodeRecord(R, F, Blob);
+ case REFERENCE_FILE:
+ return decodeRecord(R, I->DocumentationFileName, Blob);
default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"invalid field for Reference");
diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp
index eed2372..e23511b 100644
--- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp
@@ -210,6 +210,7 @@ static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor>
{REFERENCE_TYPE, {"RefType", &genIntAbbrev}},
{REFERENCE_PATH, {"Path", &genStringAbbrev}},
{REFERENCE_FIELD, {"Field", &genIntAbbrev}},
+ {REFERENCE_FILE, {"File", &genStringAbbrev}},
{TEMPLATE_PARAM_CONTENTS, {"Contents", &genStringAbbrev}},
{TEMPLATE_SPECIALIZATION_OF,
{"SpecializationOf", &genSymbolIdAbbrev}},
@@ -286,7 +287,7 @@ static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
// Reference Block
{BI_REFERENCE_BLOCK_ID,
{REFERENCE_USR, REFERENCE_NAME, REFERENCE_QUAL_NAME, REFERENCE_TYPE,
- REFERENCE_PATH, REFERENCE_FIELD}},
+ REFERENCE_PATH, REFERENCE_FIELD, REFERENCE_FILE}},
// Template Blocks.
{BI_TEMPLATE_BLOCK_ID, {}},
{BI_TEMPLATE_PARAM_BLOCK_ID, {TEMPLATE_PARAM_CONTENTS}},
@@ -479,6 +480,7 @@ void ClangDocBitcodeWriter::emitBlock(const Reference &R, FieldId Field) {
emitRecord((unsigned)R.RefType, REFERENCE_TYPE);
emitRecord(R.Path, REFERENCE_PATH);
emitRecord((unsigned)Field, REFERENCE_FIELD);
+ emitRecord(R.DocumentationFileName, REFERENCE_FILE);
}
void ClangDocBitcodeWriter::emitBlock(const FriendInfo &R) {
diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.h b/clang-tools-extra/clang-doc/BitcodeWriter.h
index 501af12..688f886 100644
--- a/clang-tools-extra/clang-doc/BitcodeWriter.h
+++ b/clang-tools-extra/clang-doc/BitcodeWriter.h
@@ -140,6 +140,7 @@ enum RecordId {
REFERENCE_TYPE,
REFERENCE_PATH,
REFERENCE_FIELD,
+ REFERENCE_FILE,
TEMPLATE_PARAM_CONTENTS,
TEMPLATE_SPECIALIZATION_OF,
TYPEDEF_USR,
diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
index 7aeaa1b..a64cb5e 100644
--- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
+++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
@@ -27,6 +27,9 @@ using namespace llvm::mustache;
namespace clang {
namespace doc {
+static Error generateDocForJSON(json::Value &JSON, StringRef Filename,
+ StringRef Path, raw_fd_ostream &OS,
+ const ClangDocContext &CDCtx);
static Error createFileOpenError(StringRef FileName, std::error_code EC) {
return createFileError("cannot open file " + FileName, EC);
@@ -132,404 +135,68 @@ Error MustacheHTMLGenerator::generateDocs(
return Err;
}
- // Track which directories we already tried to create.
- StringSet<> CreatedDirs;
- // Collect all output by file name and create the necessary directories.
- StringMap<std::vector<doc::Info *>> FileToInfos;
- for (const auto &Group : Infos) {
- llvm::TimeTraceScope TS("setup directories");
- doc::Info *Info = Group.getValue().get();
-
- SmallString<128> Path;
- sys::path::native(RootDir, Path);
- sys::path::append(Path, Info->getRelativeFilePath(""));
- if (!CreatedDirs.contains(Path)) {
- if (std::error_code EC = sys::fs::create_directories(Path))
- return createStringError(EC, "failed to create directory '%s'.",
- Path.c_str());
- CreatedDirs.insert(Path);
- }
-
- sys::path::append(Path, Info->getFileBaseName() + ".html");
- FileToInfos[Path].push_back(Info);
+ {
+ llvm::TimeTraceScope TS("Generate JSON for Mustache");
+ if (auto JSONGenerator = findGeneratorByName("json")) {
+ if (Error Err = JSONGenerator.get()->generateDocs(
+ RootDir, std::move(Infos), CDCtx))
+ return Err;
+ } else
+ return JSONGenerator.takeError();
}
+ StringMap<json::Value> JSONFileMap;
{
- llvm::TimeTraceScope TS("Generate Docs");
- for (const auto &Group : FileToInfos) {
- llvm::TimeTraceScope TS("Info to Doc");
+ llvm::TimeTraceScope TS("Iterate JSON files");
+ std::error_code EC;
+ sys::fs::directory_iterator JSONIter(RootDir, EC);
+ std::vector<json::Value> JSONFiles;
+ JSONFiles.reserve(Infos.size());
+ if (EC)
+ return createStringError("Failed to create directory iterator.");
+
+ while (JSONIter != sys::fs::directory_iterator()) {
+ if (EC)
+ return createFileError("Failed to iterate: " + JSONIter->path(), EC);
+
+ auto Path = StringRef(JSONIter->path());
+ if (!Path.ends_with(".json")) {
+ JSONIter.increment(EC);
+ continue;
+ }
+
+ auto File = MemoryBuffer::getFile(Path);
+ if (EC = File.getError(); EC)
+ // TODO: Buffer errors to report later, look into using Clang
+ // diagnostics.
+ llvm::errs() << "Failed to open file: " << Path << " " << EC.message()
+ << '\n';
+
+ auto Parsed = json::parse((*File)->getBuffer());
+ if (!Parsed)
+ return Parsed.takeError();
+
std::error_code FileErr;
- raw_fd_ostream InfoOS(Group.getKey(), FileErr, sys::fs::OF_None);
+ SmallString<16> HTMLPath(Path.begin(), Path.end());
+ sys::path::replace_extension(HTMLPath, "html");
+ raw_fd_ostream InfoOS(HTMLPath, FileErr, sys::fs::OF_None);
if (FileErr)
- return createFileOpenError(Group.getKey(), FileErr);
+ return createFileOpenError(Path, FileErr);
- for (const auto &Info : Group.getValue())
- if (Error Err = generateDocForInfo(Info, InfoOS, CDCtx))
- return Err;
+ if (Error Err = generateDocForJSON(*Parsed, sys::path::stem(HTMLPath),
+ HTMLPath, InfoOS, CDCtx))
+ return Err;
+ JSONIter.increment(EC);
}
}
- return Error::success();
-}
-
-static json::Value
-extractValue(const Location &L,
- std::optional<StringRef> RepositoryUrl = std::nullopt) {
- Object Obj = Object();
- // TODO: Consider using both Start/End line numbers to improve location report
- Obj.insert({"LineNumber", L.StartLineNumber});
- Obj.insert({"Filename", L.Filename});
-
- if (!L.IsFileInRootDir || !RepositoryUrl)
- return Obj;
- SmallString<128> FileURL(*RepositoryUrl);
- sys::path::append(FileURL, sys::path::Style::posix, L.Filename);
- FileURL += "#" + std::to_string(L.StartLineNumber);
- Obj.insert({"FileURL", FileURL});
-
- return Obj;
-}
-
-static json::Value extractValue(const Reference &I,
- StringRef CurrentDirectory) {
- SmallString<64> Path = I.getRelativeFilePath(CurrentDirectory);
- sys::path::append(Path, I.getFileBaseName() + ".html");
- sys::path::native(Path, sys::path::Style::posix);
- Object Obj = Object();
- Obj.insert({"Link", Path});
- Obj.insert({"Name", I.Name});
- Obj.insert({"QualName", I.QualName});
- Obj.insert({"ID", toHex(toStringRef(I.USR))});
- return Obj;
-}
-
-static json::Value extractValue(const TypedefInfo &I) {
- // Not Supported
- return nullptr;
-}
-
-static json::Value extractValue(const CommentInfo &I) {
- Object Obj = Object();
-
- json::Value ChildVal = Object();
- Object &Child = *ChildVal.getAsObject();
-
- json::Value ChildArr = Array();
- auto &CARef = *ChildArr.getAsArray();
- CARef.reserve(I.Children.size());
- for (const auto &C : I.Children)
- CARef.emplace_back(extractValue(*C));
-
- switch (I.Kind) {
- case CommentKind::CK_TextComment: {
- Obj.insert({commentKindToString(I.Kind), I.Text});
- return Obj;
- }
-
- case CommentKind::CK_BlockCommandComment: {
- Child.insert({"Command", I.Name});
- Child.insert({"Children", ChildArr});
- Obj.insert({commentKindToString(I.Kind), ChildVal});
- return Obj;
- }
-
- case CommentKind::CK_InlineCommandComment: {
- json::Value ArgsArr = Array();
- auto &ARef = *ArgsArr.getAsArray();
- ARef.reserve(I.Args.size());
- for (const auto &Arg : I.Args)
- ARef.emplace_back(Arg);
- Child.insert({"Command", I.Name});
- Child.insert({"Args", ArgsArr});
- Child.insert({"Children", ChildArr});
- Obj.insert({commentKindToString(I.Kind), ChildVal});
- return Obj;
- }
-
- case CommentKind::CK_ParamCommandComment:
- case CommentKind::CK_TParamCommandComment: {
- Child.insert({"ParamName", I.ParamName});
- Child.insert({"Direction", I.Direction});
- Child.insert({"Explicit", I.Explicit});
- Child.insert({"Children", ChildArr});
- Obj.insert({commentKindToString(I.Kind), ChildVal});
- return Obj;
- }
-
- case CommentKind::CK_VerbatimBlockComment: {
- Child.insert({"Text", I.Text});
- if (!I.CloseName.empty())
- Child.insert({"CloseName", I.CloseName});
- Child.insert({"Children", ChildArr});
- Obj.insert({commentKindToString(I.Kind), ChildVal});
- return Obj;
- }
-
- case CommentKind::CK_VerbatimBlockLineComment:
- case CommentKind::CK_VerbatimLineComment: {
- Child.insert({"Text", I.Text});
- Child.insert({"Children", ChildArr});
- Obj.insert({commentKindToString(I.Kind), ChildVal});
- return Obj;
- }
-
- case CommentKind::CK_HTMLStartTagComment: {
- json::Value AttrKeysArray = json::Array();
- json::Value AttrValuesArray = json::Array();
- auto &KeyArr = *AttrKeysArray.getAsArray();
- auto &ValArr = *AttrValuesArray.getAsArray();
- KeyArr.reserve(I.AttrKeys.size());
- ValArr.reserve(I.AttrValues.size());
- for (const auto &K : I.AttrKeys)
- KeyArr.emplace_back(K);
- for (const auto &V : I.AttrValues)
- ValArr.emplace_back(V);
- Child.insert({"Name", I.Name});
- Child.insert({"SelfClosing", I.SelfClosing});
- Child.insert({"AttrKeys", AttrKeysArray});
- Child.insert({"AttrValues", AttrValuesArray});
- Child.insert({"Children", ChildArr});
- Obj.insert({commentKindToString(I.Kind), ChildVal});
- return Obj;
- }
-
- case CommentKind::CK_HTMLEndTagComment: {
- Child.insert({"Name", I.Name});
- Child.insert({"Children", ChildArr});
- Obj.insert({commentKindToString(I.Kind), ChildVal});
- return Obj;
- }
-
- case CommentKind::CK_FullComment:
- case CommentKind::CK_ParagraphComment: {
- Child.insert({"Children", ChildArr});
- Obj.insert({commentKindToString(I.Kind), ChildVal});
- return Obj;
- }
-
- case CommentKind::CK_Unknown: {
- Obj.insert({commentKindToString(I.Kind), I.Text});
- return Obj;
- }
- }
- llvm_unreachable("Unknown comment kind encountered.");
-}
-
-static void maybeInsertLocation(std::optional<Location> Loc,
- const ClangDocContext &CDCtx, Object &Obj) {
- if (!Loc)
- return;
- Location L = *Loc;
- Obj.insert({"Location", extractValue(L, CDCtx.RepositoryUrl)});
-}
-
-static void extractDescriptionFromInfo(ArrayRef<CommentInfo> Descriptions,
- json::Object &EnumValObj) {
- if (Descriptions.empty())
- return;
- json::Value DescArr = Array();
- json::Array &DescARef = *DescArr.getAsArray();
- DescARef.reserve(Descriptions.size());
- for (const CommentInfo &Child : Descriptions)
- DescARef.emplace_back(extractValue(Child));
- EnumValObj.insert({"EnumValueComments", DescArr});
-}
-
-static json::Value extractValue(const FunctionInfo &I, StringRef ParentInfoDir,
- const ClangDocContext &CDCtx) {
- Object Obj = Object();
- Obj.insert({"Name", I.Name});
- Obj.insert({"ID", toHex(toStringRef(I.USR))});
- Obj.insert({"Access", getAccessSpelling(I.Access).str()});
- Obj.insert({"ReturnType", extractValue(I.ReturnType.Type, ParentInfoDir)});
-
- json::Value ParamArr = Array();
- json::Array &ParamARef = *ParamArr.getAsArray();
- ParamARef.reserve(I.Params.size());
- for (const auto Val : enumerate(I.Params)) {
- json::Value V = Object();
- auto &VRef = *V.getAsObject();
- VRef.insert({"Name", Val.value().Name});
- VRef.insert({"Type", Val.value().Type.Name});
- VRef.insert({"End", Val.index() + 1 == I.Params.size()});
- ParamARef.emplace_back(V);
- }
- Obj.insert({"Params", ParamArr});
- maybeInsertLocation(I.DefLoc, CDCtx, Obj);
- return Obj;
-}
-
-static json::Value extractValue(const EnumInfo &I,
- const ClangDocContext &CDCtx) {
- Object Obj = Object();
- std::string EnumType = I.Scoped ? "enum class " : "enum ";
- EnumType += I.Name;
- bool HasComment = llvm::any_of(
- I.Members, [](const EnumValueInfo &M) { return !M.Description.empty(); });
- Obj.insert({"EnumName", EnumType});
- Obj.insert({"HasComment", HasComment});
- Obj.insert({"ID", toHex(toStringRef(I.USR))});
- json::Value EnumArr = Array();
- json::Array &EnumARef = *EnumArr.getAsArray();
- EnumARef.reserve(I.Members.size());
- for (const EnumValueInfo &M : I.Members) {
- json::Value EnumValue = Object();
- auto &EnumValObj = *EnumValue.getAsObject();
- EnumValObj.insert({"Name", M.Name});
- if (!M.ValueExpr.empty())
- EnumValObj.insert({"ValueExpr", M.ValueExpr});
- else
- EnumValObj.insert({"Value", M.Value});
-
- extractDescriptionFromInfo(M.Description, EnumValObj);
- EnumARef.emplace_back(EnumValue);
- }
- Obj.insert({"EnumValues", EnumArr});
-
- extractDescriptionFromInfo(I.Description, Obj);
- maybeInsertLocation(I.DefLoc, CDCtx, Obj);
-
- return Obj;
-}
-
-static void extractScopeChildren(const ScopeChildren &S, Object &Obj,
- StringRef ParentInfoDir,
- const ClangDocContext &CDCtx) {
- json::Value NamespaceArr = Array();
- json::Array &NamespaceARef = *NamespaceArr.getAsArray();
- NamespaceARef.reserve(S.Namespaces.size());
- for (const Reference &Child : S.Namespaces)
- NamespaceARef.emplace_back(extractValue(Child, ParentInfoDir));
-
- if (!NamespaceARef.empty())
- Obj.insert({"Namespace", Object{{"Links", NamespaceArr}}});
-
- json::Value RecordArr = Array();
- json::Array &RecordARef = *RecordArr.getAsArray();
- RecordARef.reserve(S.Records.size());
- for (const Reference &Child : S.Records)
- RecordARef.emplace_back(extractValue(Child, ParentInfoDir));
-
- if (!RecordARef.empty())
- Obj.insert({"Record", Object{{"Links", RecordArr}}});
-
- json::Value FunctionArr = Array();
- json::Array &FunctionARef = *FunctionArr.getAsArray();
- FunctionARef.reserve(S.Functions.size());
-
- json::Value PublicFunctionArr = Array();
- json::Array &PublicFunctionARef = *PublicFunctionArr.getAsArray();
- PublicFunctionARef.reserve(S.Functions.size());
-
- json::Value ProtectedFunctionArr = Array();
- json::Array &ProtectedFunctionARef = *ProtectedFunctionArr.getAsArray();
- ProtectedFunctionARef.reserve(S.Functions.size());
-
- for (const FunctionInfo &Child : S.Functions) {
- json::Value F = extractValue(Child, ParentInfoDir, CDCtx);
- AccessSpecifier Access = Child.Access;
- if (Access == AccessSpecifier::AS_public)
- PublicFunctionARef.emplace_back(F);
- else if (Access == AccessSpecifier::AS_protected)
- ProtectedFunctionARef.emplace_back(F);
- else
- FunctionARef.emplace_back(F);
- }
-
- if (!FunctionARef.empty())
- Obj.insert({"Function", Object{{"Obj", FunctionArr}}});
-
- if (!PublicFunctionARef.empty())
- Obj.insert({"PublicFunction", Object{{"Obj", PublicFunctionArr}}});
-
- if (!ProtectedFunctionARef.empty())
- Obj.insert({"ProtectedFunction", Object{{"Obj", ProtectedFunctionArr}}});
-
- json::Value EnumArr = Array();
- auto &EnumARef = *EnumArr.getAsArray();
- EnumARef.reserve(S.Enums.size());
- for (const EnumInfo &Child : S.Enums)
- EnumARef.emplace_back(extractValue(Child, CDCtx));
-
- if (!EnumARef.empty())
- Obj.insert({"Enums", Object{{"Obj", EnumArr}}});
-
- json::Value TypedefArr = Array();
- auto &TypedefARef = *TypedefArr.getAsArray();
- TypedefARef.reserve(S.Typedefs.size());
- for (const TypedefInfo &Child : S.Typedefs)
- TypedefARef.emplace_back(extractValue(Child));
-
- if (!TypedefARef.empty())
- Obj.insert({"Typedefs", Object{{"Obj", TypedefArr}}});
-}
-
-static json::Value extractValue(const NamespaceInfo &I,
- const ClangDocContext &CDCtx) {
- Object NamespaceValue = Object();
- std::string InfoTitle = I.Name.empty() ? "Global Namespace"
- : (Twine("namespace ") + I.Name).str();
-
- SmallString<64> BasePath = I.getRelativeFilePath("");
- NamespaceValue.insert({"NamespaceTitle", InfoTitle});
- NamespaceValue.insert({"NamespacePath", BasePath});
-
- extractDescriptionFromInfo(I.Description, NamespaceValue);
- extractScopeChildren(I.Children, NamespaceValue, BasePath, CDCtx);
- return NamespaceValue;
-}
-
-static json::Value extractValue(const RecordInfo &I,
- const ClangDocContext &CDCtx) {
- Object RecordValue = Object();
- extractDescriptionFromInfo(I.Description, RecordValue);
- RecordValue.insert({"Name", I.Name});
- RecordValue.insert({"FullName", I.FullName});
- RecordValue.insert({"RecordType", getTagType(I.TagType)});
-
- maybeInsertLocation(I.DefLoc, CDCtx, RecordValue);
-
- SmallString<64> BasePath = I.getRelativeFilePath("");
- extractScopeChildren(I.Children, RecordValue, BasePath, CDCtx);
- json::Value PublicMembers = Array();
- json::Array &PubMemberRef = *PublicMembers.getAsArray();
- PubMemberRef.reserve(I.Members.size());
- json::Value ProtectedMembers = Array();
- json::Array &ProtMemberRef = *ProtectedMembers.getAsArray();
- ProtMemberRef.reserve(I.Members.size());
- json::Value PrivateMembers = Array();
- json::Array &PrivMemberRef = *PrivateMembers.getAsArray();
- PrivMemberRef.reserve(I.Members.size());
- for (const MemberTypeInfo &Member : I.Members) {
- json::Value MemberValue = Object();
- auto &MVRef = *MemberValue.getAsObject();
- MVRef.insert({"Name", Member.Name});
- MVRef.insert({"Type", Member.Type.Name});
- extractDescriptionFromInfo(Member.Description, MVRef);
-
- if (Member.Access == AccessSpecifier::AS_public)
- PubMemberRef.emplace_back(MemberValue);
- else if (Member.Access == AccessSpecifier::AS_protected)
- ProtMemberRef.emplace_back(MemberValue);
- else if (Member.Access == AccessSpecifier::AS_private)
- ProtMemberRef.emplace_back(MemberValue);
- }
- if (!PubMemberRef.empty())
- RecordValue.insert({"PublicMembers", Object{{"Obj", PublicMembers}}});
- if (!ProtMemberRef.empty())
- RecordValue.insert({"ProtectedMembers", Object{{"Obj", ProtectedMembers}}});
- if (!PrivMemberRef.empty())
- RecordValue.insert({"PrivateMembers", Object{{"Obj", PrivateMembers}}});
-
- return RecordValue;
+ return Error::success();
}
-static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V,
- Info *I) {
+static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V) {
V.getAsObject()->insert({"ProjectName", CDCtx.ProjectName});
json::Value StylesheetArr = Array();
- auto InfoPath = I->getRelativeFilePath("");
- SmallString<128> RelativePath = computeRelativePath("", InfoPath);
+ SmallString<128> RelativePath("./");
sys::path::native(RelativePath, sys::path::Style::posix);
auto *SSA = StylesheetArr.getAsArray();
@@ -555,38 +222,42 @@ static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V,
return Error::success();
}
-Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS,
- const ClangDocContext &CDCtx) {
- switch (I->IT) {
- case InfoType::IT_namespace: {
- json::Value V =
- extractValue(*static_cast<clang::doc::NamespaceInfo *>(I), CDCtx);
- if (auto Err = setupTemplateValue(CDCtx, V, I))
+static Error generateDocForJSON(json::Value &JSON, StringRef Filename,
+ StringRef Path, raw_fd_ostream &OS,
+ const ClangDocContext &CDCtx) {
+ auto StrValue = (*JSON.getAsObject())["InfoType"];
+ if (StrValue.kind() != json::Value::Kind::String)
+ return createStringError("JSON file '%s' does not contain key: 'InfoType'.",
+ Filename.str().c_str());
+ auto ObjTypeStr = StrValue.getAsString();
+ if (!ObjTypeStr.has_value())
+ return createStringError(
+ "JSON file '%s' does not contain 'InfoType' field as a string.",
+ Filename.str().c_str());
+
+ if (ObjTypeStr.value() == "namespace") {
+ if (auto Err = setupTemplateValue(CDCtx, JSON))
return Err;
assert(NamespaceTemplate && "NamespaceTemplate is nullptr.");
- NamespaceTemplate->render(V, OS);
- break;
- }
- case InfoType::IT_record: {
- json::Value V =
- extractValue(*static_cast<clang::doc::RecordInfo *>(I), CDCtx);
- if (auto Err = setupTemplateValue(CDCtx, V, I))
+ NamespaceTemplate->render(JSON, OS);
+ } else if (ObjTypeStr.value() == "record") {
+ if (auto Err = setupTemplateValue(CDCtx, JSON))
return Err;
- // Serialize the JSON value to the output stream in a readable format.
- RecordTemplate->render(V, OS);
- break;
+ assert(RecordTemplate && "RecordTemplate is nullptr.");
+ RecordTemplate->render(JSON, OS);
}
+ return Error::success();
+}
+
+Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS,
+ const ClangDocContext &CDCtx) {
+ switch (I->IT) {
case InfoType::IT_enum:
- OS << "IT_enum\n";
- break;
case InfoType::IT_function:
- OS << "IT_Function\n";
- break;
case InfoType::IT_typedef:
- OS << "IT_typedef\n";
- break;
+ case InfoType::IT_namespace:
+ case InfoType::IT_record:
case InfoType::IT_concept:
- break;
case InfoType::IT_variable:
case InfoType::IT_friend:
break;
diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp
index cc4c683..599b381 100644
--- a/clang-tools-extra/clang-doc/JSONGenerator.cpp
+++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp
@@ -43,6 +43,30 @@ static auto SerializeReferenceLambda = [](const auto &Ref, Object &Object) {
serializeReference(Ref, Object);
};
+static std::string infoTypeToString(InfoType IT) {
+ switch (IT) {
+ case InfoType::IT_default:
+ return "default";
+ case InfoType::IT_namespace:
+ return "namespace";
+ case InfoType::IT_record:
+ return "record";
+ case InfoType::IT_function:
+ return "function";
+ case InfoType::IT_enum:
+ return "enum";
+ case InfoType::IT_typedef:
+ return "typedef";
+ case InfoType::IT_concept:
+ return "concept";
+ case InfoType::IT_variable:
+ return "variable";
+ case InfoType::IT_friend:
+ return "friend";
+ }
+ llvm_unreachable("Unknown InfoType encountered.");
+}
+
static json::Object
serializeLocation(const Location &Loc,
const std::optional<StringRef> RepositoryUrl) {
@@ -59,7 +83,39 @@ serializeLocation(const Location &Loc,
return LocationObj;
}
-static json::Value serializeComment(const CommentInfo &I) {
+static void insertComment(Object &Description, json::Value &Comment,
+ StringRef Key) {
+ auto DescriptionIt = Description.find(Key);
+
+ if (DescriptionIt == Description.end()) {
+ auto CommentsArray = json::Array();
+ CommentsArray.push_back(Comment);
+ Description[Key] = std::move(CommentsArray);
+ Description["Has" + Key.str()] = true;
+ } else {
+ DescriptionIt->getSecond().getAsArray()->push_back(Comment);
+ }
+}
+
+static json::Value extractTextComments(Object *ParagraphComment) {
+ if (!ParagraphComment)
+ return json::Object();
+ return *ParagraphComment->get("Children");
+}
+
+static json::Value extractVerbatimComments(json::Array VerbatimLines) {
+ json::Value TextArray = json::Array();
+ auto &TextArrayRef = *TextArray.getAsArray();
+ for (auto &Line : VerbatimLines)
+ TextArrayRef.push_back(*Line.getAsObject()
+ ->get("VerbatimBlockLineComment")
+ ->getAsObject()
+ ->get("Text"));
+
+ return TextArray;
+}
+
+static Object serializeComment(const CommentInfo &I, Object &Description) {
// taken from PR #142273
Object Obj = Object();
@@ -70,7 +126,7 @@ static json::Value serializeComment(const CommentInfo &I) {
auto &CARef = *ChildArr.getAsArray();
CARef.reserve(I.Children.size());
for (const auto &C : I.Children)
- CARef.emplace_back(serializeComment(*C));
+ CARef.emplace_back(serializeComment(*C, Description));
switch (I.Kind) {
case CommentKind::CK_TextComment: {
@@ -79,9 +135,11 @@ static json::Value serializeComment(const CommentInfo &I) {
}
case CommentKind::CK_BlockCommandComment: {
- Child.insert({"Command", I.Name});
- Child.insert({"Children", ChildArr});
- Obj.insert({commentKindToString(I.Kind), ChildVal});
+ auto TextCommentsArray = extractTextComments(CARef.front().getAsObject());
+ if (I.Name == "brief")
+ insertComment(Description, TextCommentsArray, "BriefComments");
+ else if (I.Name == "return")
+ insertComment(Description, TextCommentsArray, "ReturnComments");
return Obj;
}
@@ -103,17 +161,20 @@ static json::Value serializeComment(const CommentInfo &I) {
Child.insert({"ParamName", I.ParamName});
Child.insert({"Direction", I.Direction});
Child.insert({"Explicit", I.Explicit});
- Child.insert({"Children", ChildArr});
- Obj.insert({commentKindToString(I.Kind), ChildVal});
+ auto TextCommentsArray = extractTextComments(CARef.front().getAsObject());
+ Child.insert({"Children", TextCommentsArray});
+ if (I.Kind == CommentKind::CK_ParamCommandComment)
+ insertComment(Description, ChildVal, "ParamComments");
return Obj;
}
case CommentKind::CK_VerbatimBlockComment: {
- Child.insert({"Text", I.Text});
- if (!I.CloseName.empty())
- Child.insert({"CloseName", I.CloseName});
- Child.insert({"Children", ChildArr});
- Obj.insert({commentKindToString(I.Kind), ChildVal});
+ if (I.CloseName == "endcode") {
+ // We don't support \code language specification
+ auto TextCommentsArray = extractVerbatimComments(CARef);
+ insertComment(Description, TextCommentsArray, "CodeComments");
+ } else if (I.CloseName == "endverbatim")
+ insertComment(Description, ChildVal, "VerbatimComments");
return Obj;
}
@@ -155,8 +216,8 @@ static json::Value serializeComment(const CommentInfo &I) {
case CommentKind::CK_FullComment:
case CommentKind::CK_ParagraphComment: {
Child.insert({"Children", ChildArr});
- Obj.insert({commentKindToString(I.Kind), ChildVal});
- return Obj;
+ Child["ParagraphComment"] = true;
+ return Child;
}
case CommentKind::CK_Unknown: {
@@ -172,6 +233,9 @@ serializeCommonAttributes(const Info &I, json::Object &Obj,
const std::optional<StringRef> RepositoryUrl) {
Obj["Name"] = I.Name;
Obj["USR"] = toHex(toStringRef(I.USR));
+ Obj["InfoType"] = infoTypeToString(I.IT);
+ if (!I.DocumentationFileName.empty())
+ Obj["DocumentationFileName"] = I.DocumentationFileName;
if (!I.Path.empty())
Obj["Path"] = I.Path;
@@ -183,12 +247,20 @@ serializeCommonAttributes(const Info &I, json::Object &Obj,
}
if (!I.Description.empty()) {
- json::Value DescArray = json::Array();
- auto &DescArrayRef = *DescArray.getAsArray();
- DescArrayRef.reserve(I.Description.size());
- for (const auto &Comment : I.Description)
- DescArrayRef.push_back(serializeComment(Comment));
- Obj["Description"] = DescArray;
+ Object Description = Object();
+ // Skip straight to the FullComment's children
+ auto &Comments = I.Description.at(0).Children;
+ for (const auto &CommentInfo : Comments) {
+ json::Value Comment = serializeComment(*CommentInfo, Description);
+ // if a ParagraphComment is returned, then it is a top-level comment that
+ // needs to be inserted manually.
+ if (auto *ParagraphComment = Comment.getAsObject();
+ ParagraphComment->get("ParagraphComment")) {
+ auto TextCommentsArray = extractTextComments(ParagraphComment);
+ insertComment(Description, TextCommentsArray, "ParagraphComments");
+ }
+ }
+ Obj["Description"] = std::move(Description);
}
// Namespaces aren't SymbolInfos, so they dont have a DefLoc
@@ -205,6 +277,8 @@ static void serializeReference(const Reference &Ref, Object &ReferenceObj) {
ReferenceObj["Name"] = Ref.Name;
ReferenceObj["QualName"] = Ref.QualName;
ReferenceObj["USR"] = toHex(toStringRef(Ref.USR));
+ if (!Ref.DocumentationFileName.empty())
+ ReferenceObj["DocumentationFileName"] = Ref.DocumentationFileName;
}
// Although namespaces and records both have ScopeChildren, they serialize them
@@ -217,14 +291,18 @@ serializeCommonChildren(const ScopeChildren &Children, json::Object &Obj,
serializeInfo(Info, Object, RepositoryUrl);
};
- if (!Children.Enums.empty())
+ if (!Children.Enums.empty()) {
serializeArray(Children.Enums, Obj, "Enums", SerializeInfo);
+ Obj["HasEnums"] = true;
+ }
if (!Children.Typedefs.empty())
serializeArray(Children.Typedefs, Obj, "Typedefs", SerializeInfo);
- if (!Children.Records.empty())
+ if (!Children.Records.empty()) {
serializeArray(Children.Records, Obj, "Records", SerializeReferenceLambda);
+ Obj["HasRecords"] = true;
+ }
}
template <typename Container, typename SerializationFunc>
@@ -234,10 +312,12 @@ static void serializeArray(const Container &Records, Object &Obj,
json::Value RecordsArray = Array();
auto &RecordsArrayRef = *RecordsArray.getAsArray();
RecordsArrayRef.reserve(Records.size());
- for (const auto &Item : Records) {
+ for (size_t Index = 0; Index < Records.size(); ++Index) {
json::Value ItemVal = Object();
auto &ItemObj = *ItemVal.getAsObject();
- SerializeInfo(Item, ItemObj);
+ SerializeInfo(Records[Index], ItemObj);
+ if (Index == Records.size() - 1)
+ ItemObj["End"] = true;
RecordsArrayRef.push_back(ItemVal);
}
Obj[Key] = RecordsArray;
@@ -380,6 +460,11 @@ static void serializeInfo(const FriendInfo &I, Object &Obj) {
}
}
+static void insertArray(Object &Obj, json::Value &Array, StringRef Key) {
+ Obj[Key] = Array;
+ Obj["Has" + Key.str()] = true;
+}
+
static void serializeInfo(const RecordInfo &I, json::Object &Obj,
const std::optional<StringRef> &RepositoryUrl) {
serializeCommonAttributes(I, Obj, RepositoryUrl);
@@ -406,7 +491,7 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj,
}
if (!PubFunctionsArrayRef.empty())
- Obj["PublicFunctions"] = PubFunctionsArray;
+ insertArray(Obj, PubFunctionsArray, "PublicFunctions");
if (!ProtFunctionsArrayRef.empty())
Obj["ProtectedFunctions"] = ProtFunctionsArray;
}
@@ -430,7 +515,7 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj,
}
if (!PubMembersArrayRef.empty())
- Obj["PublicMembers"] = PublicMembersArray;
+ insertArray(Obj, PublicMembersArray, "PublicMembers");
if (!ProtMembersArrayRef.empty())
Obj["ProtectedMembers"] = ProtectedMembersArray;
}
@@ -496,10 +581,7 @@ static SmallString<16> determineFileName(Info *I, SmallString<128> &Path) {
SmallString<16> FileName;
if (I->IT == InfoType::IT_record) {
auto *RecordSymbolInfo = static_cast<SymbolInfo *>(I);
- if (RecordSymbolInfo->MangledName.size() < 255)
- FileName = RecordSymbolInfo->MangledName;
- else
- FileName = toStringRef(toHex(RecordSymbolInfo->USR));
+ FileName = RecordSymbolInfo->MangledName;
} else if (I->IT == InfoType::IT_namespace && I->Name != "")
// Serialize the global namespace as index.json
FileName = I->Name;
@@ -527,7 +609,10 @@ Error JSONGenerator::generateDocs(
}
SmallString<16> FileName = determineFileName(Info, Path);
+ if (FileToInfos.contains(Path))
+ continue;
FileToInfos[Path].push_back(Info);
+ Info->DocumentationFileName = FileName;
}
for (const auto &Group : FileToInfos) {
diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp
index beaf314..929112f 100644
--- a/clang-tools-extra/clang-doc/Representation.cpp
+++ b/clang-tools-extra/clang-doc/Representation.cpp
@@ -247,6 +247,8 @@ void Reference::merge(Reference &&Other) {
Name = Other.Name;
if (Path.empty())
Path = Other.Path;
+ if (DocumentationFileName.empty())
+ DocumentationFileName = Other.DocumentationFileName;
}
bool FriendInfo::mergeable(const FriendInfo &Other) {
@@ -500,13 +502,13 @@ ClangDocContext::ClangDocContext(tooling::ExecutionContext *ECtx,
}
void ScopeChildren::sort() {
- llvm::sort(Namespaces.begin(), Namespaces.end());
- llvm::sort(Records.begin(), Records.end());
- llvm::sort(Functions.begin(), Functions.end());
- llvm::sort(Enums.begin(), Enums.end());
- llvm::sort(Typedefs.begin(), Typedefs.end());
- llvm::sort(Concepts.begin(), Concepts.end());
- llvm::sort(Variables.begin(), Variables.end());
+ llvm::sort(Namespaces);
+ llvm::sort(Records);
+ llvm::sort(Functions);
+ llvm::sort(Enums);
+ llvm::sort(Typedefs);
+ llvm::sort(Concepts);
+ llvm::sort(Variables);
}
} // namespace doc
} // namespace clang
diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h
index 23f0e90..2a75f89 100644
--- a/clang-tools-extra/clang-doc/Representation.h
+++ b/clang-tools-extra/clang-doc/Representation.h
@@ -121,6 +121,10 @@ struct Reference {
Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef QualName,
StringRef Path = StringRef())
: USR(USR), Name(Name), QualName(QualName), RefType(IT), Path(Path) {}
+ Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef QualName,
+ StringRef Path, SmallString<16> DocumentationFileName)
+ : USR(USR), Name(Name), QualName(QualName), RefType(IT), Path(Path),
+ DocumentationFileName(DocumentationFileName) {}
bool operator==(const Reference &Other) const {
return std::tie(USR, Name, QualName, RefType) ==
@@ -155,6 +159,7 @@ struct Reference {
// Path of directory where the clang-doc generated file will be saved
// (possibly unresolved)
llvm::SmallString<128> Path;
+ SmallString<16> DocumentationFileName;
};
// Holds the children of a record or namespace.
@@ -331,6 +336,11 @@ struct Info {
llvm::SmallString<128> Path; // Path of directory where the clang-doc
// generated file will be saved
+ // The name used for the file that this info is documented in.
+ // In the JSON generator, infos are documented in files with mangled names.
+ // Thus, we keep track of the physical filename for linking purposes.
+ SmallString<16> DocumentationFileName;
+
void mergeBase(Info &&I);
bool mergeable(const Info &Other);
diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp
index 7a0e00c..de73f68 100644
--- a/clang-tools-extra/clang-doc/Serialize.cpp
+++ b/clang-tools-extra/clang-doc/Serialize.cpp
@@ -495,7 +495,8 @@ static void InsertChild(ScopeChildren &Scope, const NamespaceInfo &Info) {
static void InsertChild(ScopeChildren &Scope, const RecordInfo &Info) {
Scope.Records.emplace_back(Info.USR, Info.Name, InfoType::IT_record,
- Info.Name, getInfoRelativePath(Info.Namespace));
+ Info.Name, getInfoRelativePath(Info.Namespace),
+ Info.MangledName);
}
static void InsertChild(ScopeChildren &Scope, EnumInfo Info) {
@@ -777,7 +778,13 @@ static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C,
Mangler->mangleCXXVTable(CXXD, MangledStream);
else
MangledStream << D->getNameAsString();
- I.MangledName = MangledName;
+ if (MangledName.size() > 255)
+ // File creation fails if the mangled name is too long, so default to the
+ // USR. We should look for a better check since filesystems differ in
+ // maximum filename length
+ I.MangledName = llvm::toStringRef(llvm::toHex(I.USR));
+ else
+ I.MangledName = MangledName;
delete Mangler;
}
diff --git a/clang-tools-extra/clang-doc/assets/clang-doc-mustache.css b/clang-tools-extra/clang-doc/assets/clang-doc-mustache.css
index a885a36..e555ee7 100644
--- a/clang-tools-extra/clang-doc/assets/clang-doc-mustache.css
+++ b/clang-tools-extra/clang-doc/assets/clang-doc-mustache.css
@@ -469,3 +469,7 @@ a, a:visited, a:hover, a:active {
text-decoration: none;
color: inherit;
}
+
+.code-block {
+ white-space: pre-line;
+}
diff --git a/clang-tools-extra/clang-doc/assets/class-template.mustache b/clang-tools-extra/clang-doc/assets/class-template.mustache
index f9e78f5..b1a7470 100644
--- a/clang-tools-extra/clang-doc/assets/class-template.mustache
+++ b/clang-tools-extra/clang-doc/assets/class-template.mustache
@@ -44,20 +44,20 @@
<main>
<div class="container">
<div class="sidebar">
- <h2>{{RecordType}} {{Name}}</h2>
+ <h2>{{TagType}} {{Name}}</h2>
<ul>
- {{#PublicMembers}}
+ {{#HasPublicMembers}}
<li class="sidebar-section">
- <a class="sidebar-item" href="#PublicMethods">Public Members</a>
+ <a class="sidebar-item" href="#PublicMembers">Public Members</a>
</li>
<ul>
- {{#Obj}}
+ {{#PublicMembers}}
<li class="sidebar-item-container">
<a class="sidebar-item" href="#{{Name}}">{{Name}}</a>
</li>
- {{/Obj}}
+ {{/PublicMembers}}
</ul>
- {{/PublicMembers}}
+ {{/HasPublicMembers}}
{{#ProtectedMembers}}
<li class="sidebar-section">
<a class="sidebar-item" href="#PublicMethods">Protected Members</a>
@@ -70,18 +70,18 @@
{{/Obj}}
</ul>
{{/ProtectedMembers}}
- {{#PublicFunction}}
+ {{#HasPublicFunctions}}
<li class="sidebar-section">
<a class="sidebar-item" href="#PublicMethods">Public Method</a>
</li>
<ul>
- {{#Obj}}
+ {{#PublicFunctions}}
<li class="sidebar-item-container">
- <a class="sidebar-item" href="#{{ID}}">{{Name}}</a>
+ <a class="sidebar-item" href="#{{USR}}">{{Name}}</a>
</li>
- {{/Obj}}
+ {{/PublicFunctions}}
</ul>
- {{/PublicFunction}}
+ {{/HasPublicFunctions}}
{{#ProtectedFunction}}
<li class="sidebar-section">
<a class="sidebar-item" href="#ProtectedFunction">Protected Method</a>
@@ -101,7 +101,7 @@
<ul>
{{#Obj}}
<li class="sidebar-item-container">
- <a class="sidebar-item" href="#{{ID}}">{{EnumName}}</a>
+ <a class="sidebar-item" href="#{{USR}}">{{EnumName}}</a>
</li>
{{/Obj}}
</ul>
@@ -127,22 +127,22 @@
<div class="content">
<section class="hero section-container">
<div class="hero__title">
- <h1 class="hero__title-large">{{RecordType}} {{Name}}</h1>
- {{#RecordComments}}
+ <h1 class="hero__title-large">{{TagType}} {{Name}}</h1>
+ {{#Description}}
<div class="hero__subtitle">
{{>Comments}}
</div>
- {{/RecordComments}}
+ {{/Description}}
</div>
</section>
- {{#PublicMembers}}
+ {{#HasPublicMembers}}
<section id="PublicMembers" class="section-container">
<h2>Public Members</h2>
<div>
- {{#Obj}}
+ {{#PublicMembers}}
<div id="{{Name}}" class="delimiter-container">
<pre>
-<code class="language-cpp code-clang-doc" >{{Type}} {{Name}}</code>
+ <code class="language-cpp code-clang-doc" >{{Type}} {{Name}}</code>
</pre>
{{#MemberComments}}
<div>
@@ -150,10 +150,10 @@
</div>
{{/MemberComments}}
</div>
- {{/Obj}}
+ {{/PublicMembers}}
</div>
</section>
- {{/PublicMembers}}
+ {{/HasPublicMembers}}
{{#ProtectedMembers}}
<section id="ProtectedMembers" class="section-container">
<h2>Protected Members</h2>
@@ -173,26 +173,28 @@
</div>
</section>
{{/ProtectedMembers}}
- {{#PublicFunction}}
+ {{#HasPublicFunctions}}
<section id="PublicMethods" class="section-container">
<h2>Public Methods</h2>
<div>
- {{#Obj}}
+ {{#PublicFunctions}}
{{>FunctionPartial}}
- {{/Obj}}
+ {{/PublicFunctions}}
</div>
</section>
- {{/PublicFunction}}
- {{#ProtectedFunction}}
- <section id="ProtectedFunction" class="section-container">
- <h2>Protected Methods</h2>
- <div>
+ {{/PublicFunctions}}
+ {{#ProtectedFunction}}
+ <li class="sidebar-section">
+ <a class="sidebar-item" href="#ProtectedFunction">Protected Method</a>
+ </li>
+ <ul>
{{#Obj}}
-{{>FunctionPartial}}
+ <li class="sidebar-item-container">
+ <a class="sidebar-item" href="#{{ID}}">{{Name}}</a>
+ </li>
{{/Obj}}
- </div>
- </section>
- {{/ProtectedFunction}}
+ </ul>
+ {{/ProtectedFunction}}
{{#Enums}}
<section id="Enums" class="section-container">
<h2>Enumerations</h2>
diff --git a/clang-tools-extra/clang-doc/assets/comment-template.mustache b/clang-tools-extra/clang-doc/assets/comment-template.mustache
index 723ace7..4e38e5f 100644
--- a/clang-tools-extra/clang-doc/assets/comment-template.mustache
+++ b/clang-tools-extra/clang-doc/assets/comment-template.mustache
@@ -5,16 +5,55 @@
This file defines templates for generating comments
}}
-{{#FullComment}}
- {{#Children}}
- {{>Comments}}
- {{/Children}}
-{{/FullComment}}
+{{#BriefComments}}
+ <div>
+ {{#.}}
+ <p>{{TextComment}}</p>
+ {{/.}}
+ </div>
+{{/BriefComments}}
+{{#ParagraphComments}}
+ <div>
+ {{#.}}
+ <p>{{TextComment}}</p>
+ {{/.}}
+ </div>
+{{/ParagraphComments}}
{{#ParagraphComment}}
{{#Children}}
{{>Comments}}
{{/Children}}
{{/ParagraphComment}}
+{{#HasParamComments}}
+ <h3>Parameters</h3>
+ {{#ParamComments}}
+ <div>
+ <b>{{ParamName}}</b> {{#Explicit}}{{Direction}}{{/Explicit}} {{#Children}}{{>Comments}}{{/Children}}
+ </div>
+ {{/ParamComments}}
+{{/HasParamComments}}
+{{#HasReturnComments}}
+ <h3>Returns</h3>
+ {{#ReturnComments}}
+ {{#.}}
+ <p>{{TextComment}}</p>
+ {{/.}}
+ {{/ReturnComments}}
+{{/HasReturnComments}}
+{{#HasCodeComments}}
+ <h3>Code</h3>
+ {{#CodeComments}}
+ <div>
+ <pre class="code-block">
+ <code>
+ {{#.}}
+ {{.}}
+ {{/.}}
+ </code>
+ </pre>
+ </div>
+ {{/CodeComments}}
+{{/HasCodeComments}}
{{#BlockCommandComment}}
<div class="block-command-comment__command">
<div class="block-command-command">
diff --git a/clang-tools-extra/clang-doc/assets/enum-template.mustache b/clang-tools-extra/clang-doc/assets/enum-template.mustache
index c459884..53da466 100644
--- a/clang-tools-extra/clang-doc/assets/enum-template.mustache
+++ b/clang-tools-extra/clang-doc/assets/enum-template.mustache
@@ -9,7 +9,7 @@
<div>
<pre>
<code class="language-cpp code-clang-doc">
-{{EnumName}}
+enum {{Name}}
</code>
</pre>
</div>
@@ -23,15 +23,21 @@
<th>Comment</th>
{{/HasComment}}
</tr>
- {{#EnumValues}}
+ {{#Members}}
<tr>
<td>{{Name}}</td>
+ {{! A ValueExpr is an explicitly assigned enum value }}
+ {{#Value}}
<td>{{Value}}</td>
+ {{/Value}}
+ {{^Value}}
+ <td>{{ValueExpr}}</td>
+ {{/Value}}
{{#EnumValueComments}}
<td>{{>Comments}}</td>
{{/EnumValueComments}}
</tr>
- {{/EnumValues}}
+ {{/Members}}
</tbody>
</table>
{{#EnumComments}}
diff --git a/clang-tools-extra/clang-doc/assets/function-template.mustache b/clang-tools-extra/clang-doc/assets/function-template.mustache
index 86e934a..2510a4d 100644
--- a/clang-tools-extra/clang-doc/assets/function-template.mustache
+++ b/clang-tools-extra/clang-doc/assets/function-template.mustache
@@ -6,7 +6,7 @@
This file defines the template for functions/methods
}}
<div class="delimiter-container">
- <div id="{{ID}}">
+ <div id="{{USR}}">
{{! Function Prototype }}
<pre>
<code class="language-cpp code-clang-doc">
@@ -14,10 +14,10 @@
</code>
</pre>
{{! Function Comments }}
- {{#FunctionComments}}
+ {{#Description}}
<div>
{{>Comments}}
</div>
- {{/FunctionComments}}
+ {{/Description}}
</div>
</div>
diff --git a/clang-tools-extra/clang-doc/assets/namespace-template.mustache b/clang-tools-extra/clang-doc/assets/namespace-template.mustache
index 1a44ed3..d96bc5c 100644
--- a/clang-tools-extra/clang-doc/assets/namespace-template.mustache
+++ b/clang-tools-extra/clang-doc/assets/namespace-template.mustache
@@ -46,56 +46,61 @@
<div class="sidebar">
<h2>{{RecordType}} {{Name}}</h2>
<ul>
- {{#Enums}}
+ {{#HasEnums}}
<li class="sidebar-section">
<a class="sidebar-item" href="#Enums">Enums</a>
</li>
<ul>
- {{#Obj}}
+ {{#Enums}}
<li class="sidebar-item-container">
- <a class="sidebar-item" href="#{{ID}}">{{EnumName}}</a>
+ <a class="sidebar-item" href="#{{USR}}">{{Name}}</a>
</li>
- {{/Obj}}
+ {{/Enums}}
</ul>
- {{/Enums}}
- {{#Record}}
+ {{/HasEnums}}
+ {{#HasRecords}}
<li class="sidebar-section">
<a class="sidebar-item" href="#Classes">Inner Classes</a>
</li>
<ul>
- {{#Links}}
+ {{#Records}}
<li class="sidebar-item-container">
- <a class="sidebar-item" href="#{{ID}}">{{Name}}</a>
+ <a class="sidebar-item" href="#{{USR}}">{{Name}}</a>
</li>
- {{/Links}}
+ {{/Records}}
</ul>
- {{/Record}}
+ {{/HasRecrods}}
</ul>
</div>
<div class="resizer" id="resizer"></div>
<div class="content">
- {{#Enums}}
+ {{#HasEnums}}
<section id="Enums" class="section-container">
<h2>Enumerations</h2>
<div>
- {{#Obj}}
+ {{#Enums}}
{{>EnumPartial}}
- {{/Obj}}
+ {{/Enums}}
</div>
</section>
- {{/Enums}}
- {{#Record}}
+ {{/HasEnums}}
+
+ {{#HasRecords}}
<section id="Classes" class="section-container">
<h2>Inner Classes</h2>
<ul class="class-container">
- {{#Links}}
- <li id="{{ID}}" style="max-height: 40px;">
- <a href="{{Link}}"><pre><code class="language-cpp code-clang-doc" >class {{Name}}</code></pre></a>
+ {{#Records}}
+ <li id="{{USR}}" style="max-height: 40px;">
+ <a href="{{DocumentationFileName}}.html">
+ <pre>
+ <code class="language-cpp code-clang-doc">class {{Name}}</code>
+ </pre>
+ </a>
</li>
- {{/Links}}
+ {{/Records}}
</ul>
+ {{/HasRecords}}
</section>
- {{/Record}}
</div>
</div>
</main>
diff --git a/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp b/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp
index 9f73f47..568cb2b 100644
--- a/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp
+++ b/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp
@@ -454,7 +454,7 @@ int includeFixerMain(int argc, const char **argv) {
// Set up a new source manager for applying the resulting replacements.
DiagnosticOptions DiagOpts;
- DiagnosticsEngine Diagnostics(new DiagnosticIDs, DiagOpts);
+ DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts);
TextDiagnosticPrinter DiagnosticPrinter(outs(), DiagOpts);
SourceManager SM(Diagnostics, tool.getFiles());
Diagnostics.setClient(&DiagnosticPrinter, false);
diff --git a/clang-tools-extra/clang-move/tool/ClangMove.cpp b/clang-tools-extra/clang-move/tool/ClangMove.cpp
index 750eb95..1be3cb1 100644
--- a/clang-tools-extra/clang-move/tool/ClangMove.cpp
+++ b/clang-tools-extra/clang-move/tool/ClangMove.cpp
@@ -178,9 +178,8 @@ int main(int argc, const char **argv) {
DiagnosticOptions DiagOpts;
clang::TextDiagnosticPrinter DiagnosticPrinter(errs(), DiagOpts);
- DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), DiagOpts,
- &DiagnosticPrinter, false);
+ DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts,
+ &DiagnosticPrinter, false);
auto &FileMgr = Tool.getFiles();
SourceManager SM(Diagnostics, FileMgr);
Rewriter Rewrite(SM, LangOptions());
diff --git a/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp b/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp
index 0350252..fbfce07 100644
--- a/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp
+++ b/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp
@@ -74,9 +74,8 @@ int main(int argc, const char **argv) {
LangOptions DefaultLangOptions;
DiagnosticOptions DiagOpts;
TextDiagnosticPrinter DiagnosticPrinter(errs(), DiagOpts);
- DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), DiagOpts,
- &DiagnosticPrinter, false);
+ DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts,
+ &DiagnosticPrinter, false);
auto &FileMgr = Tool.getFiles();
SourceManager Sources(Diagnostics, FileMgr);
diff --git a/clang-tools-extra/clang-tidy/.clang-tidy b/clang-tools-extra/clang-tidy/.clang-tidy
index 2443c97..0a2ea24 100644
--- a/clang-tools-extra/clang-tidy/.clang-tidy
+++ b/clang-tools-extra/clang-tidy/.clang-tidy
@@ -22,7 +22,6 @@ Checks: >
-performance-unnecessary-value-param,
readability-*,
-readability-avoid-nested-conditional-operator,
- -readability-avoid-return-with-void-value,
-readability-braces-around-statements,
-readability-container-contains,
-readability-convert-member-functions-to-static,
diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp
index e84be04..4ae2864 100644
--- a/clang-tools-extra/clang-tidy/ClangTidy.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp
@@ -96,8 +96,7 @@ public:
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS)
: Files(FileSystemOptions(), std::move(BaseFS)),
DiagPrinter(new TextDiagnosticPrinter(llvm::outs(), DiagOpts)),
- Diags(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), DiagOpts,
- DiagPrinter),
+ Diags(DiagnosticIDs::create(), DiagOpts, DiagPrinter),
SourceMgr(Diags, Files), Context(Context), ApplyFixes(ApplyFixes) {
DiagOpts.ShowColors = Context.getOptions().UseColor.value_or(
llvm::sys::Process::StandardOutHasColors());
@@ -570,7 +569,7 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
ClangTidyDiagnosticConsumer DiagConsumer(Context, nullptr, true, ApplyAnyFix);
auto DiagOpts = std::make_unique<DiagnosticOptions>();
- DiagnosticsEngine DE(new DiagnosticIDs(), *DiagOpts, &DiagConsumer,
+ DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer,
/*ShouldOwnClient=*/false);
Context.setDiagnosticsEngine(std::move(DiagOpts), &DE);
Tool.setDiagnosticConsumer(&DiagConsumer);
diff --git a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp
index 2c17cd3..5e705f7 100644
--- a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp
+++ b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp
@@ -71,7 +71,7 @@ ExpandModularHeadersPPCallbacks::ExpandModularHeadersPPCallbacks(
InMemoryFs(new llvm::vfs::InMemoryFileSystem),
Sources(Compiler.getSourceManager()),
// Forward the new diagnostics to the original DiagnosticConsumer.
- Diags(new DiagnosticIDs, DiagOpts,
+ Diags(DiagnosticIDs::create(), DiagOpts,
new ForwardingDiagnosticConsumer(Compiler.getDiagnosticClient())),
LangOpts(Compiler.getLangOpts()), HSOpts(Compiler.getHeaderSearchOpts()) {
// Add a FileSystem containing the extra files needed in place of modular
diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index ed1fd13..824ebdf 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -38,6 +38,7 @@
#include "IncorrectRoundingsCheck.h"
#include "InfiniteLoopCheck.h"
#include "IntegerDivisionCheck.h"
+#include "InvalidEnumDefaultInitializationCheck.h"
#include "LambdaFunctionNameCheck.h"
#include "MacroParenthesesCheck.h"
#include "MacroRepeatedSideEffectsCheck.h"
@@ -165,6 +166,8 @@ public:
CheckFactories.registerCheck<InfiniteLoopCheck>("bugprone-infinite-loop");
CheckFactories.registerCheck<IntegerDivisionCheck>(
"bugprone-integer-division");
+ CheckFactories.registerCheck<InvalidEnumDefaultInitializationCheck>(
+ "bugprone-invalid-enum-default-initialization");
CheckFactories.registerCheck<LambdaFunctionNameCheck>(
"bugprone-lambda-function-name");
CheckFactories.registerCheck<MacroParenthesesCheck>(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index d862794..59928e5 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -30,6 +30,7 @@ add_clang_library(clangTidyBugproneModule STATIC
InaccurateEraseCheck.cpp
IncorrectEnableIfCheck.cpp
IncorrectEnableSharedFromThisCheck.cpp
+ InvalidEnumDefaultInitializationCheck.cpp
UnintendedCharOstreamOutputCheck.cpp
ReturnConstRefFromParameterCheck.cpp
SuspiciousStringviewDataUsageCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp
new file mode 100644
index 0000000..33fcf45
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp
@@ -0,0 +1,180 @@
+//===--- InvalidEnumDefaultInitializationCheck.cpp - clang-tidy -----------===//
+//
+// 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 "InvalidEnumDefaultInitializationCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/TypeVisitor.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include <algorithm>
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+namespace {
+
+bool isCompleteAndHasNoZeroValue(const EnumDecl *D) {
+ const EnumDecl *Definition = D->getDefinition();
+ return Definition && Definition->isComplete() &&
+ !Definition->enumerators().empty() &&
+ std::none_of(Definition->enumerator_begin(),
+ Definition->enumerator_end(),
+ [](const EnumConstantDecl *Value) {
+ return Value->getInitVal().isZero();
+ });
+}
+
+AST_MATCHER(EnumDecl, isCompleteAndHasNoZeroValue) {
+ return isCompleteAndHasNoZeroValue(&Node);
+}
+
+// Find an initialization which initializes the value (if it has enum type) to a
+// default zero value.
+AST_MATCHER(Expr, isEmptyInit) {
+ if (isa<CXXScalarValueInitExpr, ImplicitValueInitExpr>(&Node))
+ return true;
+ if (const auto *Init = dyn_cast<InitListExpr>(&Node)) {
+ if (Init->getNumInits() == 0)
+ return true;
+ }
+ return false;
+}
+
+AST_MATCHER(InitListExpr, hasArrayFiller) { return Node.hasArrayFiller(); }
+
+// Check if any type has a "child" type that is an enum without zero value.
+// The "child" type can be an array element type or member type of a record
+// type (or a recursive combination of these). In this case, if the "root" type
+// is statically initialized, the enum component is initialized to zero.
+class FindEnumMember : public TypeVisitor<FindEnumMember, bool> {
+public:
+ const EnumType *FoundEnum = nullptr;
+
+ bool VisitType(const Type *T) {
+ const Type *DesT = T->getUnqualifiedDesugaredType();
+ if (DesT != T)
+ return Visit(DesT);
+ return false;
+ }
+ bool VisitArrayType(const ArrayType *T) {
+ return Visit(T->getElementType().getTypePtr());
+ }
+ bool VisitConstantArrayType(const ConstantArrayType *T) {
+ return Visit(T->getElementType().getTypePtr());
+ }
+ bool VisitEnumType(const EnumType *T) {
+ if (isCompleteAndHasNoZeroValue(T->getDecl())) {
+ FoundEnum = T;
+ return true;
+ }
+ return false;
+ }
+ bool VisitRecordType(const RecordType *T) {
+ const RecordDecl *RD = T->getDecl();
+ if (RD->isUnion())
+ return false;
+ auto VisitField = [this](const FieldDecl *F) {
+ return Visit(F->getType().getTypePtr());
+ };
+ return llvm::any_of(RD->fields(), VisitField);
+ }
+};
+
+} // namespace
+
+InvalidEnumDefaultInitializationCheck::InvalidEnumDefaultInitializationCheck(
+ StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+
+void InvalidEnumDefaultInitializationCheck::registerMatchers(
+ MatchFinder *Finder) {
+ auto EnumWithoutZeroValue = enumType(
+ hasDeclaration(enumDecl(isCompleteAndHasNoZeroValue()).bind("enum")));
+ auto EnumOrArrayOfEnum = qualType(hasUnqualifiedDesugaredType(
+ anyOf(EnumWithoutZeroValue,
+ arrayType(hasElementType(qualType(
+ hasUnqualifiedDesugaredType(EnumWithoutZeroValue)))))));
+ Finder->addMatcher(
+ expr(isEmptyInit(), hasType(EnumOrArrayOfEnum)).bind("expr"), this);
+
+ // Array initialization can contain an "array filler" for the (syntactically)
+ // unspecified elements. This expression is not found by AST matchers and can
+ // have any type (the array's element type). This is an implicitly generated
+ // initialization, so if the type contains somewhere an enum without zero
+ // enumerator, the zero initialization applies here. We search this array
+ // element type for the specific enum type manually when this matcher matches.
+ Finder->addMatcher(initListExpr(hasArrayFiller()).bind("array_filler_expr"),
+ this);
+}
+
+void InvalidEnumDefaultInitializationCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ const auto *InitExpr = Result.Nodes.getNodeAs<Expr>("expr");
+ const auto *Enum = Result.Nodes.getNodeAs<EnumDecl>("enum");
+ if (!InitExpr) {
+ const auto *InitList =
+ Result.Nodes.getNodeAs<InitListExpr>("array_filler_expr");
+ // Initialization of omitted array elements with array filler was found.
+ // Check the type for enum without zero value.
+ // FIXME: In this way only one enum-typed value is found, not all of these.
+ FindEnumMember Finder;
+ if (!Finder.Visit(InitList->getArrayFiller()->getType().getTypePtr()))
+ return;
+ InitExpr = InitList;
+ Enum = Finder.FoundEnum->getDecl();
+ }
+
+ if (!InitExpr || !Enum)
+ return;
+
+ ASTContext &ACtx = Enum->getASTContext();
+ SourceLocation Loc = InitExpr->getExprLoc();
+ if (Loc.isInvalid()) {
+ if (isa<ImplicitValueInitExpr, InitListExpr>(InitExpr)) {
+ DynTypedNodeList Parents = ACtx.getParents(*InitExpr);
+ if (Parents.empty())
+ return;
+
+ if (const auto *Ctor = Parents[0].get<CXXConstructorDecl>()) {
+ // Try to find member initializer with the found expression and get the
+ // source location from it.
+ CXXCtorInitializer *const *CtorInit = std::find_if(
+ Ctor->init_begin(), Ctor->init_end(),
+ [InitExpr](const CXXCtorInitializer *Init) {
+ return Init->isMemberInitializer() && Init->getInit() == InitExpr;
+ });
+ if (!CtorInit)
+ return;
+ Loc = (*CtorInit)->getLParenLoc();
+ } else if (const auto *InitList = Parents[0].get<InitListExpr>()) {
+ // The expression may be implicitly generated for an initialization.
+ // Search for a parent initialization list with valid source location.
+ while (InitList->getExprLoc().isInvalid()) {
+ DynTypedNodeList Parents = ACtx.getParents(*InitList);
+ if (Parents.empty())
+ return;
+ InitList = Parents[0].get<InitListExpr>();
+ if (!InitList)
+ return;
+ }
+ Loc = InitList->getExprLoc();
+ }
+ }
+ // If still not found a source location, omit the warning.
+ // Ideally all such cases (if they exist) should be handled to make the
+ // check more precise.
+ if (Loc.isInvalid())
+ return;
+ }
+ diag(Loc, "enum value of type %0 initialized with invalid value of 0, "
+ "enum doesn't have a zero-value enumerator")
+ << Enum;
+ diag(Enum->getLocation(), "enum is defined here", DiagnosticIDs::Note);
+}
+
+} // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.h b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.h
new file mode 100644
index 0000000..0746c4d
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.h
@@ -0,0 +1,31 @@
+//===--- InvalidEnumDefaultInitializationCheck.h - clang-tidy -*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INVALIDENUMDEFAULTINITIALIZATIONCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INVALIDENUMDEFAULTINITIALIZATIONCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::bugprone {
+
+/// Detects default initialization (to 0) of variables with `enum` type where
+/// the enum has no enumerator with value of 0.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/invalid-enum-default-initialization.html
+class InvalidEnumDefaultInitializationCheck : public ClangTidyCheck {
+public:
+ InvalidEnumDefaultInitializationCheck(StringRef Name,
+ ClangTidyContext *Context);
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace clang::tidy::bugprone
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INVALIDENUMDEFAULTINITIALIZATIONCHECK_H
diff --git a/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp
index 8b2ca69..5378223 100644
--- a/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp
@@ -381,10 +381,11 @@ void NarrowingConversionsCheck::diagNarrowTypeOrConstant(
const Expr &Rhs) {
APValue Constant = getConstantExprValue(Context, Rhs);
if (Constant.isInt())
- return diagNarrowIntegerConstant(SourceLoc, Lhs, Rhs, Constant.getInt());
- if (Constant.isFloat())
- return diagNarrowConstant(SourceLoc, Lhs, Rhs);
- return diagNarrowType(SourceLoc, Lhs, Rhs);
+ diagNarrowIntegerConstant(SourceLoc, Lhs, Rhs, Constant.getInt());
+ else if (Constant.isFloat())
+ diagNarrowConstant(SourceLoc, Lhs, Rhs);
+ else
+ diagNarrowType(SourceLoc, Lhs, Rhs);
}
void NarrowingConversionsCheck::handleIntegralCast(const ASTContext &Context,
@@ -460,10 +461,10 @@ void NarrowingConversionsCheck::handleFloatingToIntegral(
llvm::APFloat FloatConstant(0.0);
if (getFloatingConstantExprValue(Context, Rhs, FloatConstant)) {
if (!isFloatExactlyRepresentable(Context, FloatConstant, Lhs.getType()))
- return diagNarrowConstant(SourceLoc, Lhs, Rhs);
+ diagNarrowConstant(SourceLoc, Lhs, Rhs);
- if (PedanticMode)
- return diagConstantCast(SourceLoc, Lhs, Rhs);
+ else if (PedanticMode)
+ diagConstantCast(SourceLoc, Lhs, Rhs);
return;
}
@@ -478,7 +479,7 @@ void NarrowingConversionsCheck::handleFloatingToIntegral(
void NarrowingConversionsCheck::handleFloatingToBoolean(
const ASTContext &Context, SourceLocation SourceLoc, const Expr &Lhs,
const Expr &Rhs) {
- return diagNarrowTypeOrConstant(Context, SourceLoc, Lhs, Rhs);
+ diagNarrowTypeOrConstant(Context, SourceLoc, Lhs, Rhs);
}
void NarrowingConversionsCheck::handleBooleanToSignedIntegral(
@@ -532,19 +533,20 @@ void NarrowingConversionsCheck::handleBinaryOperator(const ASTContext &Context,
if (LhsType == RhsType)
return;
if (RhsType->getKind() == BuiltinType::Bool && LhsType->isSignedInteger())
- return handleBooleanToSignedIntegral(Context, SourceLoc, Lhs, Rhs);
- if (RhsType->isInteger() && LhsType->getKind() == BuiltinType::Bool)
- return handleIntegralToBoolean(Context, SourceLoc, Lhs, Rhs);
- if (RhsType->isInteger() && LhsType->isFloatingPoint())
- return handleIntegralToFloating(Context, SourceLoc, Lhs, Rhs);
- if (RhsType->isInteger() && LhsType->isInteger())
- return handleIntegralCast(Context, SourceLoc, Lhs, Rhs);
- if (RhsType->isFloatingPoint() && LhsType->getKind() == BuiltinType::Bool)
- return handleFloatingToBoolean(Context, SourceLoc, Lhs, Rhs);
- if (RhsType->isFloatingPoint() && LhsType->isInteger())
- return handleFloatingToIntegral(Context, SourceLoc, Lhs, Rhs);
- if (RhsType->isFloatingPoint() && LhsType->isFloatingPoint())
- return handleFloatingCast(Context, SourceLoc, Lhs, Rhs);
+ handleBooleanToSignedIntegral(Context, SourceLoc, Lhs, Rhs);
+ else if (RhsType->isInteger() && LhsType->getKind() == BuiltinType::Bool)
+ handleIntegralToBoolean(Context, SourceLoc, Lhs, Rhs);
+ else if (RhsType->isInteger() && LhsType->isFloatingPoint())
+ handleIntegralToFloating(Context, SourceLoc, Lhs, Rhs);
+ else if (RhsType->isInteger() && LhsType->isInteger())
+ handleIntegralCast(Context, SourceLoc, Lhs, Rhs);
+ else if (RhsType->isFloatingPoint() &&
+ LhsType->getKind() == BuiltinType::Bool)
+ handleFloatingToBoolean(Context, SourceLoc, Lhs, Rhs);
+ else if (RhsType->isFloatingPoint() && LhsType->isInteger())
+ handleFloatingToIntegral(Context, SourceLoc, Lhs, Rhs);
+ else if (RhsType->isFloatingPoint() && LhsType->isFloatingPoint())
+ handleFloatingCast(Context, SourceLoc, Lhs, Rhs);
}
bool NarrowingConversionsCheck::handleConditionalOperator(
@@ -577,21 +579,28 @@ void NarrowingConversionsCheck::handleImplicitCast(
SourceLocation SourceLoc = Lhs.getExprLoc();
switch (Cast.getCastKind()) {
case CK_BooleanToSignedIntegral:
- return handleBooleanToSignedIntegral(Context, SourceLoc, Lhs, Rhs);
+ handleBooleanToSignedIntegral(Context, SourceLoc, Lhs, Rhs);
+ return;
case CK_IntegralToBoolean:
- return handleIntegralToBoolean(Context, SourceLoc, Lhs, Rhs);
+ handleIntegralToBoolean(Context, SourceLoc, Lhs, Rhs);
+ return;
case CK_IntegralToFloating:
- return handleIntegralToFloating(Context, SourceLoc, Lhs, Rhs);
+ handleIntegralToFloating(Context, SourceLoc, Lhs, Rhs);
+ return;
case CK_IntegralCast:
- return handleIntegralCast(Context, SourceLoc, Lhs, Rhs);
+ handleIntegralCast(Context, SourceLoc, Lhs, Rhs);
+ return;
case CK_FloatingToBoolean:
- return handleFloatingToBoolean(Context, SourceLoc, Lhs, Rhs);
+ handleFloatingToBoolean(Context, SourceLoc, Lhs, Rhs);
+ return;
case CK_FloatingToIntegral:
- return handleFloatingToIntegral(Context, SourceLoc, Lhs, Rhs);
+ handleFloatingToIntegral(Context, SourceLoc, Lhs, Rhs);
+ return;
case CK_FloatingCast:
- return handleFloatingCast(Context, SourceLoc, Lhs, Rhs);
+ handleFloatingCast(Context, SourceLoc, Lhs, Rhs);
+ return;
default:
- break;
+ return;
}
}
@@ -610,9 +619,10 @@ void NarrowingConversionsCheck::handleBinaryOperator(const ASTContext &Context,
void NarrowingConversionsCheck::check(const MatchFinder::MatchResult &Result) {
if (const auto *Op = Result.Nodes.getNodeAs<BinaryOperator>("binary_op"))
- return handleBinaryOperator(*Result.Context, *Op);
- if (const auto *Cast = Result.Nodes.getNodeAs<ImplicitCastExpr>("cast"))
- return handleImplicitCast(*Result.Context, *Cast);
- llvm_unreachable("must be binary operator or cast expression");
+ handleBinaryOperator(*Result.Context, *Op);
+ else if (const auto *Cast = Result.Nodes.getNodeAs<ImplicitCastExpr>("cast"))
+ handleImplicitCast(*Result.Context, *Cast);
+ else
+ llvm_unreachable("must be binary operator or cast expression");
}
} // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
index ea3b8b8..dfd3cbf 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
@@ -74,17 +74,25 @@ void SignedCharMisuseCheck::registerMatchers(MatchFinder *Finder) {
charCastExpression(true, IntegerType, "signedCastExpression");
const auto UnSignedCharCastExpr =
charCastExpression(false, IntegerType, "unsignedCastExpression");
+ const bool IsC23 = getLangOpts().C23;
- // Catch assignments with signed char -> integer conversion.
+ // Catch assignments with signed char -> integer conversion. Ignore false
+ // positives on C23 enums with the fixed underlying type of signed char.
const auto AssignmentOperatorExpr =
expr(binaryOperator(hasOperatorName("="), hasLHS(hasType(IntegerType)),
- hasRHS(SignedCharCastExpr)));
+ hasRHS(SignedCharCastExpr)),
+ IsC23 ? unless(binaryOperator(
+ hasLHS(hasType(hasCanonicalType(enumType())))))
+ : Matcher<Stmt>(anything()));
Finder->addMatcher(AssignmentOperatorExpr, this);
- // Catch declarations with signed char -> integer conversion.
- const auto Declaration = varDecl(isDefinition(), hasType(IntegerType),
- hasInitializer(SignedCharCastExpr));
+ // Catch declarations with signed char -> integer conversion. Ignore false
+ // positives on C23 enums with the fixed underlying type of signed char.
+ const auto Declaration = varDecl(
+ isDefinition(), hasType(IntegerType), hasInitializer(SignedCharCastExpr),
+ IsC23 ? unless(hasType(hasCanonicalType(enumType())))
+ : Matcher<VarDecl>(anything()));
Finder->addMatcher(Declaration, this);
diff --git a/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
index 1f432c4..c4c4267 100644
--- a/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
@@ -69,6 +69,28 @@ void UnhandledSelfAssignmentCheck::registerMatchers(MatchFinder *Finder) {
cxxMethodDecl(unless(hasDescendant(cxxMemberCallExpr(callee(cxxMethodDecl(
hasName("operator="), ofClass(equalsBoundNode("class"))))))));
+ // Checking that some kind of constructor is called and followed by a `swap`:
+ // T& operator=(const T& other) {
+ // T tmp{this->internal_data(), some, other, args};
+ // swap(tmp);
+ // return *this;
+ // }
+ const auto HasCopyAndSwap = cxxMethodDecl(
+ ofClass(cxxRecordDecl()),
+ hasBody(compoundStmt(
+ hasDescendant(
+ varDecl(hasType(cxxRecordDecl(equalsBoundNode("class"))))
+ .bind("tmp_var")),
+ hasDescendant(stmt(anyOf(
+ cxxMemberCallExpr(hasArgument(
+ 0, declRefExpr(to(varDecl(equalsBoundNode("tmp_var")))))),
+ callExpr(
+ callee(functionDecl(hasName("swap"))), argumentCountIs(2),
+ hasAnyArgument(
+ declRefExpr(to(varDecl(equalsBoundNode("tmp_var"))))),
+ hasAnyArgument(unaryOperator(has(cxxThisExpr()),
+ hasOperatorName("*"))))))))));
+
DeclarationMatcher AdditionalMatcher = cxxMethodDecl();
if (WarnOnlyIfThisHasSuspiciousField) {
// Matcher for standard smart pointers.
@@ -89,14 +111,14 @@ void UnhandledSelfAssignmentCheck::registerMatchers(MatchFinder *Finder) {
hasType(arrayType())))))));
}
- Finder->addMatcher(cxxMethodDecl(ofClass(cxxRecordDecl().bind("class")),
- isCopyAssignmentOperator(), IsUserDefined,
- HasReferenceParam, HasNoSelfCheck,
- unless(HasNonTemplateSelfCopy),
- unless(HasTemplateSelfCopy),
- HasNoNestedSelfAssign, AdditionalMatcher)
- .bind("copyAssignmentOperator"),
- this);
+ Finder->addMatcher(
+ cxxMethodDecl(
+ ofClass(cxxRecordDecl().bind("class")), isCopyAssignmentOperator(),
+ IsUserDefined, HasReferenceParam, HasNoSelfCheck,
+ unless(HasNonTemplateSelfCopy), unless(HasTemplateSelfCopy),
+ unless(HasCopyAndSwap), HasNoNestedSelfAssign, AdditionalMatcher)
+ .bind("copyAssignmentOperator"),
+ this);
}
void UnhandledSelfAssignmentCheck::check(
diff --git a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
index 3232f6e..41386cd 100644
--- a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
@@ -11,6 +11,7 @@ add_clang_library(clangTidyLLVMModule STATIC
PreferRegisterOverUnsignedCheck.cpp
PreferStaticOverAnonymousNamespaceCheck.cpp
TwineLocalCheck.cpp
+ UseNewMLIROpBuilderCheck.cpp
LINK_LIBS
clangTidy
@@ -29,4 +30,5 @@ clang_target_link_libraries(clangTidyLLVMModule
clangBasic
clangLex
clangTooling
+ clangTransformer
)
diff --git a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
index 0754530..c7c61fd 100644
--- a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
@@ -18,6 +18,7 @@
#include "PreferRegisterOverUnsignedCheck.h"
#include "PreferStaticOverAnonymousNamespaceCheck.h"
#include "TwineLocalCheck.h"
+#include "UseNewMLIROpBuilderCheck.h"
namespace clang::tidy {
namespace llvm_check {
@@ -40,6 +41,8 @@ public:
CheckFactories.registerCheck<readability::QualifiedAutoCheck>(
"llvm-qualified-auto");
CheckFactories.registerCheck<TwineLocalCheck>("llvm-twine-local");
+ CheckFactories.registerCheck<UseNewMlirOpBuilderCheck>(
+ "llvm-use-new-mlir-op-builder");
}
ClangTidyOptions getModuleOptions() override {
diff --git a/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.cpp b/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.cpp
new file mode 100644
index 0000000..4722199
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.cpp
@@ -0,0 +1,139 @@
+//===--- UseNewMLIROpBuilderCheck.cpp - clang-tidy ------------------------===//
+//
+// 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 "UseNewMLIROpBuilderCheck.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Transformer/RangeSelector.h"
+#include "clang/Tooling/Transformer/RewriteRule.h"
+#include "clang/Tooling/Transformer/SourceCode.h"
+#include "clang/Tooling/Transformer/Stencil.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FormatVariadic.h"
+
+namespace clang::tidy::llvm_check {
+namespace {
+
+using namespace ::clang::ast_matchers;
+using namespace ::clang::transformer;
+
+EditGenerator rewrite(RangeSelector Call, RangeSelector Builder,
+ RangeSelector CallArgs) {
+ // This is using an EditGenerator rather than ASTEdit as we want to warn even
+ // if in macro.
+ return [Call = std::move(Call), Builder = std::move(Builder),
+ CallArgs =
+ std::move(CallArgs)](const MatchFinder::MatchResult &Result)
+ -> Expected<SmallVector<transformer::Edit, 1>> {
+ Expected<CharSourceRange> CallRange = Call(Result);
+ if (!CallRange)
+ return CallRange.takeError();
+ SourceManager &SM = *Result.SourceManager;
+ const LangOptions &LangOpts = Result.Context->getLangOpts();
+ SourceLocation Begin = CallRange->getBegin();
+
+ // This will result in just a warning and no edit.
+ bool InMacro = CallRange->getBegin().isMacroID();
+ if (InMacro) {
+ while (SM.isMacroArgExpansion(Begin))
+ Begin = SM.getImmediateExpansionRange(Begin).getBegin();
+ Edit WarnOnly;
+ WarnOnly.Kind = EditKind::Range;
+ WarnOnly.Range = CharSourceRange::getCharRange(Begin, Begin);
+ return SmallVector<Edit, 1>({WarnOnly});
+ }
+
+ // This will try to extract the template argument as written so that the
+ // rewritten code looks closest to original.
+ auto NextToken = [&](std::optional<Token> CurrentToken) {
+ if (!CurrentToken)
+ return CurrentToken;
+ if (CurrentToken->getEndLoc() >= CallRange->getEnd())
+ return std::optional<Token>();
+ return clang::Lexer::findNextToken(CurrentToken->getLocation(), SM,
+ LangOpts);
+ };
+ std::optional<Token> LessToken =
+ clang::Lexer::findNextToken(Begin, SM, LangOpts);
+ while (LessToken && LessToken->getKind() != clang::tok::less) {
+ LessToken = NextToken(LessToken);
+ }
+ if (!LessToken) {
+ return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
+ "missing '<' token");
+ }
+ std::optional<Token> EndToken = NextToken(LessToken);
+ for (std::optional<Token> GreaterToken = NextToken(EndToken);
+ GreaterToken && GreaterToken->getKind() != clang::tok::greater;
+ GreaterToken = NextToken(GreaterToken)) {
+ EndToken = GreaterToken;
+ }
+ if (!EndToken) {
+ return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
+ "missing '>' token");
+ }
+
+ Expected<CharSourceRange> BuilderRange = Builder(Result);
+ if (!BuilderRange)
+ return BuilderRange.takeError();
+ Expected<CharSourceRange> CallArgsRange = CallArgs(Result);
+ if (!CallArgsRange)
+ return CallArgsRange.takeError();
+
+ // Helper for concatting below.
+ auto GetText = [&](const CharSourceRange &Range) {
+ return clang::Lexer::getSourceText(Range, SM, LangOpts);
+ };
+
+ Edit Replace;
+ Replace.Kind = EditKind::Range;
+ Replace.Range = *CallRange;
+ std::string CallArgsStr;
+ // Only emit args if there are any.
+ if (auto CallArgsText = GetText(*CallArgsRange).ltrim();
+ !CallArgsText.rtrim().empty()) {
+ CallArgsStr = llvm::formatv(", {}", CallArgsText);
+ }
+ Replace.Replacement =
+ llvm::formatv("{}::create({}{})",
+ GetText(CharSourceRange::getTokenRange(
+ LessToken->getEndLoc(), EndToken->getLastLoc())),
+ GetText(*BuilderRange), CallArgsStr);
+
+ return SmallVector<Edit, 1>({Replace});
+ };
+}
+
+RewriteRuleWith<std::string> useNewMlirOpBuilderCheckRule() {
+ Stencil message = cat("use 'OpType::create(builder, ...)' instead of "
+ "'builder.create<OpType>(...)'");
+ // Match a create call on an OpBuilder.
+ ast_matchers::internal::Matcher<Stmt> base =
+ cxxMemberCallExpr(
+ on(expr(hasType(
+ cxxRecordDecl(isSameOrDerivedFrom("::mlir::OpBuilder"))))
+ .bind("builder")),
+ callee(cxxMethodDecl(hasTemplateArgument(0, templateArgument()))),
+ callee(cxxMethodDecl(hasName("create"))))
+ .bind("call");
+ return applyFirst(
+ // Attempt rewrite given an lvalue builder, else just warn.
+ {makeRule(cxxMemberCallExpr(unless(on(cxxTemporaryObjectExpr())), base),
+ rewrite(node("call"), node("builder"), callArgs("call")),
+ message),
+ makeRule(base, noopEdit(node("call")), message)});
+}
+} // namespace
+
+UseNewMlirOpBuilderCheck::UseNewMlirOpBuilderCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : TransformerClangTidyCheck(useNewMlirOpBuilderCheckRule(), Name, Context) {
+}
+
+} // namespace clang::tidy::llvm_check
diff --git a/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.h b/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.h
new file mode 100644
index 0000000..813a23c
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.h
@@ -0,0 +1,29 @@
+//===--- UseNewMLIROpBuilderCheck.h - clang-tidy ----------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_USENEWMLIROPBUILDERCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_USENEWMLIROPBUILDERCHECK_H
+
+#include "../utils/TransformerClangTidyCheck.h"
+
+namespace clang::tidy::llvm_check {
+
+/// Checks for uses of MLIR's old/to be deprecated `OpBuilder::create<T>` form
+/// and suggests using `T::create` instead.
+class UseNewMlirOpBuilderCheck : public utils::TransformerClangTidyCheck {
+public:
+ UseNewMlirOpBuilderCheck(StringRef Name, ClangTidyContext *Context);
+
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return getLangOpts().CPlusPlus;
+ }
+};
+
+} // namespace clang::tidy::llvm_check
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_USENEWMLIROPBUILDERCHECK_H
diff --git a/clang-tools-extra/clang-tidy/misc/HeaderIncludeCycleCheck.cpp b/clang-tools-extra/clang-tidy/misc/HeaderIncludeCycleCheck.cpp
index 21d443a..1f6ceda 100644
--- a/clang-tools-extra/clang-tidy/misc/HeaderIncludeCycleCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/HeaderIncludeCycleCheck.cpp
@@ -13,8 +13,8 @@
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/Regex.h"
#include <algorithm>
-#include <deque>
#include <optional>
+#include <vector>
using namespace clang::ast_matchers;
@@ -23,8 +23,8 @@ namespace clang::tidy::misc {
namespace {
struct Include {
- FileID Id;
- llvm::StringRef Name;
+ const FileEntry *File;
+ StringRef Name;
SourceLocation Loc;
};
@@ -50,31 +50,27 @@ public:
if (Reason != EnterFile && Reason != ExitFile)
return;
- FileID Id = SM.getFileID(Loc);
+ const FileID Id = SM.getFileID(Loc);
if (Id.isInvalid())
return;
+ const FileEntry *NewFile = SM.getFileEntryForID(Id);
+ const FileEntry *PrevFile = SM.getFileEntryForID(PrevFID);
+
if (Reason == ExitFile) {
- if ((Files.size() > 1U) && (Files.back().Id == PrevFID) &&
- (Files[Files.size() - 2U].Id == Id))
+ if ((Files.size() > 1U) && (Files.back().File == PrevFile) &&
+ (Files[Files.size() - 2U].File == NewFile))
Files.pop_back();
return;
}
- if (!Files.empty() && Files.back().Id == Id)
+ if (!Files.empty() && Files.back().File == NewFile)
return;
- std::optional<llvm::StringRef> FilePath = SM.getNonBuiltinFilenameForID(Id);
- llvm::StringRef FileName =
- FilePath ? llvm::sys::path::filename(*FilePath) : llvm::StringRef();
-
- if (!NextToEnter)
- NextToEnter = Include{Id, FileName, SourceLocation()};
-
- assert(NextToEnter->Name == FileName);
- NextToEnter->Id = Id;
- Files.emplace_back(*NextToEnter);
- NextToEnter.reset();
+ const std::optional<StringRef> FilePath = SM.getNonBuiltinFilenameForID(Id);
+ const StringRef FileName =
+ FilePath ? llvm::sys::path::filename(*FilePath) : StringRef();
+ Files.push_back({NewFile, FileName, std::exchange(NextToEnter, {})});
}
void InclusionDirective(SourceLocation, const Token &, StringRef FilePath,
@@ -85,36 +81,26 @@ public:
if (FileType != clang::SrcMgr::C_User)
return;
- llvm::StringRef FileName = llvm::sys::path::filename(FilePath);
- NextToEnter = {FileID(), FileName, Range.getBegin()};
+ NextToEnter = Range.getBegin();
if (!File)
return;
- FileID Id = SM.translateFile(*File);
- if (Id.isInvalid())
- return;
-
- checkForDoubleInclude(Id, FileName, Range.getBegin());
- }
-
- void EndOfMainFile() override {
- if (!Files.empty() && Files.back().Id == SM.getMainFileID())
- Files.pop_back();
-
- assert(Files.empty());
+ checkForDoubleInclude(&File->getFileEntry(),
+ llvm::sys::path::filename(FilePath),
+ Range.getBegin());
}
- void checkForDoubleInclude(FileID Id, llvm::StringRef FileName,
+ void checkForDoubleInclude(const FileEntry *File, StringRef FileName,
SourceLocation Loc) {
- auto It =
- std::find_if(Files.rbegin(), Files.rend(),
- [&](const Include &Entry) { return Entry.Id == Id; });
+ const auto It =
+ llvm::find_if(llvm::reverse(Files),
+ [&](const Include &Entry) { return Entry.File == File; });
if (It == Files.rend())
return;
- const std::optional<StringRef> FilePath = SM.getNonBuiltinFilenameForID(Id);
- if (!FilePath || isFileIgnored(*FilePath))
+ const StringRef FilePath = File->tryGetRealPathName();
+ if (FilePath.empty() || isFileIgnored(FilePath))
return;
if (It == Files.rbegin()) {
@@ -144,9 +130,19 @@ public:
});
}
+#ifndef NDEBUG
+ void EndOfMainFile() override {
+ if (!Files.empty() &&
+ Files.back().File == SM.getFileEntryForID(SM.getMainFileID()))
+ Files.pop_back();
+
+ assert(Files.empty());
+ }
+#endif
+
private:
- std::deque<Include> Files;
- std::optional<Include> NextToEnter;
+ std::vector<Include> Files;
+ SourceLocation NextToEnter;
HeaderIncludeCycleCheck &Check;
const SourceManager &SM;
std::vector<llvm::Regex> IgnoredFilesRegexes;
diff --git a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp
index 7ea9676..bb8fb240 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp
@@ -121,10 +121,11 @@ void UseDesignatedInitializersCheck::registerMatchers(MatchFinder *Finder) {
hasAnyBase(hasType(cxxRecordDecl(has(fieldDecl()))));
Finder->addMatcher(
initListExpr(
- hasType(cxxRecordDecl(
- RestrictToPODTypes ? isPOD() : isAggregate(),
- unless(anyOf(HasBaseWithFields, hasName("::std::array"))))
- .bind("type")),
+ hasType(hasUnqualifiedDesugaredType(recordType(hasDeclaration(
+ cxxRecordDecl(
+ RestrictToPODTypes ? isPOD() : isAggregate(),
+ unless(anyOf(HasBaseWithFields, hasName("::std::array"))))
+ .bind("type"))))),
IgnoreSingleElementAggregates ? hasMoreThanOneElement() : anything(),
unless(isFullyDesignated()))
.bind("init"),
@@ -155,7 +156,7 @@ void UseDesignatedInitializersCheck::check(
DiagnosticBuilder Diag =
diag(InitList->getLBraceLoc(),
"use designated initializer list to initialize %0");
- Diag << Type << InitList->getSourceRange();
+ Diag << InitList->getType() << InitList->getSourceRange();
for (const Stmt *InitExpr : *SyntacticInitList) {
const auto Designator = Designators[InitExpr->getBeginLoc()];
if (Designator && !Designator->empty())
diff --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
index 936a906..e307339 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
@@ -92,7 +92,7 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
const LangOptions &LO = getLangOpts();
// Match CXXRecordDecl only to store the range of the last non-implicit full
- // declaration, to later check whether it's within the typdef itself.
+ // declaration, to later check whether it's within the typedef itself.
const auto *MatchedTagDecl = Result.Nodes.getNodeAs<TagDecl>(TagDeclName);
if (MatchedTagDecl) {
// It is not sufficient to just track the last TagDecl that we've seen,
@@ -152,7 +152,7 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
StringRef ExtraReference = "";
if (MainTypeEndLoc.isValid() && TypeRange.fullyContains(MainTypeEndLoc)) {
// Each type introduced in a typedef can specify being a reference or
- // pointer type seperately, so we need to sigure out if the new using-decl
+ // pointer type separately, so we need to figure out if the new using-decl
// needs to be to a reference or pointer as well.
const SourceLocation Tok = utils::lexer::findPreviousAnyTokenKind(
MatchedDecl->getLocation(), SM, LO, tok::TokenKind::star,
diff --git a/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp b/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp
index 651a63b..195418d 100644
--- a/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp
+++ b/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp
@@ -41,7 +41,7 @@ public:
new ClangTidyDiagnosticConsumer(*Context, &Compiler.getDiagnostics());
auto DiagOpts = std::make_unique<DiagnosticOptions>();
auto DiagEngine = std::make_unique<DiagnosticsEngine>(
- new DiagnosticIDs, *DiagOpts, DiagConsumer);
+ DiagnosticIDs::create(), *DiagOpts, DiagConsumer);
Context->setDiagnosticsEngine(std::move(DiagOpts), DiagEngine.get());
// Create the AST consumer.
diff --git a/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
index 9c2f27f0..aaa2336 100644
--- a/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
@@ -18,10 +18,11 @@ AST_MATCHER(CXXMethodDecl, isUsed) { return Node.isUsed(); }
void TemplateVirtualMemberFunctionCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
- cxxMethodDecl(ofClass(classTemplateSpecializationDecl(
+ cxxMethodDecl(isVirtual(),
+ ofClass(classTemplateSpecializationDecl(
unless(isExplicitTemplateSpecialization()))
.bind("specialization")),
- isVirtual(), unless(isUsed()),
+ unless(isUsed()), unless(isPure()),
unless(cxxDestructorDecl(isDefaulted())))
.bind("method"),
this);
diff --git a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp
index 20c7329..5f19706 100644
--- a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp
@@ -361,14 +361,15 @@ void ImplicitBoolConversionCheck::check(
if (const auto *CastToBool =
Result.Nodes.getNodeAs<ImplicitCastExpr>("implicitCastToBool")) {
const auto *Parent = Result.Nodes.getNodeAs<Stmt>("parentStmt");
- return handleCastToBool(CastToBool, Parent, *Result.Context);
+ handleCastToBool(CastToBool, Parent, *Result.Context);
+ return;
}
if (const auto *CastFromBool =
Result.Nodes.getNodeAs<ImplicitCastExpr>("implicitCastFromBool")) {
const auto *NextImplicitCast =
Result.Nodes.getNodeAs<ImplicitCastExpr>("furtherImplicitCast");
- return handleCastFromBool(CastFromBool, NextImplicitCast, *Result.Context);
+ handleCastFromBool(CastFromBool, NextImplicitCast, *Result.Context);
}
}
diff --git a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
index 91a08b9..561f067 100644
--- a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
@@ -106,12 +106,14 @@ QualifiedAutoCheck::QualifiedAutoCheck(StringRef Name,
: ClangTidyCheck(Name, Context),
AddConstToQualified(Options.get("AddConstToQualified", true)),
AllowedTypes(
- utils::options::parseStringList(Options.get("AllowedTypes", ""))) {}
+ utils::options::parseStringList(Options.get("AllowedTypes", ""))),
+ IgnoreAliasing(Options.get("IgnoreAliasing", true)) {}
void QualifiedAutoCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "AddConstToQualified", AddConstToQualified);
Options.store(Opts, "AllowedTypes",
utils::options::serializeStringList(AllowedTypes));
+ Options.store(Opts, "IgnoreAliasing", IgnoreAliasing);
}
void QualifiedAutoCheck::registerMatchers(MatchFinder *Finder) {
@@ -134,16 +136,30 @@ void QualifiedAutoCheck::registerMatchers(MatchFinder *Finder) {
auto IsBoundToType = refersToType(equalsBoundNode("type"));
auto UnlessFunctionType = unless(hasUnqualifiedDesugaredType(functionType()));
- auto IsAutoDeducedToPointer = [](const std::vector<StringRef> &AllowedTypes,
- const auto &...InnerMatchers) {
- return autoType(hasDeducedType(
- hasUnqualifiedDesugaredType(pointerType(pointee(InnerMatchers...))),
- unless(hasUnqualifiedType(
- matchers::matchesAnyListedTypeName(AllowedTypes, false))),
- unless(pointerType(pointee(hasUnqualifiedType(
- matchers::matchesAnyListedTypeName(AllowedTypes, false)))))));
+
+ auto IsPointerType = [this](const auto &...InnerMatchers) {
+ if (this->IgnoreAliasing) {
+ return qualType(
+ hasUnqualifiedDesugaredType(pointerType(pointee(InnerMatchers...))));
+ } else {
+ return qualType(
+ anyOf(qualType(pointerType(pointee(InnerMatchers...))),
+ qualType(substTemplateTypeParmType(hasReplacementType(
+ pointerType(pointee(InnerMatchers...)))))));
+ }
};
+ auto IsAutoDeducedToPointer =
+ [IsPointerType](const std::vector<StringRef> &AllowedTypes,
+ const auto &...InnerMatchers) {
+ return autoType(hasDeducedType(
+ IsPointerType(InnerMatchers...),
+ unless(hasUnqualifiedType(
+ matchers::matchesAnyListedTypeName(AllowedTypes, false))),
+ unless(pointerType(pointee(hasUnqualifiedType(
+ matchers::matchesAnyListedTypeName(AllowedTypes, false)))))));
+ };
+
Finder->addMatcher(
ExplicitSingleVarDecl(
hasType(IsAutoDeducedToPointer(AllowedTypes, UnlessFunctionType)),
diff --git a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h
index 187a4cd..b5b713f 100644
--- a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h
@@ -32,6 +32,7 @@ public:
private:
const bool AddConstToQualified;
const std::vector<StringRef> AllowedTypes;
+ const bool IgnoreAliasing;
};
} // namespace clang::tidy::readability
diff --git a/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py b/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
index 0f8ac73..7cd21af 100755
--- a/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
+++ b/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
@@ -177,7 +177,7 @@ def main():
parser.add_argument(
"-j",
type=int,
- default=1,
+ default=0,
help="number of tidy instances to be run in parallel.",
)
parser.add_argument(
@@ -318,6 +318,7 @@ def main():
if max_task_count == 0:
max_task_count = multiprocessing.cpu_count()
max_task_count = min(len(lines_by_file), max_task_count)
+ print(f"Running clang-tidy in {max_task_count} threads...")
combine_fixes = False
export_fixes_dir = None
diff --git a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
index 8741147..a3dca6c 100755
--- a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
+++ b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
@@ -548,7 +548,7 @@ async def main() -> None:
files = {f for f in files if file_name_re.search(f)}
print(
- "Running clang-tidy for",
+ f"Running clang-tidy in {max_task} threads for",
len(files),
"files out of",
number_files_in_database,
diff --git a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
index 7f4ccca..e1c1bee 100644
--- a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
+++ b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
@@ -207,13 +207,9 @@ FormatStringConverter::FormatStringConverter(
ArgsOffset(FormatArgOffset + 1), LangOpts(LO) {
assert(ArgsOffset <= NumArgs);
FormatExpr = llvm::dyn_cast<StringLiteral>(
- Args[FormatArgOffset]->IgnoreImplicitAsWritten());
+ Args[FormatArgOffset]->IgnoreUnlessSpelledInSource());
- if (!FormatExpr || !FormatExpr->isOrdinary()) {
- // Function must have a narrow string literal as its first argument.
- conversionNotPossible("first argument is not a narrow string literal");
- return;
- }
+ assert(FormatExpr && FormatExpr->isOrdinary());
if (const std::optional<StringRef> MaybeMacroName =
formatStringContainsUnreplaceableMacro(Call, FormatExpr, SM, PP);
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index a703009..b445dcf 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -1279,11 +1279,9 @@ void ClangdLSPServer::onHover(const TextDocumentPositionParams &Params,
R.contents.kind = HoverContentFormat;
R.range = (*H)->SymRange;
switch (HoverContentFormat) {
- case MarkupKind::PlainText:
- R.contents.value = (*H)->present().asPlainText();
- return Reply(std::move(R));
case MarkupKind::Markdown:
- R.contents.value = (*H)->present().asMarkdown();
+ case MarkupKind::PlainText:
+ R.contents.value = (*H)->present(HoverContentFormat);
return Reply(std::move(R));
};
llvm_unreachable("unhandled MarkupKind");
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index 184c3c9..9c17b4c 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -193,7 +193,11 @@ MarkupContent renderDoc(const markup::Document &Doc, MarkupKind Kind) {
Result.value.append(Doc.asPlainText());
break;
case MarkupKind::Markdown:
- Result.value.append(Doc.asMarkdown());
+ if (Config::current().Documentation.CommentFormat ==
+ Config::CommentFormatPolicy::PlainText)
+ Result.value.append(Doc.asEscapedMarkdown());
+ else
+ Result.value.append(Doc.asMarkdown());
break;
}
return Result;
diff --git a/clang-tools-extra/clangd/Config.h b/clang-tools-extra/clangd/Config.h
index 83e0fce..2e3e0a4 100644
--- a/clang-tools-extra/clangd/Config.h
+++ b/clang-tools-extra/clangd/Config.h
@@ -196,6 +196,19 @@ struct Config {
/// Controls highlighting modifiers that are disabled.
std::vector<std::string> DisabledModifiers;
} SemanticTokens;
+
+ enum class CommentFormatPolicy {
+ /// Treat comments as plain text.
+ PlainText,
+ /// Treat comments as Markdown.
+ Markdown,
+ /// Treat comments as doxygen.
+ Doxygen,
+ };
+
+ struct {
+ CommentFormatPolicy CommentFormat = CommentFormatPolicy::PlainText;
+ } Documentation;
};
} // namespace clangd
diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp b/clang-tools-extra/clangd/ConfigCompile.cpp
index 35d35f7..5dda6dd 100644
--- a/clang-tools-extra/clangd/ConfigCompile.cpp
+++ b/clang-tools-extra/clangd/ConfigCompile.cpp
@@ -198,6 +198,7 @@ struct FragmentCompiler {
compile(std::move(F.InlayHints));
compile(std::move(F.SemanticTokens));
compile(std::move(F.Style));
+ compile(std::move(F.Documentation));
}
void compile(Fragment::IfBlock &&F) {
@@ -793,6 +794,21 @@ struct FragmentCompiler {
}
}
+ void compile(Fragment::DocumentationBlock &&F) {
+ if (F.CommentFormat) {
+ if (auto Val =
+ compileEnum<Config::CommentFormatPolicy>("CommentFormat",
+ *F.CommentFormat)
+ .map("Plaintext", Config::CommentFormatPolicy::PlainText)
+ .map("Markdown", Config::CommentFormatPolicy::Markdown)
+ .map("Doxygen", Config::CommentFormatPolicy::Doxygen)
+ .value())
+ Out.Apply.push_back([Val](const Params &, Config &C) {
+ C.Documentation.CommentFormat = *Val;
+ });
+ }
+ }
+
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 9e00dbc..a6a7cd5 100644
--- a/clang-tools-extra/clangd/ConfigFragment.h
+++ b/clang-tools-extra/clangd/ConfigFragment.h
@@ -393,6 +393,17 @@ struct Fragment {
std::vector<Located<std::string>> DisabledModifiers;
};
SemanticTokensBlock SemanticTokens;
+
+ /// Configures documentation style and behaviour.
+ struct DocumentationBlock {
+ /// Specifies the format of comments in the code.
+ /// Valid values are enum Config::CommentFormatPolicy values:
+ /// - Plaintext: Treat comments as plain text.
+ /// - Markdown: Treat comments as Markdown.
+ /// - Doxygen: Treat comments as doxygen.
+ std::optional<Located<std::string>> CommentFormat;
+ };
+ DocumentationBlock Documentation;
};
} // namespace config
diff --git a/clang-tools-extra/clangd/ConfigYAML.cpp b/clang-tools-extra/clangd/ConfigYAML.cpp
index 6086357..289b7e8 100644
--- a/clang-tools-extra/clangd/ConfigYAML.cpp
+++ b/clang-tools-extra/clangd/ConfigYAML.cpp
@@ -69,6 +69,7 @@ public:
Dict.handle("Hover", [&](Node &N) { parse(F.Hover, N); });
Dict.handle("InlayHints", [&](Node &N) { parse(F.InlayHints, N); });
Dict.handle("SemanticTokens", [&](Node &N) { parse(F.SemanticTokens, N); });
+ Dict.handle("Documentation", [&](Node &N) { parse(F.Documentation, N); });
Dict.parse(N);
return !(N.failed() || HadError);
}
@@ -312,6 +313,15 @@ private:
Dict.parse(N);
}
+ void parse(Fragment::DocumentationBlock &F, Node &N) {
+ DictParser Dict("Documentation", this);
+ Dict.handle("CommentFormat", [&](Node &N) {
+ if (auto Value = scalarValue(N, "CommentFormat"))
+ F.CommentFormat = *Value;
+ });
+ Dict.parse(N);
+ }
+
// Helper for parsing mapping nodes (dictionaries).
// We don't use YamlIO as we want to control over unknown keys.
class DictParser {
diff --git a/clang-tools-extra/clangd/FindSymbols.cpp b/clang-tools-extra/clangd/FindSymbols.cpp
index 84bcbc1..7655a39 100644
--- a/clang-tools-extra/clangd/FindSymbols.cpp
+++ b/clang-tools-extra/clangd/FindSymbols.cpp
@@ -14,6 +14,7 @@
#include "SourceCode.h"
#include "index/Index.h"
#include "support/Logger.h"
+#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Index/IndexSymbol.h"
#include "llvm/ADT/ArrayRef.h"
@@ -391,6 +392,17 @@ private:
D = TD;
}
+ // FriendDecls don't act as DeclContexts, but they might wrap a function
+ // definition that won't be visible through other means in the AST. Hence
+ // unwrap it here instead.
+ if (auto *Friend = llvm::dyn_cast<FriendDecl>(D)) {
+ if (auto *Func =
+ llvm::dyn_cast_or_null<FunctionDecl>(Friend->getFriendDecl())) {
+ if (Func->isThisDeclarationADefinition())
+ D = Func;
+ }
+ }
+
VisitKind Visit = shouldVisit(D);
if (Visit == VisitKind::No)
return;
diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index e39d8bf..1e0718d 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -15,6 +15,7 @@
#include "Headers.h"
#include "IncludeCleaner.h"
#include "ParsedAST.h"
+#include "Protocol.h"
#include "Selection.h"
#include "SourceCode.h"
#include "clang-include-cleaner/Analysis.h"
@@ -960,42 +961,6 @@ std::optional<HoverInfo> getHoverContents(const Attr *A, ParsedAST &AST) {
return HI;
}
-bool isParagraphBreak(llvm::StringRef Rest) {
- return Rest.ltrim(" \t").starts_with("\n");
-}
-
-bool punctuationIndicatesLineBreak(llvm::StringRef Line) {
- constexpr llvm::StringLiteral Punctuation = R"txt(.:,;!?)txt";
-
- Line = Line.rtrim();
- return !Line.empty() && Punctuation.contains(Line.back());
-}
-
-bool isHardLineBreakIndicator(llvm::StringRef Rest) {
- // '-'/'*' md list, '@'/'\' documentation command, '>' md blockquote,
- // '#' headings, '`' code blocks
- constexpr llvm::StringLiteral LinebreakIndicators = R"txt(-*@\>#`)txt";
-
- Rest = Rest.ltrim(" \t");
- if (Rest.empty())
- return false;
-
- if (LinebreakIndicators.contains(Rest.front()))
- return true;
-
- if (llvm::isDigit(Rest.front())) {
- llvm::StringRef AfterDigit = Rest.drop_while(llvm::isDigit);
- if (AfterDigit.starts_with(".") || AfterDigit.starts_with(")"))
- return true;
- }
- return false;
-}
-
-bool isHardLineBreakAfter(llvm::StringRef Line, llvm::StringRef Rest) {
- // Should we also consider whether Line is short?
- return punctuationIndicatesLineBreak(Line) || isHardLineBreakIndicator(Rest);
-}
-
void addLayoutInfo(const NamedDecl &ND, HoverInfo &HI) {
if (ND.isInvalidDecl())
return;
@@ -1570,6 +1535,26 @@ markup::Document HoverInfo::present() const {
return Output;
}
+std::string HoverInfo::present(MarkupKind Kind) const {
+ if (Kind == MarkupKind::Markdown) {
+ const Config &Cfg = Config::current();
+ if ((Cfg.Documentation.CommentFormat ==
+ Config::CommentFormatPolicy::Markdown) ||
+ (Cfg.Documentation.CommentFormat ==
+ Config::CommentFormatPolicy::Doxygen))
+ // If the user prefers Markdown, we use the present() method to generate
+ // the Markdown output.
+ return present().asMarkdown();
+ if (Cfg.Documentation.CommentFormat ==
+ Config::CommentFormatPolicy::PlainText)
+ // If the user prefers plain text, we use the present() method to generate
+ // the plain text output.
+ return present().asEscapedMarkdown();
+ }
+
+ return present().asPlainText();
+}
+
// If the backtick at `Offset` starts a probable quoted range, return the range
// (including the quotes).
std::optional<llvm::StringRef> getBacktickQuoteRange(llvm::StringRef Line,
@@ -1583,9 +1568,14 @@ std::optional<llvm::StringRef> getBacktickQuoteRange(llvm::StringRef Line,
return std::nullopt;
// The quoted string must be nonempty and usually has no leading/trailing ws.
- auto Next = Line.find('`', Offset + 1);
+ auto Next = Line.find_first_of("`\n", Offset + 1);
if (Next == llvm::StringRef::npos)
return std::nullopt;
+
+ // There should be no newline in the quoted string.
+ if (Line[Next] == '\n')
+ return std::nullopt;
+
llvm::StringRef Contents = Line.slice(Offset + 1, Next);
if (Contents.empty() || isWhitespace(Contents.front()) ||
isWhitespace(Contents.back()))
@@ -1600,51 +1590,40 @@ std::optional<llvm::StringRef> getBacktickQuoteRange(llvm::StringRef Line,
return Line.slice(Offset, Next + 1);
}
-void parseDocumentationLine(llvm::StringRef Line, markup::Paragraph &Out) {
+void parseDocumentationParagraph(llvm::StringRef Text, markup::Paragraph &Out) {
// Probably this is appendText(Line), but scan for something interesting.
- for (unsigned I = 0; I < Line.size(); ++I) {
- switch (Line[I]) {
+ for (unsigned I = 0; I < Text.size(); ++I) {
+ switch (Text[I]) {
case '`':
- if (auto Range = getBacktickQuoteRange(Line, I)) {
- Out.appendText(Line.substr(0, I));
+ if (auto Range = getBacktickQuoteRange(Text, I)) {
+ Out.appendText(Text.substr(0, I));
Out.appendCode(Range->trim("`"), /*Preserve=*/true);
- return parseDocumentationLine(Line.substr(I + Range->size()), Out);
+ return parseDocumentationParagraph(Text.substr(I + Range->size()), Out);
}
break;
}
}
- Out.appendText(Line).appendSpace();
+ Out.appendText(Text);
}
void parseDocumentation(llvm::StringRef Input, markup::Document &Output) {
- std::vector<llvm::StringRef> ParagraphLines;
- auto FlushParagraph = [&] {
- if (ParagraphLines.empty())
- return;
- auto &P = Output.addParagraph();
- for (llvm::StringRef Line : ParagraphLines)
- parseDocumentationLine(Line, P);
- ParagraphLines.clear();
- };
-
- llvm::StringRef Line, Rest;
- for (std::tie(Line, Rest) = Input.split('\n');
- !(Line.empty() && Rest.empty());
- std::tie(Line, Rest) = Rest.split('\n')) {
-
- // After a linebreak remove spaces to avoid 4 space markdown code blocks.
- // FIXME: make FlushParagraph handle this.
- Line = Line.ltrim();
- if (!Line.empty())
- ParagraphLines.push_back(Line);
-
- if (isParagraphBreak(Rest) || isHardLineBreakAfter(Line, Rest)) {
- FlushParagraph();
- }
+ // A documentation string is treated as a sequence of paragraphs,
+ // where the paragraphs are seperated by at least one empty line
+ // (meaning 2 consecutive newline characters).
+ // Possible leading empty lines (introduced by an odd number > 1 of
+ // empty lines between 2 paragraphs) will be removed later in the Markup
+ // renderer.
+ llvm::StringRef Paragraph, Rest;
+ for (std::tie(Paragraph, Rest) = Input.split("\n\n");
+ !(Paragraph.empty() && Rest.empty());
+ std::tie(Paragraph, Rest) = Rest.split("\n\n")) {
+
+ // The Paragraph will be empty if there is an even number of newline
+ // characters between two paragraphs, so we skip it.
+ if (!Paragraph.empty())
+ parseDocumentationParagraph(Paragraph, Output.addParagraph());
}
- FlushParagraph();
}
-
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
const HoverInfo::PrintedType &T) {
OS << T.Type;
diff --git a/clang-tools-extra/clangd/Hover.h b/clang-tools-extra/clangd/Hover.h
index fe689de..2f65431 100644
--- a/clang-tools-extra/clangd/Hover.h
+++ b/clang-tools-extra/clangd/Hover.h
@@ -120,6 +120,8 @@ struct HoverInfo {
/// Produce a user-readable information.
markup::Document present() const;
+
+ std::string present(MarkupKind Kind) const;
};
inline bool operator==(const HoverInfo::PrintedType &LHS,
diff --git a/clang-tools-extra/clangd/Preamble.cpp b/clang-tools-extra/clangd/Preamble.cpp
index 7b4d63f..8af9e46 100644
--- a/clang-tools-extra/clangd/Preamble.cpp
+++ b/clang-tools-extra/clangd/Preamble.cpp
@@ -659,7 +659,7 @@ buildPreamble(PathRef FileName, CompilerInvocation CI,
WallTimer PreambleTimer;
PreambleTimer.startTimer();
auto BuiltPreamble = PrecompiledPreamble::Build(
- CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine,
+ CI, ContentsBuffer.get(), Bounds, PreambleDiagsEngine,
Stats ? TimedFS : StatCacheFS, std::make_shared<PCHContainerOperations>(),
StoreInMemory, /*StoragePath=*/"", CapturedInfo);
diff --git a/clang-tools-extra/clangd/SystemIncludeExtractor.cpp b/clang-tools-extra/clangd/SystemIncludeExtractor.cpp
index 0b067e8..106de1b 100644
--- a/clang-tools-extra/clangd/SystemIncludeExtractor.cpp
+++ b/clang-tools-extra/clangd/SystemIncludeExtractor.cpp
@@ -254,7 +254,7 @@ bool isValidTarget(llvm::StringRef Triple) {
std::shared_ptr<TargetOptions> TargetOpts(new TargetOptions);
TargetOpts->Triple = Triple.str();
DiagnosticOptions DiagOpts;
- DiagnosticsEngine Diags(new DiagnosticIDs, DiagOpts,
+ DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts,
new IgnoringDiagConsumer);
llvm::IntrusiveRefCntPtr<TargetInfo> Target =
TargetInfo::CreateTargetInfo(Diags, *TargetOpts);
diff --git a/clang-tools-extra/clangd/support/Markup.cpp b/clang-tools-extra/clangd/support/Markup.cpp
index 63aff96..a130830 100644
--- a/clang-tools-extra/clangd/support/Markup.cpp
+++ b/clang-tools-extra/clangd/support/Markup.cpp
@@ -6,12 +6,12 @@
//
//===----------------------------------------------------------------------===//
#include "support/Markup.h"
+#include "clang/Basic/CharInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include <cstddef>
#include <iterator>
@@ -64,8 +64,8 @@ bool looksLikeTag(llvm::StringRef Contents) {
// It's always safe to escape punctuation, but want minimal escaping.
// The strategy is to escape the first character of anything that might start
// a markdown grammar construct.
-bool needsLeadingEscape(char C, llvm::StringRef Before, llvm::StringRef After,
- bool StartsLine) {
+bool needsLeadingEscapePlaintext(char C, llvm::StringRef Before,
+ llvm::StringRef After, bool StartsLine) {
assert(Before.take_while(llvm::isSpace).empty());
auto RulerLength = [&]() -> /*Length*/ unsigned {
if (!StartsLine || !Before.empty())
@@ -151,16 +151,94 @@ bool needsLeadingEscape(char C, llvm::StringRef Before, llvm::StringRef After,
}
}
-/// Escape a markdown text block. Ensures the punctuation will not introduce
+/// \brief Tests whether \p C should be backslash-escaped in markdown.
+///
+/// The MarkupContent LSP specification defines that `markdown` content needs to
+/// follow GFM (GitHub Flavored Markdown) rules. And we can assume that markdown
+/// is rendered on the client side. This means we do not need to escape any
+/// markdown constructs.
+/// The only exception is when the client does not support HTML rendering in
+/// markdown. In that case, we need to escape HTML tags and HTML entities.
+///
+/// **FIXME:** handle the case when the client does support HTML rendering in
+/// markdown. For this, the LSP server needs to check the
+/// [supportsHtml
+/// capability](https://github.com/microsoft/language-server-protocol/issues/1344)
+/// of the client.
+///
+/// \param C The character to check.
+/// \param After The string that follows \p C .
+/// This is used to determine if \p C is part of a tag or an entity reference.
+///
+/// \returns true if \p C should be escaped, false otherwise.
+bool needsLeadingEscapeMarkdown(char C, llvm::StringRef After) {
+ switch (C) {
+ case '<': // HTML tag (or autolink, which we choose not to escape)
+ return looksLikeTag(After);
+ case '&': { // HTML entity reference
+ auto End = After.find(';');
+ if (End == llvm::StringRef::npos)
+ return false;
+ llvm::StringRef Content = After.substr(0, End);
+ if (Content.consume_front("#")) {
+ if (Content.consume_front("x") || Content.consume_front("X"))
+ return llvm::all_of(Content, llvm::isHexDigit);
+ return llvm::all_of(Content, llvm::isDigit);
+ }
+ return llvm::all_of(Content, llvm::isAlpha);
+ }
+ default:
+ return false;
+ }
+}
+
+bool needsLeadingEscape(char C, llvm::StringRef Before, llvm::StringRef After,
+ bool StartsLine, bool EscapeMarkdown) {
+ if (EscapeMarkdown)
+ return needsLeadingEscapePlaintext(C, Before, After, StartsLine);
+ return needsLeadingEscapeMarkdown(C, After);
+}
+
+/// Escape a markdown text block.
+/// If \p EscapeMarkdown is true it ensures the punctuation will not introduce
/// any of the markdown constructs.
-std::string renderText(llvm::StringRef Input, bool StartsLine) {
+/// Else, markdown syntax is not escaped, only HTML tags and entities.
+std::string renderText(llvm::StringRef Input, bool StartsLine,
+ bool EscapeMarkdown) {
std::string R;
- for (unsigned I = 0; I < Input.size(); ++I) {
- if (needsLeadingEscape(Input[I], Input.substr(0, I), Input.substr(I + 1),
- StartsLine))
- R.push_back('\\');
- R.push_back(Input[I]);
+ R.reserve(Input.size());
+
+ // split the input into lines, and escape each line separately.
+ llvm::StringRef Line, Rest;
+
+ bool IsFirstLine = true;
+
+ for (std::tie(Line, Rest) = Input.split('\n');
+ !(Line.empty() && Rest.empty());
+ std::tie(Line, Rest) = Rest.split('\n')) {
+
+ bool StartsLineIntern = IsFirstLine ? StartsLine : true;
+
+ // Ignore leading spaces for the escape logic, but preserve them in the
+ // output.
+ StringRef LeadingSpaces = Line.take_while(llvm::isSpace);
+ if (!LeadingSpaces.empty()) {
+ R.append(LeadingSpaces);
+ }
+
+ for (unsigned I = LeadingSpaces.size(); I < Line.size(); ++I) {
+ if (needsLeadingEscape(Line[I], Line.substr(LeadingSpaces.size(), I),
+ Line.substr(I + 1), StartsLineIntern,
+ EscapeMarkdown))
+ R.push_back('\\');
+ R.push_back(Line[I]);
+ }
+
+ IsFirstLine = false;
+ if (!Rest.empty())
+ R.push_back('\n');
}
+
return R;
}
@@ -168,6 +246,7 @@ std::string renderText(llvm::StringRef Input, bool StartsLine) {
/// is surrounded by backticks and the inner contents are properly escaped.
std::string renderInlineBlock(llvm::StringRef Input) {
std::string R;
+ R.reserve(Input.size());
// Double all backticks to make sure we don't close the inline block early.
for (size_t From = 0; From < Input.size();) {
size_t Next = Input.find("`", From);
@@ -261,6 +340,9 @@ std::string renderBlocks(llvm::ArrayRef<std::unique_ptr<Block>> Children,
// https://github.com/microsoft/vscode/issues/88416 for details.
class Ruler : public Block {
public:
+ void renderEscapedMarkdown(llvm::raw_ostream &OS) const override {
+ renderMarkdown(OS);
+ }
void renderMarkdown(llvm::raw_ostream &OS) const override {
// Note that we need an extra new line before the ruler, otherwise we might
// make previous block a title instead of introducing a ruler.
@@ -275,6 +357,9 @@ public:
class CodeBlock : public Block {
public:
+ void renderEscapedMarkdown(llvm::raw_ostream &OS) const override {
+ renderMarkdown(OS);
+ }
void renderMarkdown(llvm::raw_ostream &OS) const override {
std::string Marker = getMarkerForCodeBlock(Contents);
// No need to pad from previous blocks, as they should end with a new line.
@@ -303,11 +388,13 @@ private:
std::string indentLines(llvm::StringRef Input) {
assert(!Input.ends_with("\n") && "Input should've been trimmed.");
std::string IndentedR;
- // We'll add 2 spaces after each new line.
+ // We'll add 2 spaces after each new line which is not followed by another new
+ // line.
IndentedR.reserve(Input.size() + Input.count('\n') * 2);
- for (char C : Input) {
+ for (size_t I = 0; I < Input.size(); ++I) {
+ char C = Input[I];
IndentedR += C;
- if (C == '\n')
+ if (C == '\n' && (((I + 1) < Input.size()) && (Input[I + 1] != '\n')))
IndentedR.append(" ");
}
return IndentedR;
@@ -316,17 +403,34 @@ std::string indentLines(llvm::StringRef Input) {
class Heading : public Paragraph {
public:
Heading(size_t Level) : Level(Level) {}
+
+ void renderEscapedMarkdown(llvm::raw_ostream &OS) const override {
+ insertHeadingMarkers(OS);
+ Paragraph::renderEscapedMarkdown(OS);
+ }
+
void renderMarkdown(llvm::raw_ostream &OS) const override {
- OS << std::string(Level, '#') << ' ';
+ insertHeadingMarkers(OS);
Paragraph::renderMarkdown(OS);
}
private:
size_t Level;
+
+ void insertHeadingMarkers(llvm::raw_ostream &OS) const {
+ OS << std::string(Level, '#') << ' ';
+ }
};
} // namespace
+std::string Block::asEscapedMarkdown() const {
+ std::string R;
+ llvm::raw_string_ostream OS(R);
+ renderEscapedMarkdown(OS);
+ return llvm::StringRef(OS.str()).trim().str();
+}
+
std::string Block::asMarkdown() const {
std::string R;
llvm::raw_string_ostream OS(R);
@@ -341,6 +445,35 @@ std::string Block::asPlainText() const {
return llvm::StringRef(OS.str()).trim().str();
}
+void Paragraph::renderEscapedMarkdown(llvm::raw_ostream &OS) const {
+ bool NeedsSpace = false;
+ bool HasChunks = false;
+ for (auto &C : Chunks) {
+ if (C.SpaceBefore || NeedsSpace)
+ OS << " ";
+ switch (C.Kind) {
+ case ChunkKind::PlainText:
+ OS << renderText(C.Contents, !HasChunks, /*EscapeMarkdown=*/true);
+ break;
+ case ChunkKind::InlineCode:
+ OS << renderInlineBlock(C.Contents);
+ break;
+ case ChunkKind::Bold:
+ OS << renderText("**" + C.Contents + "**", !HasChunks,
+ /*EscapeMarkdown=*/true);
+ break;
+ case ChunkKind::Emphasized:
+ OS << renderText("*" + C.Contents + "*", !HasChunks,
+ /*EscapeMarkdown=*/true);
+ break;
+ }
+ HasChunks = true;
+ NeedsSpace = C.SpaceAfter;
+ }
+ // A paragraph in markdown is separated by a blank line.
+ OS << "\n\n";
+}
+
void Paragraph::renderMarkdown(llvm::raw_ostream &OS) const {
bool NeedsSpace = false;
bool HasChunks = false;
@@ -348,20 +481,26 @@ void Paragraph::renderMarkdown(llvm::raw_ostream &OS) const {
if (C.SpaceBefore || NeedsSpace)
OS << " ";
switch (C.Kind) {
- case Chunk::PlainText:
- OS << renderText(C.Contents, !HasChunks);
+ case ChunkKind::PlainText:
+ OS << renderText(C.Contents, !HasChunks, /*EscapeMarkdown=*/false);
break;
- case Chunk::InlineCode:
+ case ChunkKind::InlineCode:
OS << renderInlineBlock(C.Contents);
break;
+ case ChunkKind::Bold:
+ OS << "**" << renderText(C.Contents, !HasChunks, /*EscapeMarkdown=*/false)
+ << "**";
+ break;
+ case ChunkKind::Emphasized:
+ OS << "*" << renderText(C.Contents, !HasChunks, /*EscapeMarkdown=*/false)
+ << "*";
+ break;
}
HasChunks = true;
NeedsSpace = C.SpaceAfter;
}
- // Paragraphs are translated into markdown lines, not markdown paragraphs.
- // Therefore it only has a single linebreak afterwards.
- // VSCode requires two spaces at the end of line to start a new one.
- OS << " \n";
+ // A paragraph in markdown is separated by a blank line.
+ OS << "\n\n";
}
std::unique_ptr<Block> Paragraph::clone() const {
@@ -370,8 +509,8 @@ std::unique_ptr<Block> Paragraph::clone() const {
/// Choose a marker to delimit `Text` from a prioritized list of options.
/// This is more readable than escaping for plain-text.
-llvm::StringRef chooseMarker(llvm::ArrayRef<llvm::StringRef> Options,
- llvm::StringRef Text) {
+llvm::StringRef Paragraph::chooseMarker(llvm::ArrayRef<llvm::StringRef> Options,
+ llvm::StringRef Text) const {
// Prefer a delimiter whose characters don't appear in the text.
for (llvm::StringRef S : Options)
if (Text.find_first_of(S) == llvm::StringRef::npos)
@@ -379,31 +518,147 @@ llvm::StringRef chooseMarker(llvm::ArrayRef<llvm::StringRef> Options,
return Options.front();
}
+bool Paragraph::punctuationIndicatesLineBreak(llvm::StringRef Line) const {
+ constexpr llvm::StringLiteral Punctuation = R"txt(.:,;!?)txt";
+
+ Line = Line.rtrim();
+ return !Line.empty() && Punctuation.contains(Line.back());
+}
+
+bool Paragraph::isHardLineBreakIndicator(llvm::StringRef Rest) const {
+ // '-'/'*' md list, '@'/'\' documentation command, '>' md blockquote,
+ // '#' headings, '`' code blocks, two spaces (markdown force newline)
+ constexpr llvm::StringLiteral LinebreakIndicators = R"txt(-*@\>#`)txt";
+
+ Rest = Rest.ltrim(" \t");
+ if (Rest.empty())
+ return false;
+
+ if (LinebreakIndicators.contains(Rest.front()))
+ return true;
+
+ if (llvm::isDigit(Rest.front())) {
+ llvm::StringRef AfterDigit = Rest.drop_while(llvm::isDigit);
+ if (AfterDigit.starts_with(".") || AfterDigit.starts_with(")"))
+ return true;
+ }
+ return false;
+}
+
+bool Paragraph::isHardLineBreakAfter(llvm::StringRef Line,
+ llvm::StringRef Rest) const {
+ // In Markdown, 2 spaces before a line break forces a line break.
+ // Add a line break for plaintext in this case too.
+ // Should we also consider whether Line is short?
+ return Line.ends_with(" ") || punctuationIndicatesLineBreak(Line) ||
+ isHardLineBreakIndicator(Rest);
+}
+
void Paragraph::renderPlainText(llvm::raw_ostream &OS) const {
bool NeedsSpace = false;
+ std::string ConcatenatedText;
+ ConcatenatedText.reserve(EstimatedStringSize);
+
+ llvm::raw_string_ostream ConcatenatedOS(ConcatenatedText);
+
for (auto &C : Chunks) {
+
+ if (C.Kind == ChunkKind::PlainText) {
+ if (C.SpaceBefore || NeedsSpace)
+ ConcatenatedOS << ' ';
+
+ ConcatenatedOS << C.Contents;
+ NeedsSpace = llvm::isSpace(C.Contents.back()) || C.SpaceAfter;
+ continue;
+ }
+
if (C.SpaceBefore || NeedsSpace)
- OS << " ";
+ ConcatenatedOS << ' ';
llvm::StringRef Marker = "";
- if (C.Preserve && C.Kind == Chunk::InlineCode)
+ if (C.Preserve && C.Kind == ChunkKind::InlineCode)
Marker = chooseMarker({"`", "'", "\""}, C.Contents);
- OS << Marker << C.Contents << Marker;
+ else if (C.Kind == ChunkKind::Bold)
+ Marker = "**";
+ else if (C.Kind == ChunkKind::Emphasized)
+ Marker = "*";
+ ConcatenatedOS << Marker << C.Contents << Marker;
NeedsSpace = C.SpaceAfter;
}
- OS << '\n';
+
+ // We go through the contents line by line to handle the newlines
+ // and required spacing correctly.
+ //
+ // Newlines are added if:
+ // - the line ends with 2 spaces and a newline follows
+ // - the line ends with punctuation that indicates a line break (.:,;!?)
+ // - the next line starts with a hard line break indicator (-@>#`, or a digit
+ // followed by '.' or ')'), ignoring leading whitespace.
+ //
+ // Otherwise, newlines in the input are replaced with a single space.
+ //
+ // Multiple spaces are collapsed into a single space.
+ //
+ // Lines containing only whitespace are ignored.
+ llvm::StringRef Line, Rest;
+
+ for (std::tie(Line, Rest) =
+ llvm::StringRef(ConcatenatedText).trim().split('\n');
+ !(Line.empty() && Rest.empty());
+ std::tie(Line, Rest) = Rest.split('\n')) {
+
+ // Remove lines which only contain whitespace.
+ //
+ // Note: this also handles the case when there are multiple newlines
+ // in a row, since all leading newlines are removed.
+ //
+ // The documentation parsing treats multiple newlines as paragraph
+ // separators, hence it will create a new Paragraph instead of adding
+ // multiple newlines to the same Paragraph.
+ // Therfore multiple newlines are never added to a paragraph
+ // except if the user explicitly adds them using
+ // e.g. appendText("user text\n\nnext text").
+ Line = Line.ltrim();
+ if (Line.empty())
+ continue;
+
+ OS << canonicalizeSpaces(Line);
+
+ if (isHardLineBreakAfter(Line, Rest))
+ OS << '\n';
+ else if (!Rest.empty())
+ // Since we removed any trailing whitespace from the input using trim(),
+ // we know that the next line contains non-whitespace characters.
+ // Therefore, we can add a space without worrying about trailing spaces.
+ OS << ' ';
+ }
+
+ // Paragraphs are separated by a blank line.
+ OS << "\n\n";
}
BulletList::BulletList() = default;
BulletList::~BulletList() = default;
+void BulletList::renderEscapedMarkdown(llvm::raw_ostream &OS) const {
+ for (auto &D : Items) {
+ std::string M = D.asEscapedMarkdown();
+ // Instead of doing this we might prefer passing Indent to children to get
+ // rid of the copies, if it turns out to be a bottleneck.
+ OS << "- " << indentLines(M) << '\n';
+ }
+ // We add 2 newlines after list to terminate it in markdown.
+ OS << "\n\n";
+}
+
void BulletList::renderMarkdown(llvm::raw_ostream &OS) const {
for (auto &D : Items) {
+ std::string M = D.asMarkdown();
// Instead of doing this we might prefer passing Indent to children to get
// rid of the copies, if it turns out to be a bottleneck.
- OS << "- " << indentLines(D.asMarkdown()) << '\n';
+ OS << "- " << indentLines(M) << '\n';
}
- // We need a new line after list to terminate it in markdown.
- OS << '\n';
+ // We add 2 newlines after list to terminate it in markdown.
+ OS << "\n\n";
}
void BulletList::renderPlainText(llvm::raw_ostream &OS) const {
@@ -412,6 +667,7 @@ void BulletList::renderPlainText(llvm::raw_ostream &OS) const {
// rid of the copies, if it turns out to be a bottleneck.
OS << "- " << indentLines(D.asPlainText()) << '\n';
}
+ OS << '\n';
}
Paragraph &Paragraph::appendSpace() {
@@ -420,32 +676,51 @@ Paragraph &Paragraph::appendSpace() {
return *this;
}
-Paragraph &Paragraph::appendText(llvm::StringRef Text) {
- std::string Norm = canonicalizeSpaces(Text);
- if (Norm.empty())
+Paragraph &Paragraph::appendChunk(llvm::StringRef Contents, ChunkKind K) {
+ if (Contents.empty())
return *this;
Chunks.emplace_back();
Chunk &C = Chunks.back();
- C.Contents = std::move(Norm);
- C.Kind = Chunk::PlainText;
- C.SpaceBefore = llvm::isSpace(Text.front());
- C.SpaceAfter = llvm::isSpace(Text.back());
+ C.Contents = Contents;
+ C.Kind = K;
+
+ EstimatedStringSize += Contents.size();
return *this;
}
+Paragraph &Paragraph::appendText(llvm::StringRef Text) {
+ if (!Chunks.empty() && Chunks.back().Kind == ChunkKind::PlainText) {
+ Chunks.back().Contents += std::move(Text);
+ return *this;
+ }
+
+ return appendChunk(std::move(Text), ChunkKind::PlainText);
+}
+
+Paragraph &Paragraph::appendEmphasizedText(llvm::StringRef Text) {
+ return appendChunk(canonicalizeSpaces(std::move(Text)),
+ ChunkKind::Emphasized);
+}
+
+Paragraph &Paragraph::appendBoldText(llvm::StringRef Text) {
+ return appendChunk(canonicalizeSpaces(std::move(Text)), ChunkKind::Bold);
+}
+
Paragraph &Paragraph::appendCode(llvm::StringRef Code, bool Preserve) {
bool AdjacentCode =
- !Chunks.empty() && Chunks.back().Kind == Chunk::InlineCode;
+ !Chunks.empty() && Chunks.back().Kind == ChunkKind::InlineCode;
std::string Norm = canonicalizeSpaces(std::move(Code));
if (Norm.empty())
return *this;
+ EstimatedStringSize += Norm.size();
Chunks.emplace_back();
Chunk &C = Chunks.back();
C.Contents = std::move(Norm);
- C.Kind = Chunk::InlineCode;
+ C.Kind = ChunkKind::InlineCode;
C.Preserve = Preserve;
// Disallow adjacent code spans without spaces, markdown can't render them.
C.SpaceBefore = AdjacentCode;
+
return *this;
}
@@ -482,6 +757,10 @@ void Document::addCodeBlock(std::string Code, std::string Language) {
std::make_unique<CodeBlock>(std::move(Code), std::move(Language)));
}
+std::string Document::asEscapedMarkdown() const {
+ return renderBlocks(Children, &Block::renderEscapedMarkdown);
+}
+
std::string Document::asMarkdown() const {
return renderBlocks(Children, &Block::renderMarkdown);
}
diff --git a/clang-tools-extra/clangd/support/Markup.h b/clang-tools-extra/clangd/support/Markup.h
index 3a869c4..eea6328 100644
--- a/clang-tools-extra/clangd/support/Markup.h
+++ b/clang-tools-extra/clangd/support/Markup.h
@@ -27,9 +27,11 @@ namespace markup {
/// should trim them if need be.
class Block {
public:
+ virtual void renderEscapedMarkdown(llvm::raw_ostream &OS) const = 0;
virtual void renderMarkdown(llvm::raw_ostream &OS) const = 0;
virtual void renderPlainText(llvm::raw_ostream &OS) const = 0;
virtual std::unique_ptr<Block> clone() const = 0;
+ std::string asEscapedMarkdown() const;
std::string asMarkdown() const;
std::string asPlainText() const;
@@ -42,6 +44,7 @@ public:
/// One must introduce different paragraphs to create separate blocks.
class Paragraph : public Block {
public:
+ void renderEscapedMarkdown(llvm::raw_ostream &OS) const override;
void renderMarkdown(llvm::raw_ostream &OS) const override;
void renderPlainText(llvm::raw_ostream &OS) const override;
std::unique_ptr<Block> clone() const override;
@@ -49,6 +52,12 @@ public:
/// Append plain text to the end of the string.
Paragraph &appendText(llvm::StringRef Text);
+ /// Append emphasized text, this translates to the * block in markdown.
+ Paragraph &appendEmphasizedText(llvm::StringRef Text);
+
+ /// Append bold text, this translates to the ** block in markdown.
+ Paragraph &appendBoldText(llvm::StringRef Text);
+
/// Append inline code, this translates to the ` block in markdown.
/// \p Preserve indicates the code span must be apparent even in plaintext.
Paragraph &appendCode(llvm::StringRef Code, bool Preserve = false);
@@ -58,11 +67,9 @@ public:
Paragraph &appendSpace();
private:
+ enum ChunkKind { PlainText, InlineCode, Bold, Emphasized };
struct Chunk {
- enum {
- PlainText,
- InlineCode,
- } Kind = PlainText;
+ ChunkKind Kind = PlainText;
// Preserve chunk markers in plaintext.
bool Preserve = false;
std::string Contents;
@@ -73,6 +80,21 @@ private:
bool SpaceAfter = false;
};
std::vector<Chunk> Chunks;
+
+ /// Estimated size of the string representation of this paragraph.
+ /// Used to reserve space in the output string.
+ /// Each time paragraph content is added, this value is updated.
+ /// This is an estimate, so it may not be accurate but can help
+ /// reducing dynamically reallocating string memory.
+ unsigned EstimatedStringSize = 0;
+
+ Paragraph &appendChunk(llvm::StringRef Contents, ChunkKind K);
+
+ llvm::StringRef chooseMarker(llvm::ArrayRef<llvm::StringRef> Options,
+ llvm::StringRef Text) const;
+ bool punctuationIndicatesLineBreak(llvm::StringRef Line) const;
+ bool isHardLineBreakIndicator(llvm::StringRef Rest) const;
+ bool isHardLineBreakAfter(llvm::StringRef Line, llvm::StringRef Rest) const;
};
/// Represents a sequence of one or more documents. Knows how to print them in a
@@ -82,6 +104,10 @@ public:
BulletList();
~BulletList();
+ // A BulletList rendered in markdown is a tight list if it is not a nested
+ // list and no item contains multiple paragraphs. Otherwise, it is a loose
+ // list.
+ void renderEscapedMarkdown(llvm::raw_ostream &OS) const override;
void renderMarkdown(llvm::raw_ostream &OS) const override;
void renderPlainText(llvm::raw_ostream &OS) const override;
std::unique_ptr<Block> clone() const override;
@@ -117,9 +143,13 @@ public:
BulletList &addBulletList();
+ /// Doesn't contain any trailing newlines and escaped markdown syntax.
+ /// It is expected that the result of this function
+ /// is rendered as markdown.
+ std::string asEscapedMarkdown() const;
/// Doesn't contain any trailing newlines.
- /// We try to make the markdown human-readable, e.g. avoid extra escaping.
- /// At least one client (coc.nvim) displays the markdown verbatim!
+ /// It is expected that the result of this function
+ /// is rendered as markdown.
std::string asMarkdown() const;
/// Doesn't contain any trailing newlines.
std::string asPlainText() const;
diff --git a/clang-tools-extra/clangd/test/signature-help-unescaped.test b/clang-tools-extra/clangd/test/signature-help-unescaped.test
new file mode 100644
index 0000000..c8a7df8
--- /dev/null
+++ b/clang-tools-extra/clangd/test/signature-help-unescaped.test
@@ -0,0 +1,40 @@
+# We specify a custom path in XDG_CONFIG_HOME, which only works on some systems.
+# UNSUPPORTED: system-windows
+# UNSUPPORTED: system-darwin
+
+# RUN: mkdir -p %t/clangd
+
+# Create a config file that configures to use CommentFormat Markdown.
+# RUN: echo 'Documentation:' > %t/clangd/config.yaml
+# RUN: echo ' CommentFormat: Markdown' >> %t/clangd/config.yaml
+# RUN: env XDG_CONFIG_HOME=%t clangd -lit-test -enable-config < %s | FileCheck -strict-whitespace %s
+# Start a session.
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"textDocument": {"signatureHelp": {"signatureInformation": {"documentationFormat": ["markdown", "plaintext"]}}}},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"// comment `markdown` _noescape_\nvoid x(int);\nint main(){\nx("}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/signatureHelp","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":3,"character":2}}}
+# CHECK: "id": 1,
+# CHECK-NEXT: "jsonrpc": "2.0",
+# CHECK-NEXT: "result": {
+# CHECK-NEXT: "activeParameter": 0,
+# CHECK-NEXT: "activeSignature": 0,
+# CHECK-NEXT: "signatures": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "documentation": {
+# CHECK-NEXT: "kind": "markdown",
+# CHECK-NEXT: "value": "comment `markdown` _noescape_"
+# CHECK-NEXT: },
+# CHECK-NEXT: "label": "x(int) -> void",
+# CHECK-NEXT: "parameters": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "label": "int"
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
+---
+{"jsonrpc":"2.0","id":100000,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index b7c64c7..61bd631 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1095,10 +1095,11 @@ TEST(CompletionTest, Documentation) {
int x = ^
)cpp");
- EXPECT_THAT(Results.Completions,
- Contains(AllOf(
- named("foo"),
- doc("Annotation: custom_annotation\nNon-doxygen comment."))));
+ EXPECT_THAT(
+ Results.Completions,
+ Contains(
+ AllOf(named("foo"),
+ doc("Annotation: custom_annotation\n\nNon-doxygen comment."))));
EXPECT_THAT(
Results.Completions,
Contains(AllOf(named("bar"), doc("Doxygen comment.\n\\param int a"))));
@@ -2297,7 +2298,7 @@ TEST(CompletionTest, Render) {
EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
EXPECT_EQ(R.filterText, "x");
EXPECT_EQ(R.detail, "int");
- EXPECT_EQ(R.documentation->value, "From \"foo.h\"\nThis is x()");
+ EXPECT_EQ(R.documentation->value, "From \"foo.h\"\n\nThis is x()");
EXPECT_THAT(R.additionalTextEdits, IsEmpty());
EXPECT_EQ(R.sortText, sortText(1.0, "x"));
EXPECT_FALSE(R.deprecated);
@@ -2332,7 +2333,7 @@ TEST(CompletionTest, Render) {
C.BundleSize = 2;
R = C.render(Opts);
EXPECT_EQ(R.detail, "[2 overloads]");
- EXPECT_EQ(R.documentation->value, "From \"foo.h\"\nThis is x()");
+ EXPECT_EQ(R.documentation->value, "From \"foo.h\"\n\nThis is x()");
C.Deprecated = true;
R = C.render(Opts);
@@ -2340,7 +2341,7 @@ TEST(CompletionTest, Render) {
Opts.DocumentationFormat = MarkupKind::Markdown;
R = C.render(Opts);
- EXPECT_EQ(R.documentation->value, "From `\"foo.h\"` \nThis is `x()`");
+ EXPECT_EQ(R.documentation->value, "From `\"foo.h\"`\n\nThis is `x()`");
}
TEST(CompletionTest, IgnoreRecoveryResults) {
@@ -3266,6 +3267,56 @@ TEST(SignatureHelpTest, VariadicType) {
}
}
+TEST(SignatureHelpTest, SkipExplicitObjectParameter) {
+ Annotations Code(R"cpp(
+ struct A {
+ void foo(this auto&& self, int arg);
+ void bar(this A self, int arg);
+ };
+ int main() {
+ A a {};
+ a.foo($c1^);
+ (&A::bar)($c2^);
+ (&A::foo)($c3^);
+ }
+ )cpp");
+
+ auto TU = TestTU::withCode(Code.code());
+ TU.ExtraArgs = {"-std=c++23"};
+
+ MockFS FS;
+ auto Inputs = TU.inputs(FS);
+
+ auto Preamble = TU.preamble();
+ ASSERT_TRUE(Preamble);
+
+ {
+ const auto Result = signatureHelp(testPath(TU.Filename), Code.point("c1"),
+ *Preamble, Inputs, MarkupKind::PlainText);
+
+ EXPECT_EQ(1U, Result.signatures.size());
+
+ EXPECT_THAT(Result.signatures[0], AllOf(sig("foo([[int arg]]) -> void")));
+ }
+ {
+ const auto Result = signatureHelp(testPath(TU.Filename), Code.point("c2"),
+ *Preamble, Inputs, MarkupKind::PlainText);
+
+ EXPECT_EQ(1U, Result.signatures.size());
+
+ EXPECT_THAT(Result.signatures[0], AllOf(sig("([[A]], [[int]]) -> void")));
+ }
+ {
+ // TODO: llvm/llvm-project/146649
+ const auto Result = signatureHelp(testPath(TU.Filename), Code.point("c3"),
+ *Preamble, Inputs, MarkupKind::PlainText);
+ // TODO: We expect 1 signature here, with this signature
+ EXPECT_EQ(0U, Result.signatures.size());
+ // EXPECT_THAT(Result.signatures[0], AllOf(sig("([[auto&&]], [[int]]) ->
+ // void")));
+ }
+}
+
TEST(CompletionTest, IncludedCompletionKinds) {
Annotations Test(R"cpp(#include "^)cpp");
auto TU = TestTU::withCode(Test.code());
@@ -4368,14 +4419,24 @@ TEST(CompletionTest, SkipExplicitObjectParameter) {
Annotations Code(R"cpp(
struct A {
void foo(this auto&& self, int arg);
+ void bar(this A self, int arg);
};
int main() {
A a {};
- a.^
+ a.$c1^;
+ (&A::fo$c2^;
+ (&A::ba$c3^;
}
)cpp");
+ // TODO: llvm/llvm-project/146649
+ // This is incorrect behavior. Correct Result should be a variant of,
+ // c2: signature = (auto&& self, int arg)
+ // snippet = (${1: auto&& self}, ${2: int arg})
+ // c3: signature = (A self, int arg)
+ // snippet = (${1: A self}, ${2: int arg})
+
auto TU = TestTU::withCode(Code.code());
TU.ExtraArgs = {"-std=c++23"};
@@ -4386,12 +4447,31 @@ TEST(CompletionTest, SkipExplicitObjectParameter) {
MockFS FS;
auto Inputs = TU.inputs(FS);
- auto Result = codeComplete(testPath(TU.Filename), Code.point(),
- Preamble.get(), Inputs, Opts);
-
- EXPECT_THAT(Result.Completions,
- ElementsAre(AllOf(named("foo"), signature("(int arg)"),
- snippetSuffix("(${1:int arg})"))));
+ {
+ auto Result = codeComplete(testPath(TU.Filename), Code.point("c1"),
+ Preamble.get(), Inputs, Opts);
+
+ EXPECT_THAT(Result.Completions,
+ UnorderedElementsAre(AllOf(named("foo"), signature("(int arg)"),
+ snippetSuffix("(${1:int arg})")),
+ AllOf(named("bar"), signature("(int arg)"),
+ snippetSuffix("(${1:int arg})"))));
+ }
+ {
+ auto Result = codeComplete(testPath(TU.Filename), Code.point("c2"),
+ Preamble.get(), Inputs, Opts);
+ EXPECT_THAT(
+ Result.Completions,
+ ElementsAre(AllOf(named("foo"), signature("<class self:auto>(int arg)"),
+ snippetSuffix("<${1:class self:auto}>"))));
+ }
+ {
+ auto Result = codeComplete(testPath(TU.Filename), Code.point("c3"),
+ Preamble.get(), Inputs, Opts);
+ EXPECT_THAT(Result.Completions,
+ ElementsAre(AllOf(named("bar"), signature("(int arg)"),
+ snippetSuffix(""))));
+ }
}
} // namespace
} // namespace clangd
diff --git a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp
index 75d0ff2..0e411b2 100644
--- a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp
@@ -299,7 +299,7 @@ TEST_F(ConfigCompileTests, DiagnosticSuppression) {
"typecheck_bool_condition",
"unexpected_friend", "warn_alloca"));
clang::DiagnosticOptions DiagOpts;
- clang::DiagnosticsEngine DiagEngine(new DiagnosticIDs, DiagOpts,
+ clang::DiagnosticsEngine DiagEngine(DiagnosticIDs::create(), DiagOpts,
new clang::IgnoringDiagConsumer);
using Diag = clang::Diagnostic;
diff --git a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
index 282859c..5b1630e 100644
--- a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
@@ -335,6 +335,7 @@ TEST(DocumentSymbols, BasicSymbols) {
Foo(int a) {}
void $decl[[f]]();
friend void f1();
+ friend void f2() {}
friend class Friend;
Foo& operator=(const Foo&);
~Foo();
@@ -346,7 +347,7 @@ TEST(DocumentSymbols, BasicSymbols) {
};
void f1();
- inline void f2() {}
+ void f2();
static const int KInt = 2;
const char* kStr = "123";
@@ -386,6 +387,8 @@ TEST(DocumentSymbols, BasicSymbols) {
withDetail("(int)"), children()),
AllOf(withName("f"), withKind(SymbolKind::Method),
withDetail("void ()"), children()),
+ AllOf(withName("f2"), withKind(SymbolKind::Function),
+ withDetail("void ()"), children()),
AllOf(withName("operator="), withKind(SymbolKind::Method),
withDetail("Foo &(const Foo &)"), children()),
AllOf(withName("~Foo"), withKind(SymbolKind::Constructor),
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 4a21daf..12d260d 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -10,6 +10,7 @@
#include "Annotations.h"
#include "Config.h"
#include "Hover.h"
+#include "Protocol.h"
#include "TestFS.h"
#include "TestIndex.h"
#include "TestTU.h"
@@ -3125,7 +3126,7 @@ TEST(Hover, All) {
Expected.SymRange = T.range();
Case.ExpectedBuilder(Expected);
- SCOPED_TRACE(H->present().asPlainText());
+ SCOPED_TRACE(H->present(MarkupKind::PlainText));
EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);
EXPECT_EQ(H->LocalScope, Expected.LocalScope);
EXPECT_EQ(H->Name, Expected.Name);
@@ -3217,7 +3218,7 @@ TEST(Hover, Providers) {
ASSERT_TRUE(H);
HoverInfo Expected;
Case.ExpectedBuilder(Expected);
- SCOPED_TRACE(H->present().asMarkdown());
+ SCOPED_TRACE(H->present(MarkupKind::Markdown));
EXPECT_EQ(H->Provider, Expected.Provider);
}
}
@@ -3233,11 +3234,11 @@ TEST(Hover, ParseProviderInfo) {
struct Case {
HoverInfo HI;
llvm::StringRef ExpectedMarkdown;
- } Cases[] = {{HIFoo, "### `foo` \nprovided by `\"foo.h\"`"},
- {HIFooBar, "### `foo` \nprovided by `<bar.h>`"}};
+ } Cases[] = {{HIFoo, "### `foo`\n\nprovided by `\"foo.h\"`"},
+ {HIFooBar, "### `foo`\n\nprovided by `<bar.h>`"}};
for (const auto &Case : Cases)
- EXPECT_EQ(Case.HI.present().asMarkdown(), Case.ExpectedMarkdown);
+ EXPECT_EQ(Case.HI.present(MarkupKind::Markdown), Case.ExpectedMarkdown);
}
TEST(Hover, UsedSymbols) {
@@ -3287,7 +3288,7 @@ TEST(Hover, UsedSymbols) {
ASSERT_TRUE(H);
HoverInfo Expected;
Case.ExpectedBuilder(Expected);
- SCOPED_TRACE(H->present().asMarkdown());
+ SCOPED_TRACE(H->present(MarkupKind::Markdown));
EXPECT_EQ(H->UsedSymbolNames, Expected.UsedSymbolNames);
}
}
@@ -3441,6 +3442,7 @@ TEST(Hover, Present) {
R"(class foo
Size: 10 bytes
+
documentation
template <typename T, typename C = bool> class Foo {})",
@@ -3465,8 +3467,8 @@ template <typename T, typename C = bool> class Foo {})",
},
"function foo\n"
"\n"
- "→ ret_type (aka can_ret_type)\n"
- "Parameters:\n"
+ "→ ret_type (aka can_ret_type)\n\n"
+ "Parameters:\n\n"
"- \n"
"- type (aka can_type)\n"
"- type foo (aka can_type)\n"
@@ -3491,8 +3493,11 @@ template <typename T, typename C = bool> class Foo {})",
R"(field foo
Type: type (aka can_type)
+
Value = value
+
Offset: 12 bytes
+
Size: 4 bytes (+4 bytes padding), alignment 4 bytes
// In test::Bar
@@ -3514,8 +3519,11 @@ def)",
R"(field foo
Type: type (aka can_type)
+
Value = value
+
Offset: 4 bytes and 3 bits
+
Size: 25 bits (+4 bits padding), alignment 8 bytes
// In test::Bar
@@ -3573,6 +3581,7 @@ protected: size_t method())",
R"(constructor cls
Parameters:
+
- int a
- int b = 5
@@ -3609,7 +3618,9 @@ private: union foo {})",
R"(variable foo
Type: int
+
Value = 3
+
Passed as arg_a
// In test::Bar
@@ -3644,7 +3655,9 @@ Passed by value)",
R"(variable foo
Type: int
+
Value = 3
+
Passed by reference as arg_a
// In test::Bar
@@ -3667,7 +3680,9 @@ int foo = 3)",
R"(variable foo
Type: int
+
Value = 3
+
Passed as arg_a (converted to alias_int)
// In test::Bar
@@ -3705,7 +3720,9 @@ int foo = 3)",
R"(variable foo
Type: int
+
Value = 3
+
Passed by const reference as arg_a (converted to int)
// In test::Bar
@@ -3741,83 +3758,140 @@ provides Foo, Bar, Baz, Foobar, Qux and 1 more)"}};
Config Cfg;
Cfg.Hover.ShowAKA = true;
WithContextValue WithCfg(Config::Key, std::move(Cfg));
- EXPECT_EQ(HI.present().asPlainText(), C.ExpectedRender);
+ EXPECT_EQ(HI.present(MarkupKind::PlainText), C.ExpectedRender);
}
}
TEST(Hover, ParseDocumentation) {
struct Case {
llvm::StringRef Documentation;
+ llvm::StringRef ExpectedRenderEscapedMarkdown;
llvm::StringRef ExpectedRenderMarkdown;
llvm::StringRef ExpectedRenderPlainText;
} Cases[] = {{
" \n foo\nbar",
- "foo bar",
+ "foo\nbar",
+ "foo\nbar",
"foo bar",
},
{
"foo\nbar \n ",
- "foo bar",
+ "foo\nbar",
+ "foo\nbar",
"foo bar",
},
{
"foo \nbar",
- "foo bar",
- "foo bar",
+ "foo \nbar",
+ "foo \nbar",
+ "foo\nbar",
},
{
"foo \nbar",
- "foo bar",
- "foo bar",
+ "foo \nbar",
+ "foo \nbar",
+ "foo\nbar",
},
{
"foo\n\n\nbar",
- "foo \nbar",
- "foo\nbar",
+ "foo\n\nbar",
+ "foo\n\nbar",
+ "foo\n\nbar",
},
{
"foo\n\n\n\tbar",
- "foo \nbar",
- "foo\nbar",
+ "foo\n\n\tbar",
+ "foo\n\n\tbar",
+ "foo\n\nbar",
+ },
+ {
+ "foo\n\n\n bar",
+ "foo\n\n bar",
+ "foo\n\n bar",
+ "foo\n\nbar",
+ },
+ {
+ "foo\n\n\n bar",
+ "foo\n\n bar",
+ "foo\n\n bar",
+ "foo\n\nbar",
},
{
"foo\n\n\n bar",
- "foo \nbar",
- "foo\nbar",
+ "foo\n\n bar",
+ "foo\n\n bar",
+ "foo\n\nbar",
+ },
+ {
+ "foo\n\n\n\nbar",
+ "foo\n\nbar",
+ "foo\n\nbar",
+ "foo\n\nbar",
+ },
+ {
+ "foo\n\n\n\n\tbar",
+ "foo\n\n\tbar",
+ "foo\n\n\tbar",
+ "foo\n\nbar",
+ },
+ {
+ "foo\n\n\n\n bar",
+ "foo\n\n bar",
+ "foo\n\n bar",
+ "foo\n\nbar",
+ },
+ {
+ "foo\n\n\n\n bar",
+ "foo\n\n bar",
+ "foo\n\n bar",
+ "foo\n\nbar",
+ },
+ {
+ "foo\n\n\n\n bar",
+ "foo\n\n bar",
+ "foo\n\n bar",
+ "foo\n\nbar",
},
{
"foo.\nbar",
- "foo. \nbar",
+ "foo.\nbar",
+ "foo.\nbar",
"foo.\nbar",
},
{
"foo. \nbar",
- "foo. \nbar",
+ "foo. \nbar",
+ "foo. \nbar",
"foo.\nbar",
},
{
"foo\n*bar",
- "foo \n\\*bar",
+ "foo\n\\*bar",
+ "foo\n*bar",
"foo\n*bar",
},
{
"foo\nbar",
- "foo bar",
+ "foo\nbar",
+ "foo\nbar",
"foo bar",
},
{
"Tests primality of `p`.",
"Tests primality of `p`.",
"Tests primality of `p`.",
+ "Tests primality of `p`.",
},
{
"'`' should not occur in `Code`",
"'\\`' should not occur in `Code`",
"'`' should not occur in `Code`",
+ "'`' should not occur in `Code`",
},
{
"`not\nparsed`",
- "\\`not parsed\\`",
+ "\\`not\nparsed\\`",
+ "`not\nparsed`",
"`not parsed`",
}};
@@ -3825,6 +3899,7 @@ TEST(Hover, ParseDocumentation) {
markup::Document Output;
parseDocumentation(C.Documentation, Output);
+ EXPECT_EQ(Output.asEscapedMarkdown(), C.ExpectedRenderEscapedMarkdown);
EXPECT_EQ(Output.asMarkdown(), C.ExpectedRenderMarkdown);
EXPECT_EQ(Output.asPlainText(), C.ExpectedRenderPlainText);
}
@@ -3837,7 +3912,7 @@ TEST(Hover, PresentHeadings) {
HI.Kind = index::SymbolKind::Variable;
HI.Name = "foo";
- EXPECT_EQ(HI.present().asMarkdown(), "### variable `foo`");
+ EXPECT_EQ(HI.present(MarkupKind::Markdown), "### variable `foo`");
}
// This is a separate test as rulers behave differently in markdown vs
@@ -3850,23 +3925,23 @@ TEST(Hover, PresentRulers) {
HI.Definition = "def";
llvm::StringRef ExpectedMarkdown = //
- "### variable `foo` \n"
+ "### variable `foo`\n"
"\n"
"---\n"
- "Value = `val` \n"
+ "Value = `val`\n"
"\n"
"---\n"
"```cpp\n"
"def\n"
"```";
- EXPECT_EQ(HI.present().asMarkdown(), ExpectedMarkdown);
+ EXPECT_EQ(HI.present(MarkupKind::Markdown), ExpectedMarkdown);
llvm::StringRef ExpectedPlaintext = R"pt(variable foo
Value = val
def)pt";
- EXPECT_EQ(HI.present().asPlainText(), ExpectedPlaintext);
+ EXPECT_EQ(HI.present(MarkupKind::PlainText), ExpectedPlaintext);
}
TEST(Hover, SpaceshipTemplateNoCrash) {
diff --git a/clang-tools-extra/clangd/unittests/support/MarkupTests.cpp b/clang-tools-extra/clangd/unittests/support/MarkupTests.cpp
index 2d86c91..482f230 100644
--- a/clang-tools-extra/clangd/unittests/support/MarkupTests.cpp
+++ b/clang-tools-extra/clangd/unittests/support/MarkupTests.cpp
@@ -17,6 +17,10 @@ namespace markup {
namespace {
std::string escape(llvm::StringRef Text) {
+ return Paragraph().appendText(Text.str()).asEscapedMarkdown();
+}
+
+std::string dontEscape(llvm::StringRef Text) {
return Paragraph().appendText(Text.str()).asMarkdown();
}
@@ -107,18 +111,135 @@ TEST(Render, Escaping) {
// In code blocks we don't need to escape ASCII punctuation.
Paragraph P = Paragraph();
P.appendCode("* foo !+ bar * baz");
- EXPECT_EQ(P.asMarkdown(), "`* foo !+ bar * baz`");
+ EXPECT_EQ(P.asEscapedMarkdown(), "`* foo !+ bar * baz`");
// But we have to escape the backticks.
P = Paragraph();
P.appendCode("foo`bar`baz", /*Preserve=*/true);
- EXPECT_EQ(P.asMarkdown(), "`foo``bar``baz`");
+ EXPECT_EQ(P.asEscapedMarkdown(), "`foo``bar``baz`");
// In plain-text, we fall back to different quotes.
EXPECT_EQ(P.asPlainText(), "'foo`bar`baz'");
// Inline code blocks starting or ending with backticks should add spaces.
P = Paragraph();
P.appendCode("`foo");
+ EXPECT_EQ(P.asEscapedMarkdown(), "` ``foo `");
+ P = Paragraph();
+ P.appendCode("foo`");
+ EXPECT_EQ(P.asEscapedMarkdown(), "` foo`` `");
+ P = Paragraph();
+ P.appendCode("`foo`");
+ EXPECT_EQ(P.asEscapedMarkdown(), "` ``foo`` `");
+
+ // Code blocks might need more than 3 backticks.
+ Document D;
+ D.addCodeBlock("foobarbaz `\nqux");
+ EXPECT_EQ(D.asEscapedMarkdown(), "```cpp\n"
+ "foobarbaz `\nqux\n"
+ "```");
+ D = Document();
+ D.addCodeBlock("foobarbaz ``\nqux");
+ EXPECT_THAT(D.asEscapedMarkdown(), "```cpp\n"
+ "foobarbaz ``\nqux\n"
+ "```");
+ D = Document();
+ D.addCodeBlock("foobarbaz ```\nqux");
+ EXPECT_EQ(D.asEscapedMarkdown(), "````cpp\n"
+ "foobarbaz ```\nqux\n"
+ "````");
+ D = Document();
+ D.addCodeBlock("foobarbaz ` `` ``` ```` `\nqux");
+ EXPECT_EQ(D.asEscapedMarkdown(), "`````cpp\n"
+ "foobarbaz ` `` ``` ```` `\nqux\n"
+ "`````");
+}
+
+TEST(Render, NoEscaping) {
+ // Check all ASCII punctuation.
+ std::string Punctuation = R"txt(!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~)txt";
+ EXPECT_EQ(dontEscape(Punctuation), Punctuation);
+
+ // Inline code
+ EXPECT_THAT(dontEscape("`foo`"), escapedNone());
+ EXPECT_THAT(dontEscape("`foo"), escapedNone());
+ EXPECT_THAT(dontEscape("foo`"), escapedNone());
+ EXPECT_THAT(dontEscape("``foo``"), escapedNone());
+ // Code blocks
+ EXPECT_THAT(dontEscape("```"), escapedNone());
+ EXPECT_THAT(dontEscape("~~~"), escapedNone());
+
+ // Rulers and headings
+ EXPECT_THAT(dontEscape("## Heading"), escapedNone());
+ EXPECT_THAT(dontEscape("Foo # bar"), escapedNone());
+ EXPECT_THAT(dontEscape("---"), escapedNone());
+ EXPECT_THAT(dontEscape("-"), escapedNone());
+ EXPECT_THAT(dontEscape("==="), escapedNone());
+ EXPECT_THAT(dontEscape("="), escapedNone());
+ EXPECT_THAT(dontEscape("***"), escapedNone()); // \** could start emphasis!
+
+ // HTML tags.
+ EXPECT_THAT(dontEscape("<pre"), escaped('<'));
+ EXPECT_THAT(dontEscape("< pre"), escapedNone());
+ EXPECT_THAT(dontEscape("if a<b then"), escaped('<'));
+ EXPECT_THAT(dontEscape("if a<b then c."), escapedNone());
+ EXPECT_THAT(dontEscape("if a<b then c='foo'."), escaped('<'));
+ EXPECT_THAT(dontEscape("std::vector<T>"), escaped('<'));
+ EXPECT_THAT(dontEscape("std::vector<std::string>"), escaped('<'));
+ EXPECT_THAT(dontEscape("std::map<int, int>"), escapedNone());
+ // Autolinks
+ EXPECT_THAT(dontEscape("Email <foo@bar.com>"), escapedNone());
+ EXPECT_THAT(dontEscape("Website <http://foo.bar>"), escapedNone());
+
+ // Bullet lists.
+ EXPECT_THAT(dontEscape("- foo"), escapedNone());
+ EXPECT_THAT(dontEscape("* foo"), escapedNone());
+ EXPECT_THAT(dontEscape("+ foo"), escapedNone());
+ EXPECT_THAT(dontEscape("+"), escapedNone());
+ EXPECT_THAT(dontEscape("a + foo"), escapedNone());
+ EXPECT_THAT(dontEscape("a+ foo"), escapedNone());
+ EXPECT_THAT(dontEscape("1. foo"), escapedNone());
+ EXPECT_THAT(dontEscape("a. foo"), escapedNone());
+
+ // Emphasis.
+ EXPECT_THAT(dontEscape("*foo*"), escapedNone());
+ EXPECT_THAT(dontEscape("**foo**"), escapedNone());
+ EXPECT_THAT(dontEscape("*foo"), escapedNone());
+ EXPECT_THAT(dontEscape("foo *"), escapedNone());
+ EXPECT_THAT(dontEscape("foo * bar"), escapedNone());
+ EXPECT_THAT(dontEscape("foo_bar"), escapedNone());
+ EXPECT_THAT(dontEscape("foo _bar"), escapedNone());
+ EXPECT_THAT(dontEscape("foo_ bar"), escapedNone());
+ EXPECT_THAT(dontEscape("foo _ bar"), escapedNone());
+
+ // HTML entities.
+ EXPECT_THAT(dontEscape("fish &chips;"), escaped('&'));
+ EXPECT_THAT(dontEscape("fish & chips;"), escapedNone());
+ EXPECT_THAT(dontEscape("fish &chips"), escapedNone());
+ EXPECT_THAT(dontEscape("foo &#42; bar"), escaped('&'));
+ EXPECT_THAT(dontEscape("foo &#xaf; bar"), escaped('&'));
+ EXPECT_THAT(dontEscape("foo &?; bar"), escapedNone());
+
+ // Links.
+ EXPECT_THAT(dontEscape("[foo](bar)"), escapedNone());
+ EXPECT_THAT(dontEscape("[foo]: bar"), escapedNone());
+ // No need to escape these, as the target never exists.
+ EXPECT_THAT(dontEscape("[foo][]"), escapedNone());
+ EXPECT_THAT(dontEscape("[foo][bar]"), escapedNone());
+ EXPECT_THAT(dontEscape("[foo]"), escapedNone());
+
+ // In code blocks we don't need to escape ASCII punctuation.
+ Paragraph P = Paragraph();
+ P.appendCode("* foo !+ bar * baz");
+ EXPECT_EQ(P.asMarkdown(), "`* foo !+ bar * baz`");
+
+ // But we have to escape the backticks.
+ P = Paragraph();
+ P.appendCode("foo`bar`baz", /*Preserve=*/true);
+ EXPECT_EQ(P.asMarkdown(), "`foo``bar``baz`");
+
+ // Inline code blocks starting or ending with backticks should add spaces.
+ P = Paragraph();
+ P.appendCode("`foo");
EXPECT_EQ(P.asMarkdown(), "` ``foo `");
P = Paragraph();
P.appendCode("foo`");
@@ -150,17 +271,6 @@ TEST(Render, Escaping) {
"`````");
}
-TEST(Paragraph, Chunks) {
- Paragraph P = Paragraph();
- P.appendText("One ");
- P.appendCode("fish");
- P.appendText(", two ");
- P.appendCode("fish", /*Preserve=*/true);
-
- EXPECT_EQ(P.asMarkdown(), "One `fish`, two `fish`");
- EXPECT_EQ(P.asPlainText(), "One fish, two `fish`");
-}
-
TEST(Paragraph, SeparationOfChunks) {
// This test keeps appending contents to a single Paragraph and checks
// expected accumulated contents after each one.
@@ -168,28 +278,122 @@ TEST(Paragraph, SeparationOfChunks) {
Paragraph P;
P.appendText("after ");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after");
EXPECT_EQ(P.asMarkdown(), "after");
EXPECT_EQ(P.asPlainText(), "after");
P.appendCode("foobar").appendSpace();
+ EXPECT_EQ(P.asEscapedMarkdown(), "after `foobar`");
EXPECT_EQ(P.asMarkdown(), "after `foobar`");
EXPECT_EQ(P.asPlainText(), "after foobar");
P.appendText("bat");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after `foobar` bat");
EXPECT_EQ(P.asMarkdown(), "after `foobar` bat");
EXPECT_EQ(P.asPlainText(), "after foobar bat");
P.appendCode("no").appendCode("space");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after `foobar` bat`no` `space`");
EXPECT_EQ(P.asMarkdown(), "after `foobar` bat`no` `space`");
EXPECT_EQ(P.asPlainText(), "after foobar batno space");
+
+ P.appendText(" text");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after `foobar` bat`no` `space` text");
+ EXPECT_EQ(P.asMarkdown(), "after `foobar` bat`no` `space` text");
+ EXPECT_EQ(P.asPlainText(), "after foobar batno space text");
+
+ P.appendSpace().appendCode("code").appendText(".\n newline");
+ EXPECT_EQ(P.asEscapedMarkdown(),
+ "after `foobar` bat`no` `space` text `code`.\n newline");
+ EXPECT_EQ(P.asMarkdown(),
+ "after `foobar` bat`no` `space` text `code`.\n newline");
+ EXPECT_EQ(P.asPlainText(), "after foobar batno space text code.\nnewline");
+}
+
+TEST(Paragraph, SeparationOfChunks2) {
+ // This test keeps appending contents to a single Paragraph and checks
+ // expected accumulated contents after each one.
+ // Purpose is to check for separation between different chunks
+ // where the spacing is in the appended string rather set by appendSpace.
+ Paragraph P;
+
+ P.appendText("after ");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after");
+ EXPECT_EQ(P.asMarkdown(), "after");
+ EXPECT_EQ(P.asPlainText(), "after");
+
+ P.appendText("foobar");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after foobar");
+ EXPECT_EQ(P.asMarkdown(), "after foobar");
+ EXPECT_EQ(P.asPlainText(), "after foobar");
+
+ P.appendText(" bat");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after foobar bat");
+ EXPECT_EQ(P.asMarkdown(), "after foobar bat");
+ EXPECT_EQ(P.asPlainText(), "after foobar bat");
+
+ P.appendText("baz");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after foobar batbaz");
+ EXPECT_EQ(P.asMarkdown(), "after foobar batbaz");
+ EXPECT_EQ(P.asPlainText(), "after foobar batbaz");
+
+ P.appendText(" faz ");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after foobar batbaz faz");
+ EXPECT_EQ(P.asMarkdown(), "after foobar batbaz faz");
+ EXPECT_EQ(P.asPlainText(), "after foobar batbaz faz");
+
+ P.appendText(" bar ");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after foobar batbaz faz bar");
+ EXPECT_EQ(P.asMarkdown(), "after foobar batbaz faz bar");
+ EXPECT_EQ(P.asPlainText(), "after foobar batbaz faz bar");
+
+ P.appendText("qux");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after foobar batbaz faz bar qux");
+ EXPECT_EQ(P.asMarkdown(), "after foobar batbaz faz bar qux");
+ EXPECT_EQ(P.asPlainText(), "after foobar batbaz faz bar qux");
+}
+
+TEST(Paragraph, SeparationOfChunks3) {
+ // This test keeps appending contents to a single Paragraph and checks
+ // expected accumulated contents after each one.
+ // Purpose is to check for separation between different chunks
+ // where the spacing is in the appended string rather set by appendSpace.
+ Paragraph P;
+
+ P.appendText("after \n");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after");
+ EXPECT_EQ(P.asMarkdown(), "after");
+ EXPECT_EQ(P.asPlainText(), "after");
+
+ P.appendText(" foobar\n");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after \n foobar");
+ EXPECT_EQ(P.asMarkdown(), "after \n foobar");
+ EXPECT_EQ(P.asPlainText(), "after\nfoobar");
+
+ P.appendText("- bat\n");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after \n foobar\n\\- bat");
+ EXPECT_EQ(P.asMarkdown(), "after \n foobar\n- bat");
+ EXPECT_EQ(P.asPlainText(), "after\nfoobar\n- bat");
+
+ P.appendText("- baz");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after \n foobar\n\\- bat\n\\- baz");
+ EXPECT_EQ(P.asMarkdown(), "after \n foobar\n- bat\n- baz");
+ EXPECT_EQ(P.asPlainText(), "after\nfoobar\n- bat\n- baz");
+
+ P.appendText(" faz ");
+ EXPECT_EQ(P.asEscapedMarkdown(), "after \n foobar\n\\- bat\n\\- baz faz");
+ EXPECT_EQ(P.asMarkdown(), "after \n foobar\n- bat\n- baz faz");
+ EXPECT_EQ(P.asPlainText(), "after\nfoobar\n- bat\n- baz faz");
}
TEST(Paragraph, ExtraSpaces) {
- // Make sure spaces inside chunks are dropped.
+ // Make sure spaces inside chunks are preserved for markdown
+ // and dropped for plain text.
Paragraph P;
P.appendText("foo\n \t baz");
P.appendCode(" bar\n");
- EXPECT_EQ(P.asMarkdown(), "foo baz`bar`");
+ EXPECT_EQ(P.asEscapedMarkdown(), "foo\n \t baz`bar`");
+ EXPECT_EQ(P.asMarkdown(), "foo\n \t baz`bar`");
EXPECT_EQ(P.asPlainText(), "foo bazbar");
}
@@ -197,7 +401,8 @@ TEST(Paragraph, SpacesCollapsed) {
Paragraph P;
P.appendText(" foo bar ");
P.appendText(" baz ");
- EXPECT_EQ(P.asMarkdown(), "foo bar baz");
+ EXPECT_EQ(P.asEscapedMarkdown(), "foo bar baz");
+ EXPECT_EQ(P.asMarkdown(), "foo bar baz");
EXPECT_EQ(P.asPlainText(), "foo bar baz");
}
@@ -206,21 +411,60 @@ TEST(Paragraph, NewLines) {
Paragraph P;
P.appendText(" \n foo\nbar\n ");
P.appendCode(" \n foo\nbar \n ");
- EXPECT_EQ(P.asMarkdown(), "foo bar `foo bar`");
+ EXPECT_EQ(P.asEscapedMarkdown(), "foo\nbar\n `foo bar`");
+ EXPECT_EQ(P.asMarkdown(), "foo\nbar\n `foo bar`");
EXPECT_EQ(P.asPlainText(), "foo bar foo bar");
}
+TEST(Paragraph, BoldText) {
+ Paragraph P;
+ P.appendBoldText("");
+ EXPECT_EQ(P.asEscapedMarkdown(), "");
+ EXPECT_EQ(P.asMarkdown(), "");
+ EXPECT_EQ(P.asPlainText(), "");
+
+ P.appendBoldText(" \n foo\nbar\n ");
+ EXPECT_EQ(P.asEscapedMarkdown(), "\\*\\*foo bar\\*\\*");
+ EXPECT_EQ(P.asMarkdown(), "**foo bar**");
+ EXPECT_EQ(P.asPlainText(), "**foo bar**");
+
+ P.appendSpace().appendBoldText("foobar");
+ EXPECT_EQ(P.asEscapedMarkdown(), "\\*\\*foo bar\\*\\* \\*\\*foobar\\*\\*");
+ EXPECT_EQ(P.asMarkdown(), "**foo bar** **foobar**");
+ EXPECT_EQ(P.asPlainText(), "**foo bar** **foobar**");
+}
+
+TEST(Paragraph, EmphasizedText) {
+ Paragraph P;
+ P.appendEmphasizedText("");
+ EXPECT_EQ(P.asEscapedMarkdown(), "");
+ EXPECT_EQ(P.asMarkdown(), "");
+ EXPECT_EQ(P.asPlainText(), "");
+
+ P.appendEmphasizedText(" \n foo\nbar\n ");
+ EXPECT_EQ(P.asEscapedMarkdown(), "\\*foo bar\\*");
+ EXPECT_EQ(P.asMarkdown(), "*foo bar*");
+ EXPECT_EQ(P.asPlainText(), "*foo bar*");
+
+ P.appendSpace().appendEmphasizedText("foobar");
+ EXPECT_EQ(P.asEscapedMarkdown(), "\\*foo bar\\* \\*foobar\\*");
+ EXPECT_EQ(P.asMarkdown(), "*foo bar* *foobar*");
+ EXPECT_EQ(P.asPlainText(), "*foo bar* *foobar*");
+}
+
TEST(Document, Separators) {
Document D;
D.addParagraph().appendText("foo");
D.addCodeBlock("test");
D.addParagraph().appendText("bar");
- const char ExpectedMarkdown[] = R"md(foo
+ const char ExpectedMarkdown[] = R"md(foo
+
```cpp
test
```
bar)md";
+ EXPECT_EQ(D.asEscapedMarkdown(), ExpectedMarkdown);
EXPECT_EQ(D.asMarkdown(), ExpectedMarkdown);
const char ExpectedText[] = R"pt(foo
@@ -238,7 +482,8 @@ TEST(Document, Ruler) {
// Ruler followed by paragraph.
D.addParagraph().appendText("bar");
- EXPECT_EQ(D.asMarkdown(), "foo \n\n---\nbar");
+ EXPECT_EQ(D.asEscapedMarkdown(), "foo\n\n---\nbar");
+ EXPECT_EQ(D.asMarkdown(), "foo\n\n---\nbar");
EXPECT_EQ(D.asPlainText(), "foo\n\nbar");
D = Document();
@@ -246,7 +491,8 @@ TEST(Document, Ruler) {
D.addRuler();
D.addCodeBlock("bar");
// Ruler followed by a codeblock.
- EXPECT_EQ(D.asMarkdown(), "foo \n\n---\n```cpp\nbar\n```");
+ EXPECT_EQ(D.asEscapedMarkdown(), "foo\n\n---\n```cpp\nbar\n```");
+ EXPECT_EQ(D.asMarkdown(), "foo\n\n---\n```cpp\nbar\n```");
EXPECT_EQ(D.asPlainText(), "foo\n\nbar");
// Ruler followed by another ruler
@@ -254,13 +500,15 @@ TEST(Document, Ruler) {
D.addParagraph().appendText("foo");
D.addRuler();
D.addRuler();
+ EXPECT_EQ(D.asEscapedMarkdown(), "foo");
EXPECT_EQ(D.asMarkdown(), "foo");
EXPECT_EQ(D.asPlainText(), "foo");
// Multiple rulers between blocks
D.addRuler();
D.addParagraph().appendText("foo");
- EXPECT_EQ(D.asMarkdown(), "foo \n\n---\nfoo");
+ EXPECT_EQ(D.asEscapedMarkdown(), "foo\n\n---\nfoo");
+ EXPECT_EQ(D.asMarkdown(), "foo\n\n---\nfoo");
EXPECT_EQ(D.asPlainText(), "foo\n\nfoo");
}
@@ -272,7 +520,8 @@ TEST(Document, Append) {
E.addRuler();
E.addParagraph().appendText("bar");
D.append(std::move(E));
- EXPECT_EQ(D.asMarkdown(), "foo \n\n---\nbar");
+ EXPECT_EQ(D.asEscapedMarkdown(), "foo\n\n---\nbar");
+ EXPECT_EQ(D.asMarkdown(), "foo\n\n---\nbar");
}
TEST(Document, Heading) {
@@ -280,8 +529,9 @@ TEST(Document, Heading) {
D.addHeading(1).appendText("foo");
D.addHeading(2).appendText("bar");
D.addParagraph().appendText("baz");
- EXPECT_EQ(D.asMarkdown(), "# foo \n## bar \nbaz");
- EXPECT_EQ(D.asPlainText(), "foo\nbar\nbaz");
+ EXPECT_EQ(D.asEscapedMarkdown(), "# foo\n\n## bar\n\nbaz");
+ EXPECT_EQ(D.asMarkdown(), "# foo\n\n## bar\n\nbaz");
+ EXPECT_EQ(D.asPlainText(), "foo\n\nbar\n\nbaz");
}
TEST(CodeBlock, Render) {
@@ -299,6 +549,7 @@ foo
R"pt(foo
bar
baz)pt";
+ EXPECT_EQ(D.asEscapedMarkdown(), ExpectedMarkdown);
EXPECT_EQ(D.asMarkdown(), ExpectedMarkdown);
EXPECT_EQ(D.asPlainText(), ExpectedPlainText);
D.addCodeBlock("foo");
@@ -311,6 +562,7 @@ foo
```cpp
foo
```)md";
+ EXPECT_EQ(D.asEscapedMarkdown(), ExpectedMarkdown);
EXPECT_EQ(D.asMarkdown(), ExpectedMarkdown);
ExpectedPlainText =
R"pt(foo
@@ -325,18 +577,20 @@ TEST(BulletList, Render) {
BulletList L;
// Flat list
L.addItem().addParagraph().appendText("foo");
+ EXPECT_EQ(L.asEscapedMarkdown(), "- foo");
EXPECT_EQ(L.asMarkdown(), "- foo");
EXPECT_EQ(L.asPlainText(), "- foo");
L.addItem().addParagraph().appendText("bar");
llvm::StringRef Expected = R"md(- foo
- bar)md";
+ EXPECT_EQ(L.asEscapedMarkdown(), Expected);
EXPECT_EQ(L.asMarkdown(), Expected);
EXPECT_EQ(L.asPlainText(), Expected);
// Nested list, with a single item.
Document &D = L.addItem();
- // First item with foo\nbaz
+ // First item with 2 paragraphs - foo\n\n baz
D.addParagraph().appendText("foo");
D.addParagraph().appendText("baz");
@@ -352,18 +606,27 @@ TEST(BulletList, Render) {
DeepDoc.addParagraph().appendText("baz");
StringRef ExpectedMarkdown = R"md(- foo
- bar
-- foo
- baz
- - foo
- - baz
+- foo
+
+ baz
+
+ - foo
+
+ - baz
+
baz)md";
+ EXPECT_EQ(L.asEscapedMarkdown(), ExpectedMarkdown);
EXPECT_EQ(L.asMarkdown(), ExpectedMarkdown);
StringRef ExpectedPlainText = R"pt(- foo
- bar
- foo
+
baz
+
- foo
+
- baz
+
baz)pt";
EXPECT_EQ(L.asPlainText(), ExpectedPlainText);
@@ -371,21 +634,31 @@ TEST(BulletList, Render) {
Inner.addParagraph().appendText("after");
ExpectedMarkdown = R"md(- foo
- bar
-- foo
- baz
- - foo
- - baz
+- foo
+
+ baz
+
+ - foo
+
+ - baz
+
baz
-
+
after)md";
+ EXPECT_EQ(L.asEscapedMarkdown(), ExpectedMarkdown);
EXPECT_EQ(L.asMarkdown(), ExpectedMarkdown);
ExpectedPlainText = R"pt(- foo
- bar
- foo
+
baz
+
- foo
+
- baz
+
baz
+
after)pt";
EXPECT_EQ(L.asPlainText(), ExpectedPlainText);
}
diff --git a/clang-tools-extra/clangd/unittests/tweaks/TweakTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/TweakTests.cpp
index e39b702..b6607e9 100644
--- a/clang-tools-extra/clangd/unittests/tweaks/TweakTests.cpp
+++ b/clang-tools-extra/clangd/unittests/tweaks/TweakTests.cpp
@@ -45,7 +45,7 @@ TEST(FileEdits, AbsolutePath) {
MemFS->addFile(Path, 0, llvm::MemoryBuffer::getMemBuffer("", Path));
FileManager FM(FileSystemOptions(), MemFS);
DiagnosticOptions DiagOpts;
- DiagnosticsEngine DE(new DiagnosticIDs, DiagOpts);
+ DiagnosticsEngine DE(DiagnosticIDs::create(), DiagOpts);
SourceManager SM(DE, FM);
for (const auto *Path : RelPaths) {
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index bccb0ca..e45f870 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -101,9 +101,25 @@ Improvements to clang-query
Improvements to clang-tidy
--------------------------
+- The :program:`run-clang-tidy.py` and :program:`clang-tidy-diff.py` scripts
+ now run checks in parallel by default using all available hardware threads.
+ Both scripts display the number of threads being used in their output.
+
New checks
^^^^^^^^^^
+- New :doc:`bugprone-invalid-enum-default-initialization
+ <clang-tidy/checks/bugprone/invalid-enum-default-initialization>` check.
+
+ Detects default initialization (to 0) of variables with ``enum`` type where
+ the enum has no enumerator with value of 0.
+
+- New :doc:`llvm-mlir-op-builder
+ <clang-tidy/checks/llvm/use-new-mlir-op-builder>` check.
+
+ Checks for uses of MLIR's old/to be deprecated ``OpBuilder::create<T>`` form
+ and suggests using ``T::create`` instead.
+
New check aliases
^^^^^^^^^^^^^^^^^
@@ -114,6 +130,40 @@ Changes in existing checks
<clang-tidy/checks/bugprone/infinite-loop>` check by adding detection for
variables introduced by structured bindings.
+- Improved :doc:`bugprone-signed-char-misuse
+ <clang-tidy/checks/bugprone/signed-char-misuse>` check by fixing
+ false positives on C23 enums with the fixed underlying type of signed char.
+
+- Improved :doc:`bugprone-unhandled-self-assignment
+ <clang-tidy/checks/bugprone/unhandled-self-assignment>` check by adding
+ an additional matcher that generalizes the copy-and-swap idiom pattern
+ detection.
+
+- Improved :doc:`misc-header-include-cycle
+ <clang-tidy/checks/misc/header-include-cycle>` check performance.
+
+- Improved :doc:`modernize-use-designated-initializers
+ <clang-tidy/checks/modernize/use-designated-initializers>` check to
+ suggest using designated initializers for aliased aggregate types.
+
+- Improved :doc:`modernize-use-std-format
+ <clang-tidy/checks/modernize/use-std-format>` check to correctly match
+ when the format string is converted to a different type by an implicit
+ constructor call.
+
+- Improved :doc:`modernize-use-std-print
+ <clang-tidy/checks/modernize/use-std-print>` check to correctly match
+ when the format string is converted to a different type by an implicit
+ constructor call.
+
+- Improved :doc:`portability-template-virtual-member-function
+ <clang-tidy/checks/portability/template-virtual-member-function>` check to
+ avoid false positives on pure virtual member functions.
+
+- Improved :doc:`readability-qualified-auto
+ <clang-tidy/checks/readability/qualified-auto>` check by adding the option
+ `IgnoreAliasing`, that allows not looking at underlying types of type aliases.
+
Removed checks
^^^^^^^^^^^^^^
@@ -140,4 +190,3 @@ Improvements to pp-trace
Clang-tidy Visual Studio plugin
-------------------------------
-
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst
new file mode 100644
index 0000000..a3bd2b6
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst
@@ -0,0 +1,72 @@
+.. title:: clang-tidy - bugprone-invalid-enum-default-initialization
+
+bugprone-invalid-enum-default-initialization
+============================================
+
+Detects default initialization (to 0) of variables with ``enum`` type where
+the enum has no enumerator with value of 0.
+
+In C++ a default initialization is performed if a variable is initialized with
+initializer list or in other implicit ways, and no value is specified at the
+initialization. In such cases the value 0 is used for the initialization.
+This also applies to enumerations even if it does not have an enumerator with
+value 0. In this way a variable with the ``enum`` type may contain initially an
+invalid value (if the program expects that it contains only the listed
+enumerator values).
+
+The check emits a warning only if an ``enum`` variable is default-initialized
+(contrary to not initialized) and the ``enum`` does not have an enumerator with
+value of 0. The type can be a scoped or non-scoped ``enum``. Unions are not
+handled by the check (if it contains a member of enumeration type).
+
+.. code-block:: c++
+
+ enum class Enum1: int {
+ A = 1,
+ B
+ };
+
+ enum class Enum0: int {
+ A = 0,
+ B
+ };
+
+ void f() {
+ Enum1 X1{}; // warn: 'X1' is initialized to 0
+ Enum1 X2 = Enum1(); // warn: 'X2' is initialized to 0
+ Enum1 X3; // no warning: 'X3' is not initialized
+ Enum0 X4{}; // no warning: type has an enumerator with value of 0
+ }
+
+ struct S1 {
+ Enum1 A;
+ S(): A() {} // warn: 'A' is initialized to 0
+ };
+
+ struct S2 {
+ int A;
+ Enum1 B;
+ };
+
+ S2 VarS2{}; // warn: member 'B' is initialized to 0
+
+The check applies to initialization of arrays or structures with initialization
+lists in C code too. In these cases elements not specified in the list (and have
+enum type) are set to 0.
+
+.. code-block:: c
+
+ enum Enum1 {
+ Enum1_A = 1,
+ Enum1_B
+ };
+ struct Struct1 {
+ int a;
+ enum Enum1 b;
+ };
+
+ enum Enum1 Array1[2] = {Enum1_A}; // warn: omitted elements are initialized to 0
+ enum Enum1 Array2[2][2] = {{Enum1_A}, {Enum1_A}}; // warn: last element of both nested arrays is initialized to 0
+ enum Enum1 Array3[2][2] = {{Enum1_A, Enum1_A}}; // warn: elements of second array are initialized to 0
+
+ struct Struct1 S1 = {1}; // warn: element 'b' is initialized to 0
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 0cffbd3..b6444eb 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -106,6 +106,7 @@ Clang-Tidy Checks
:doc:`bugprone-incorrect-roundings <bugprone/incorrect-roundings>`,
:doc:`bugprone-infinite-loop <bugprone/infinite-loop>`,
:doc:`bugprone-integer-division <bugprone/integer-division>`,
+ :doc:`bugprone-invalid-enum-default-initialization <bugprone/invalid-enum-default-initialization>`,
:doc:`bugprone-lambda-function-name <bugprone/lambda-function-name>`,
:doc:`bugprone-macro-parentheses <bugprone/macro-parentheses>`, "Yes"
:doc:`bugprone-macro-repeated-side-effects <bugprone/macro-repeated-side-effects>`,
@@ -247,6 +248,7 @@ Clang-Tidy Checks
:doc:`linuxkernel-must-check-errs <linuxkernel/must-check-errs>`,
:doc:`llvm-header-guard <llvm/header-guard>`,
:doc:`llvm-include-order <llvm/include-order>`, "Yes"
+ :doc:`llvm-use-new-mlir-op-builder <llvm/use-new-mlir-op-builder>`, "Yes"
:doc:`llvm-namespace-comment <llvm/namespace-comment>`,
:doc:`llvm-prefer-isa-or-dyn-cast-in-conditionals <llvm/prefer-isa-or-dyn-cast-in-conditionals>`, "Yes"
:doc:`llvm-prefer-register-over-unsigned <llvm/prefer-register-over-unsigned>`, "Yes"
diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/use-new-mlir-op-builder.rst b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-new-mlir-op-builder.rst
new file mode 100644
index 0000000..dc1989d
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-new-mlir-op-builder.rst
@@ -0,0 +1,21 @@
+.. title:: clang-tidy - llvm-use-new-mlir-op-builder
+
+llvm-mlir-op-builder
+====================
+
+Checks for uses of MLIR's old/to be deprecated ``OpBuilder::create<T>`` form
+and suggests using ``T::create`` instead.
+
+Example
+-------
+
+.. code-block:: c++
+
+ builder.create<FooOp>(builder.getUnknownLoc(), "baz");
+
+
+Transforms to:
+
+.. code-block:: c++
+
+ FooOp::create(builder, builder.getUnknownLoc(), "baz");
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/qualified-auto.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/qualified-auto.rst
index efa0857..34390e2 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/qualified-auto.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/qualified-auto.rst
@@ -96,3 +96,45 @@ Note in the LLVM alias, the default value is `false`.
matched against only the type name (i.e. ``Type``). E.g. to suppress reports
for ``std::array`` iterators use `std::array<.*>::(const_)?iterator` string.
The default is an empty string.
+
+.. option:: IgnoreAliasing
+
+ If set to `true` the check will use the underlying type to determine the type
+ that ``auto`` is deduced to. If set to `false` the check will not look beyond
+ the first type alias.
+ Default value is `true`.
+
+ .. code-block:: c++
+
+ using IntPtr = int*;
+ IntPtr foo();
+
+ auto bar = foo();
+
+ If :option:`IgnoreAliasing` is set to `true`, it will be transformed into:
+
+ .. code-block:: c++
+
+ auto *bar = foo();
+
+ Otherwise no changes will occur.
+
+Limitations
+-----------
+
+When :option:`IgnoreAliasing` is set to `false`, there are cases where
+Clang has not preserved the type alias and the underlying type will be used so
+false positives may occur.
+
+For example:
+
+.. code-block:: c++
+
+ using IntPtr = int *;
+
+ void loopPtr(const std::vector<IntPtr> &VectorIntPtr) {
+
+ // May fail for IgnoreAliasing==false as AST does not have the 'IntPtr'
+ for (auto Data : VectorIntPtr) {
+ }
+ }
diff --git a/clang-tools-extra/modularize/ModularizeUtilities.cpp b/clang-tools-extra/modularize/ModularizeUtilities.cpp
index 8a24f21..4dd84fe 100644
--- a/clang-tools-extra/modularize/ModularizeUtilities.cpp
+++ b/clang-tools-extra/modularize/ModularizeUtilities.cpp
@@ -47,7 +47,7 @@ ModularizeUtilities::ModularizeUtilities(std::vector<std::string> &InputPaths,
ProblemFilesPath(ProblemFilesListPath), HasModuleMap(false),
MissingHeaderCount(0),
// Init clang stuff needed for loading the module map and preprocessing.
- LangOpts(new LangOptions()), DiagIDs(new DiagnosticIDs()),
+ LangOpts(new LangOptions()), DiagIDs(DiagnosticIDs::create()),
DC(llvm::errs(), DiagnosticOpts),
Diagnostics(new DiagnosticsEngine(DiagIDs, DiagnosticOpts, &DC, false)),
TargetOpts(new ModuleMapTargetOptions()),
diff --git a/clang-tools-extra/test/clang-apply-replacements/basic.cpp b/clang-tools-extra/test/clang-apply-replacements/basic.cpp
index 4f19a96..2399307 100644
--- a/clang-tools-extra/test/clang-apply-replacements/basic.cpp
+++ b/clang-tools-extra/test/clang-apply-replacements/basic.cpp
@@ -1,17 +1,17 @@
-// RUN: mkdir -p %T/Inputs/basic
-// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/basic/basic.h > %T/Inputs/basic/basic.h
-// RUN: sed "s#\$(path)#%/T/Inputs/basic#" %S/Inputs/basic/file1.yaml > %T/Inputs/basic/file1.yaml
-// RUN: sed "s#\$(path)#%/T/Inputs/basic#" %S/Inputs/basic/file2.yaml > %T/Inputs/basic/file2.yaml
-// RUN: clang-apply-replacements %T/Inputs/basic
-// RUN: FileCheck -input-file=%T/Inputs/basic/basic.h %S/Inputs/basic/basic.h
+// RUN: mkdir -p %t.dir/Inputs/basic
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/basic/basic.h > %t.dir/Inputs/basic/basic.h
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/basic#" %S/Inputs/basic/file1.yaml > %t.dir/Inputs/basic/file1.yaml
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/basic#" %S/Inputs/basic/file2.yaml > %t.dir/Inputs/basic/file2.yaml
+// RUN: clang-apply-replacements %t.dir/Inputs/basic
+// RUN: FileCheck -input-file=%t.dir/Inputs/basic/basic.h %S/Inputs/basic/basic.h
//
// Check that the yaml files are *not* deleted after running clang-apply-replacements without remove-change-desc-files.
-// RUN: ls -1 %T/Inputs/basic | FileCheck %s --check-prefix=YAML
+// RUN: ls -1 %t.dir/Inputs/basic | FileCheck %s --check-prefix=YAML
//
// Check that the yaml files *are* deleted after running clang-apply-replacements with remove-change-desc-files.
-// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/basic/basic.h > %T/Inputs/basic/basic.h
-// RUN: clang-apply-replacements -remove-change-desc-files %T/Inputs/basic
-// RUN: ls -1 %T/Inputs/basic | FileCheck %s --check-prefix=NO_YAML
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/basic/basic.h > %t.dir/Inputs/basic/basic.h
+// RUN: clang-apply-replacements -remove-change-desc-files %t.dir/Inputs/basic
+// RUN: ls -1 %t.dir/Inputs/basic | FileCheck %s --check-prefix=NO_YAML
//
// YAML: {{^file.\.yaml$}}
// NO_YAML-NOT: {{^file.\.yaml$}}
diff --git a/clang-tools-extra/test/clang-apply-replacements/conflict.cpp b/clang-tools-extra/test/clang-apply-replacements/conflict.cpp
index c1f2342..7b0a8c2 100644
--- a/clang-tools-extra/test/clang-apply-replacements/conflict.cpp
+++ b/clang-tools-extra/test/clang-apply-replacements/conflict.cpp
@@ -1,17 +1,17 @@
-// RUN: mkdir -p %T/Inputs/conflict
-// RUN: sed "s#\$(path)#%/S/Inputs/conflict#" %S/Inputs/conflict/file1.yaml > %T/Inputs/conflict/file1.yaml
-// RUN: sed "s#\$(path)#%/S/Inputs/conflict#" %S/Inputs/conflict/file2.yaml > %T/Inputs/conflict/file2.yaml
-// RUN: sed "s#\$(path)#%/S/Inputs/conflict#" %S/Inputs/conflict/file3.yaml > %T/Inputs/conflict/file3.yaml
-// RUN: sed "s#\$(path)#%/S/Inputs/conflict#" %S/Inputs/conflict/expected.txt > %T/Inputs/conflict/expected.txt
-// RUN: not clang-apply-replacements %T/Inputs/conflict > %T/Inputs/conflict/output.txt 2>&1
-// RUN: diff -b %T/Inputs/conflict/output.txt %T/Inputs/conflict/expected.txt
+// RUN: mkdir -p %t.dir/Inputs/conflict
+// RUN: sed "s#\$(path)#%/S/Inputs/conflict#" %S/Inputs/conflict/file1.yaml > %t.dir/Inputs/conflict/file1.yaml
+// RUN: sed "s#\$(path)#%/S/Inputs/conflict#" %S/Inputs/conflict/file2.yaml > %t.dir/Inputs/conflict/file2.yaml
+// RUN: sed "s#\$(path)#%/S/Inputs/conflict#" %S/Inputs/conflict/file3.yaml > %t.dir/Inputs/conflict/file3.yaml
+// RUN: sed "s#\$(path)#%/S/Inputs/conflict#" %S/Inputs/conflict/expected.txt > %t.dir/Inputs/conflict/expected.txt
+// RUN: not clang-apply-replacements %t.dir/Inputs/conflict > %t.dir/Inputs/conflict/output.txt 2>&1
+// RUN: diff -b %t.dir/Inputs/conflict/output.txt %t.dir/Inputs/conflict/expected.txt
//
// Check that the yaml files are *not* deleted after running clang-apply-replacements without remove-change-desc-files even when there is a failure.
-// RUN: ls -1 %T/Inputs/conflict | FileCheck %s --check-prefix=YAML
+// RUN: ls -1 %t.dir/Inputs/conflict | FileCheck %s --check-prefix=YAML
//
// Check that the yaml files *are* deleted after running clang-apply-replacements with remove-change-desc-files even when there is a failure.
-// RUN: not clang-apply-replacements %T/Inputs/conflict -remove-change-desc-files > %T/Inputs/conflict/output.txt 2>&1
-// RUN: ls -1 %T/Inputs/conflict | FileCheck %s --check-prefix=NO_YAML
+// RUN: not clang-apply-replacements %t.dir/Inputs/conflict -remove-change-desc-files > %t.dir/Inputs/conflict/output.txt 2>&1
+// RUN: ls -1 %t.dir/Inputs/conflict | FileCheck %s --check-prefix=NO_YAML
//
// YAML: {{^file.\.yaml$}}
// NO_YAML-NOT: {{^file.\.yaml$}}
diff --git a/clang-tools-extra/test/clang-apply-replacements/crlf.cpp b/clang-tools-extra/test/clang-apply-replacements/crlf.cpp
index 15ba5b5..f40429e 100644
--- a/clang-tools-extra/test/clang-apply-replacements/crlf.cpp
+++ b/clang-tools-extra/test/clang-apply-replacements/crlf.cpp
@@ -1,5 +1,5 @@
-// RUN: mkdir -p %T/Inputs/crlf
-// RUN: cat %S/Inputs/crlf/crlf.cpp > %T/Inputs/crlf/crlf.cpp
-// RUN: sed "s#\$(path)#%/T/Inputs/crlf#" %S/Inputs/crlf/file1.yaml > %T/Inputs/crlf/file1.yaml
-// RUN: clang-apply-replacements %T/Inputs/crlf
-// RUN: diff %T/Inputs/crlf/crlf.cpp %S/Inputs/crlf/crlf.cpp.expected
+// RUN: mkdir -p %t.dir/Inputs/crlf
+// RUN: cat %S/Inputs/crlf/crlf.cpp > %t.dir/Inputs/crlf/crlf.cpp
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/crlf#" %S/Inputs/crlf/file1.yaml > %t.dir/Inputs/crlf/file1.yaml
+// RUN: clang-apply-replacements %t.dir/Inputs/crlf
+// RUN: diff %t.dir/Inputs/crlf/crlf.cpp %S/Inputs/crlf/crlf.cpp.expected
diff --git a/clang-tools-extra/test/clang-apply-replacements/format-header.cpp b/clang-tools-extra/test/clang-apply-replacements/format-header.cpp
index 6a221c4..9d2680e 100644
--- a/clang-tools-extra/test/clang-apply-replacements/format-header.cpp
+++ b/clang-tools-extra/test/clang-apply-replacements/format-header.cpp
@@ -1,13 +1,13 @@
-// RUN: mkdir -p %T/Inputs/format_header_yes
-// RUN: mkdir -p %T/Inputs/format_header_no
+// RUN: mkdir -p %t.dir/Inputs/format_header_yes
+// RUN: mkdir -p %t.dir/Inputs/format_header_no
//
//
-// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/format_header/yes.cpp > %T/Inputs/format_header_yes/yes.cpp
-// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/format_header/no.cpp > %T/Inputs/format_header_no/no.cpp
-// RUN: sed "s#\$(path)#%/T/Inputs/format_header_yes#" %S/Inputs/format_header/yes.yaml > %T/Inputs/format_header_yes/yes.yaml
-// RUN: sed "s#\$(path)#%/T/Inputs/format_header_no#" %S/Inputs/format_header/no.yaml > %T/Inputs/format_header_no/no.yaml
-// RUN: clang-apply-replacements -format -style="{BasedOnStyle: llvm, SortIncludes: CaseSensitive}" %T/Inputs/format_header_yes
-// RUN: clang-apply-replacements %T/Inputs/format_header_no
-// RUN: FileCheck --strict-whitespace -input-file=%T/Inputs/format_header_yes/yes.cpp %S/Inputs/format_header/yes.cpp
-// RUN: FileCheck --strict-whitespace -input-file=%T/Inputs/format_header_no/no.cpp %S/Inputs/format_header/no.cpp
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/format_header/yes.cpp > %t.dir/Inputs/format_header_yes/yes.cpp
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/format_header/no.cpp > %t.dir/Inputs/format_header_no/no.cpp
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/format_header_yes#" %S/Inputs/format_header/yes.yaml > %t.dir/Inputs/format_header_yes/yes.yaml
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/format_header_no#" %S/Inputs/format_header/no.yaml > %t.dir/Inputs/format_header_no/no.yaml
+// RUN: clang-apply-replacements -format -style="{BasedOnStyle: llvm, SortIncludes: CaseSensitive}" %t.dir/Inputs/format_header_yes
+// RUN: clang-apply-replacements %t.dir/Inputs/format_header_no
+// RUN: FileCheck --strict-whitespace -input-file=%t.dir/Inputs/format_header_yes/yes.cpp %S/Inputs/format_header/yes.cpp
+// RUN: FileCheck --strict-whitespace -input-file=%t.dir/Inputs/format_header_no/no.cpp %S/Inputs/format_header/no.cpp
//
diff --git a/clang-tools-extra/test/clang-apply-replacements/format.cpp b/clang-tools-extra/test/clang-apply-replacements/format.cpp
index 7de320d..0f40ef62 100644
--- a/clang-tools-extra/test/clang-apply-replacements/format.cpp
+++ b/clang-tools-extra/test/clang-apply-replacements/format.cpp
@@ -1,15 +1,15 @@
-// RUN: mkdir -p %T/Inputs/format
+// RUN: mkdir -p %t.dir/Inputs/format
//
// yes.cpp requires formatting after replacements are applied. no.cpp does not.
// The presence of no.cpp ensures that files that don't need formatting still
// have their new state written to disk after applying replacements.
//
-// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/format/yes.cpp > %T/Inputs/format/yes.cpp
-// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/format/no.cpp > %T/Inputs/format/no.cpp
-// RUN: sed "s#\$(path)#%/T/Inputs/format#" %S/Inputs/format/yes.yaml > %T/Inputs/format/yes.yaml
-// RUN: sed "s#\$(path)#%/T/Inputs/format#" %S/Inputs/format/no.yaml > %T/Inputs/format/no.yaml
-// RUN: clang-apply-replacements -format %T/Inputs/format
-// RUN: FileCheck --strict-whitespace -input-file=%T/Inputs/format/yes.cpp %S/Inputs/format/yes.cpp
-// RUN: FileCheck --strict-whitespace -input-file=%T/Inputs/format/no.cpp %S/Inputs/format/no.cpp
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/format/yes.cpp > %t.dir/Inputs/format/yes.cpp
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/format/no.cpp > %t.dir/Inputs/format/no.cpp
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/format#" %S/Inputs/format/yes.yaml > %t.dir/Inputs/format/yes.yaml
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/format#" %S/Inputs/format/no.yaml > %t.dir/Inputs/format/no.yaml
+// RUN: clang-apply-replacements -format %t.dir/Inputs/format
+// RUN: FileCheck --strict-whitespace -input-file=%t.dir/Inputs/format/yes.cpp %S/Inputs/format/yes.cpp
+// RUN: FileCheck --strict-whitespace -input-file=%t.dir/Inputs/format/no.cpp %S/Inputs/format/no.cpp
//
-// RUN not clang-apply-replacements -format=blah %T/Inputs/format
+// RUN not clang-apply-replacements -format=blah %t.dir/Inputs/format
diff --git a/clang-tools-extra/test/clang-apply-replacements/identical-in-TU.cpp b/clang-tools-extra/test/clang-apply-replacements/identical-in-TU.cpp
index 024db11..df9c4fc 100644
--- a/clang-tools-extra/test/clang-apply-replacements/identical-in-TU.cpp
+++ b/clang-tools-extra/test/clang-apply-replacements/identical-in-TU.cpp
@@ -1,10 +1,10 @@
-// RUN: mkdir -p %T/Inputs/identical-in-TU
+// RUN: mkdir -p %t.dir/Inputs/identical-in-TU
-// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/identical-in-TU/identical-in-TU.cpp > %T/Inputs/identical-in-TU/identical-in-TU.cpp
-// RUN: sed "s#\$(path)#%/T/Inputs/identical-in-TU#" %S/Inputs/identical-in-TU/file1.yaml > %T/Inputs/identical-in-TU/file1.yaml
-// RUN: sed "s#\$(path)#%/T/Inputs/identical-in-TU#" %S/Inputs/identical-in-TU/file2.yaml > %T/Inputs/identical-in-TU/file2.yaml
-// RUN: clang-apply-replacements %T/Inputs/identical-in-TU
-// RUN: FileCheck -input-file=%T/Inputs/identical-in-TU/identical-in-TU.cpp %S/Inputs/identical-in-TU/identical-in-TU.cpp
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/identical-in-TU/identical-in-TU.cpp > %t.dir/Inputs/identical-in-TU/identical-in-TU.cpp
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/identical-in-TU#" %S/Inputs/identical-in-TU/file1.yaml > %t.dir/Inputs/identical-in-TU/file1.yaml
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/identical-in-TU#" %S/Inputs/identical-in-TU/file2.yaml > %t.dir/Inputs/identical-in-TU/file2.yaml
+// RUN: clang-apply-replacements %t.dir/Inputs/identical-in-TU
+// RUN: FileCheck -input-file=%t.dir/Inputs/identical-in-TU/identical-in-TU.cpp %S/Inputs/identical-in-TU/identical-in-TU.cpp
// Similar to identical test but each yaml file contains the same fix twice.
// This check ensures that only the duplicated replacements in a single yaml
diff --git a/clang-tools-extra/test/clang-apply-replacements/identical.cpp b/clang-tools-extra/test/clang-apply-replacements/identical.cpp
index ffbf2e3..8a2d1e5 100644
--- a/clang-tools-extra/test/clang-apply-replacements/identical.cpp
+++ b/clang-tools-extra/test/clang-apply-replacements/identical.cpp
@@ -1,6 +1,6 @@
-// RUN: mkdir -p %T/Inputs/identical
-// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/identical/identical.cpp > %T/Inputs/identical/identical.cpp
-// RUN: sed "s#\$(path)#%/T/Inputs/identical#" %S/Inputs/identical/file1.yaml > %T/Inputs/identical/file1.yaml
-// RUN: sed "s#\$(path)#%/T/Inputs/identical#" %S/Inputs/identical/file2.yaml > %T/Inputs/identical/file2.yaml
-// RUN: clang-apply-replacements %T/Inputs/identical
-// RUN: FileCheck -input-file=%T/Inputs/identical/identical.cpp %S/Inputs/identical/identical.cpp
+// RUN: mkdir -p %t.dir/Inputs/identical
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/identical/identical.cpp > %t.dir/Inputs/identical/identical.cpp
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/identical#" %S/Inputs/identical/file1.yaml > %t.dir/Inputs/identical/file1.yaml
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/identical#" %S/Inputs/identical/file2.yaml > %t.dir/Inputs/identical/file2.yaml
+// RUN: clang-apply-replacements %t.dir/Inputs/identical
+// RUN: FileCheck -input-file=%t.dir/Inputs/identical/identical.cpp %S/Inputs/identical/identical.cpp
diff --git a/clang-tools-extra/test/clang-apply-replacements/ignore-conflict.cpp b/clang-tools-extra/test/clang-apply-replacements/ignore-conflict.cpp
index 4e681dd..e310256 100644
--- a/clang-tools-extra/test/clang-apply-replacements/ignore-conflict.cpp
+++ b/clang-tools-extra/test/clang-apply-replacements/ignore-conflict.cpp
@@ -1,5 +1,5 @@
-// RUN: mkdir -p %T/Inputs/ignore-conflict
-// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/ignore-conflict/ignore-conflict.cpp > %T/Inputs/ignore-conflict/ignore-conflict.cpp
-// RUN: sed "s#\$(path)#%/T/Inputs/ignore-conflict#" %S/Inputs/ignore-conflict/file1.yaml > %T/Inputs/ignore-conflict/file1.yaml
-// RUN: clang-apply-replacements --ignore-insert-conflict %T/Inputs/ignore-conflict
-// RUN: FileCheck -input-file=%T/Inputs/ignore-conflict/ignore-conflict.cpp %S/Inputs/ignore-conflict/ignore-conflict.cpp
+// RUN: mkdir -p %t.dir/Inputs/ignore-conflict
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/ignore-conflict/ignore-conflict.cpp > %t.dir/Inputs/ignore-conflict/ignore-conflict.cpp
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/ignore-conflict#" %S/Inputs/ignore-conflict/file1.yaml > %t.dir/Inputs/ignore-conflict/file1.yaml
+// RUN: clang-apply-replacements --ignore-insert-conflict %t.dir/Inputs/ignore-conflict
+// RUN: FileCheck -input-file=%t.dir/Inputs/ignore-conflict/ignore-conflict.cpp %S/Inputs/ignore-conflict/ignore-conflict.cpp
diff --git a/clang-tools-extra/test/clang-apply-replacements/invalid-files.cpp b/clang-tools-extra/test/clang-apply-replacements/invalid-files.cpp
index b0eb9ef..09efd4c 100644
--- a/clang-tools-extra/test/clang-apply-replacements/invalid-files.cpp
+++ b/clang-tools-extra/test/clang-apply-replacements/invalid-files.cpp
@@ -1,6 +1,6 @@
-// RUN: mkdir -p %T/invalid-files
-// RUN: cp %S/Inputs/invalid-files/invalid-files.yaml %T/invalid-files/invalid-files.yaml
-// RUN: clang-apply-replacements %T/invalid-files
+// RUN: mkdir -p %t.dir/invalid-files
+// RUN: cp %S/Inputs/invalid-files/invalid-files.yaml %t.dir/invalid-files/invalid-files.yaml
+// RUN: clang-apply-replacements %t.dir/invalid-files
//
// Check that the yaml files are *not* deleted after running clang-apply-replacements without remove-change-desc-files.
-// RUN: ls %T/invalid-files/invalid-files.yaml
+// RUN: ls %t.dir/invalid-files/invalid-files.yaml
diff --git a/clang-tools-extra/test/clang-apply-replacements/order-dependent.cpp b/clang-tools-extra/test/clang-apply-replacements/order-dependent.cpp
index 769f4f7..32a3bd1 100644
--- a/clang-tools-extra/test/clang-apply-replacements/order-dependent.cpp
+++ b/clang-tools-extra/test/clang-apply-replacements/order-dependent.cpp
@@ -1,7 +1,7 @@
-// RUN: mkdir -p %T/Inputs/order-dependent
-// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/order-dependent/order-dependent.cpp > %T/Inputs/order-dependent/order-dependent.cpp
-// RUN: sed "s#\$(path)#%/T/Inputs/order-dependent#" %S/Inputs/order-dependent/file1.yaml > %T/Inputs/order-dependent/file1.yaml
-// RUN: sed "s#\$(path)#%/T/Inputs/order-dependent#" %S/Inputs/order-dependent/file2.yaml > %T/Inputs/order-dependent/file2.yaml
-// RUN: sed "s#\$(path)#%/T/Inputs/order-dependent#" %S/Inputs/order-dependent/expected.txt > %T/Inputs/order-dependent/expected.txt
-// RUN: not clang-apply-replacements %T/Inputs/order-dependent > %T/Inputs/order-dependent/output.txt 2>&1
-// RUN: diff -b %T/Inputs/order-dependent/output.txt %T/Inputs/order-dependent/expected.txt
+// RUN: mkdir -p %t.dir/Inputs/order-dependent
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/order-dependent/order-dependent.cpp > %t.dir/Inputs/order-dependent/order-dependent.cpp
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/order-dependent#" %S/Inputs/order-dependent/file1.yaml > %t.dir/Inputs/order-dependent/file1.yaml
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/order-dependent#" %S/Inputs/order-dependent/file2.yaml > %t.dir/Inputs/order-dependent/file2.yaml
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/order-dependent#" %S/Inputs/order-dependent/expected.txt > %t.dir/Inputs/order-dependent/expected.txt
+// RUN: not clang-apply-replacements %t.dir/Inputs/order-dependent > %t.dir/Inputs/order-dependent/output.txt 2>&1
+// RUN: diff -b %t.dir/Inputs/order-dependent/output.txt %t.dir/Inputs/order-dependent/expected.txt
diff --git a/clang-tools-extra/test/clang-apply-replacements/relative-paths.cpp b/clang-tools-extra/test/clang-apply-replacements/relative-paths.cpp
index 92cde84..36e3e89 100644
--- a/clang-tools-extra/test/clang-apply-replacements/relative-paths.cpp
+++ b/clang-tools-extra/test/clang-apply-replacements/relative-paths.cpp
@@ -1,7 +1,7 @@
-// RUN: mkdir -p %T/Inputs/relative-paths
-// RUN: mkdir -p %T/Inputs/relative-paths/subdir
-// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/relative-paths/basic.h > %T/Inputs/relative-paths/basic.h
-// RUN: sed "s#\$(path)#%/T/Inputs/relative-paths#" %S/Inputs/relative-paths/file1.yaml > %T/Inputs/relative-paths/file1.yaml
-// RUN: sed "s#\$(path)#%/T/Inputs/relative-paths#" %S/Inputs/relative-paths/file2.yaml > %T/Inputs/relative-paths/file2.yaml
-// RUN: clang-apply-replacements %T/Inputs/relative-paths
-// RUN: FileCheck -input-file=%T/Inputs/relative-paths/basic.h %S/Inputs/relative-paths/basic.h
+// RUN: mkdir -p %t.dir/Inputs/relative-paths
+// RUN: mkdir -p %t.dir/Inputs/relative-paths/subdir
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/relative-paths/basic.h > %t.dir/Inputs/relative-paths/basic.h
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/relative-paths#" %S/Inputs/relative-paths/file1.yaml > %t.dir/Inputs/relative-paths/file1.yaml
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/relative-paths#" %S/Inputs/relative-paths/file2.yaml > %t.dir/Inputs/relative-paths/file2.yaml
+// RUN: clang-apply-replacements %t.dir/Inputs/relative-paths
+// RUN: FileCheck -input-file=%t.dir/Inputs/relative-paths/basic.h %S/Inputs/relative-paths/basic.h
diff --git a/clang-tools-extra/test/clang-apply-replacements/yml-basic.cpp b/clang-tools-extra/test/clang-apply-replacements/yml-basic.cpp
index e6ee919..e076ff7 100644
--- a/clang-tools-extra/test/clang-apply-replacements/yml-basic.cpp
+++ b/clang-tools-extra/test/clang-apply-replacements/yml-basic.cpp
@@ -1,17 +1,17 @@
-// RUN: mkdir -p %T/Inputs/yml-basic
-// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/yml-basic/basic.h > %T/Inputs/yml-basic/basic.h
-// RUN: sed "s#\$(path)#%/T/Inputs/yml-basic#" %S/Inputs/yml-basic/file1.yml > %T/Inputs/yml-basic/file1.yml
-// RUN: sed "s#\$(path)#%/T/Inputs/yml-basic#" %S/Inputs/yml-basic/file2.yml > %T/Inputs/yml-basic/file2.yml
-// RUN: clang-apply-replacements %T/Inputs/yml-basic
-// RUN: FileCheck -input-file=%T/Inputs/yml-basic/basic.h %S/Inputs/yml-basic/basic.h
+// RUN: mkdir -p %t.dir/Inputs/yml-basic
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/yml-basic/basic.h > %t.dir/Inputs/yml-basic/basic.h
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/yml-basic#" %S/Inputs/yml-basic/file1.yml > %t.dir/Inputs/yml-basic/file1.yml
+// RUN: sed "s#\$(path)#%/t.dir/Inputs/yml-basic#" %S/Inputs/yml-basic/file2.yml > %t.dir/Inputs/yml-basic/file2.yml
+// RUN: clang-apply-replacements %t.dir/Inputs/yml-basic
+// RUN: FileCheck -input-file=%t.dir/Inputs/yml-basic/basic.h %S/Inputs/yml-basic/basic.h
//
// Check that the yml files are *not* deleted after running clang-apply-replacements without remove-change-desc-files.
-// RUN: ls -1 %T/Inputs/yml-basic | FileCheck %s --check-prefix=YML
+// RUN: ls -1 %t.dir/Inputs/yml-basic | FileCheck %s --check-prefix=YML
//
// Check that the yml files *are* deleted after running clang-apply-replacements with remove-change-desc-files.
-// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/yml-basic/basic.h > %T/Inputs/yml-basic/basic.h
-// RUN: clang-apply-replacements -remove-change-desc-files %T/Inputs/yml-basic
-// RUN: ls -1 %T/Inputs/yml-basic | FileCheck %s --check-prefix=NO_YML
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/yml-basic/basic.h > %t.dir/Inputs/yml-basic/basic.h
+// RUN: clang-apply-replacements -remove-change-desc-files %t.dir/Inputs/yml-basic
+// RUN: ls -1 %t.dir/Inputs/yml-basic | FileCheck %s --check-prefix=NO_YML
//
// YML: {{^file.\.yml$}}
// NO_YML-NOT: {{^file.\.yml$}}
diff --git a/clang-tools-extra/test/clang-change-namespace/allow-list.cpp b/clang-tools-extra/test/clang-change-namespace/allow-list.cpp
index 7a941dcb..3b0d5b9 100644
--- a/clang-tools-extra/test/clang-change-namespace/allow-list.cpp
+++ b/clang-tools-extra/test/clang-change-namespace/allow-list.cpp
@@ -1,5 +1,5 @@
-// RUN: echo "^std::.*$" > %T/allow-list.txt
-// RUN: clang-change-namespace -old_namespace "na::nb" -new_namespace "x::y" --file_pattern ".*" --allowed_file %T/allow-list.txt %s -- | sed 's,// CHECK.*,,' | FileCheck %s
+// RUN: echo "^std::.*$" > %t.allow-list.txt
+// RUN: clang-change-namespace -old_namespace "na::nb" -new_namespace "x::y" --file_pattern ".*" --allowed_file %t.allow-list.txt %s -- | sed 's,// CHECK.*,,' | FileCheck %s
#include "Inputs/fake-std.h"
diff --git a/clang-tools-extra/test/clang-change-namespace/macro.cpp b/clang-tools-extra/test/clang-change-namespace/macro.cpp
index 40c4caf..f0b134d 100644
--- a/clang-tools-extra/test/clang-change-namespace/macro.cpp
+++ b/clang-tools-extra/test/clang-change-namespace/macro.cpp
@@ -1,15 +1,16 @@
-// RUN: cp %S/macro.cpp %T/macro.cpp
-// RUN: echo "#define USING using na::nc::X" > %T/macro.h
+// RUN: mkdir -p %t.dir
+// RUN: cp %S/macro.cpp %t.dir/macro.cpp
+// RUN: echo "#define USING using na::nc::X" > %t.dir/macro.h
//
-// RUN: clang-change-namespace -old_namespace "na::nb" -new_namespace "x::y" --file_pattern "macro.cpp$" --i %T/macro.cpp --
-// RUN: FileCheck -input-file=%T/macro.cpp -check-prefix=CHECK-CC %s
-// RUN: FileCheck -input-file=%T/macro.h -check-prefix=CHECK-HEADER %s
+// RUN: clang-change-namespace -old_namespace "na::nb" -new_namespace "x::y" --file_pattern "macro.cpp$" --i %t.dir/macro.cpp --
+// RUN: FileCheck -input-file=%t.dir/macro.cpp -check-prefix=CHECK-CC %s
+// RUN: FileCheck -input-file=%t.dir/macro.h -check-prefix=CHECK-HEADER %s
//
-// RUN: cp %S/macro.cpp %T/macro.cpp
-// RUN: echo "#define USING using na::nc::X" > %T/macro.h
-// RUN: clang-change-namespace -old_namespace "na::nb" -new_namespace "x::y" --file_pattern ".*" --i %T/macro.cpp --
-// RUN: FileCheck -input-file=%T/macro.cpp -check-prefix=CHECK-CC %s
-// RUN: FileCheck -input-file=%T/macro.h -check-prefix=CHECK-CHANGED-HEADER %s
+// RUN: cp %S/macro.cpp %t.dir/macro.cpp
+// RUN: echo "#define USING using na::nc::X" > %t.dir/macro.h
+// RUN: clang-change-namespace -old_namespace "na::nb" -new_namespace "x::y" --file_pattern ".*" --i %t.dir/macro.cpp --
+// RUN: FileCheck -input-file=%t.dir/macro.cpp -check-prefix=CHECK-CC %s
+// RUN: FileCheck -input-file=%t.dir/macro.h -check-prefix=CHECK-CHANGED-HEADER %s
#include "macro.h"
namespace na { namespace nc { class X{}; } }
diff --git a/clang-tools-extra/test/clang-doc/Inputs/basic-project/include/Circle.h b/clang-tools-extra/test/clang-doc/Inputs/basic-project/include/Circle.h
index 7bee3ff..74bffcd 100644
--- a/clang-tools-extra/test/clang-doc/Inputs/basic-project/include/Circle.h
+++ b/clang-tools-extra/test/clang-doc/Inputs/basic-project/include/Circle.h
@@ -26,6 +26,10 @@ public:
/**
* @brief Calculates the perimeter of the circle.
*
+ * @code
+ * Circle circle(5.0);
+ * double perimeter = circle.perimeter();
+ * @endcode
* @return double The perimeter of the circle.
*/
double perimeter() const override;
diff --git a/clang-tools-extra/test/clang-doc/basic-project.mustache.test b/clang-tools-extra/test/clang-doc/basic-project.mustache.test
index 7bfdd4b..e2d9da6 100644
--- a/clang-tools-extra/test/clang-doc/basic-project.mustache.test
+++ b/clang-tools-extra/test/clang-doc/basic-project.mustache.test
@@ -2,17 +2,17 @@
// RUN: sed 's|$test_dir|%/S|g' %S/Inputs/basic-project/database_template.json > %t/build/compile_commands.json
// RUN: clang-doc --format=mustache --output=%t/docs --executor=all-TUs %t/build/compile_commands.json
-// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Shape.html -check-prefix=HTML-SHAPE
-// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Calculator.html -check-prefix=HTML-CALC
-// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Rectangle.html -check-prefix=HTML-RECTANGLE
-// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Circle.html -check-prefix=HTML-CIRCLE
+// RUN: FileCheck %s -input-file=%t/docs/_ZTV5Shape.html -check-prefix=HTML-SHAPE
+// RUN: FileCheck %s -input-file=%t/docs/_ZTV10Calculator.html -check-prefix=HTML-CALC
+// RUN: FileCheck %s -input-file=%t/docs/_ZTV9Rectangle.html -check-prefix=HTML-RECTANGLE
+// RUN: FileCheck %s -input-file=%t/docs/_ZTV6Circle.html -check-prefix=HTML-CIRCLE
HTML-SHAPE: <html lang="en-US">
HTML-SHAPE: <head>
HTML-SHAPE: <meta charset="utf-8"/>
HTML-SHAPE: <title>Shape</title>
-HTML-SHAPE: <link rel="stylesheet" type="text/css" href="../clang-doc-mustache.css"/>
-HTML-SHAPE: <script src="../mustache-index.js"></script>
+HTML-SHAPE: <link rel="stylesheet" type="text/css" href="./clang-doc-mustache.css"/>
+HTML-SHAPE: <script src="./mustache-index.js"></script>
HTML-SHAPE: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
HTML-SHAPE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
HTML-SHAPE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/cpp.min.js"></script>
@@ -60,6 +60,17 @@ HTML-SHAPE: <div class="content">
HTML-SHAPE: <section class="hero section-container">
HTML-SHAPE: <div class="hero__title">
HTML-SHAPE: <h1 class="hero__title-large">class Shape</h1>
+HTML-SHAPE: <div class="hero__subtitle">
+HTML-SHAPE: <div>
+HTML-SHAPE: <p> Abstract base class for shapes.</p>
+HTML-SHAPE: </div>
+HTML-SHAPE: <div>
+HTML-SHAPE: <p></p>
+HTML-SHAPE: </div>
+HTML-SHAPE: <div>
+HTML-SHAPE: <p> Provides a common interface for different types of shapes.</p>
+HTML-SHAPE: </div>
+HTML-SHAPE: </div>
HTML-SHAPE: </div>
HTML-SHAPE: </section>
HTML-SHAPE: <section id="PublicMethods" class="section-container">
@@ -72,6 +83,19 @@ HTML-SHAPE: <code class="language-cpp code-clang-doc">
HTML-SHAPE: double area ()
HTML-SHAPE: </code>
HTML-SHAPE: </pre>
+HTML-SHAPE: <div>
+HTML-SHAPE: <div>
+HTML-SHAPE: <p> Calculates the area of the shape.</p>
+HTML-SHAPE: </div>
+HTML-SHAPE: <div>
+HTML-SHAPE: <p></p>
+HTML-SHAPE: </div>
+HTML-SHAPE: <div>
+HTML-SHAPE: <p></p>
+HTML-SHAPE: </div>
+HTML-SHAPE: <h3>Returns</h3>
+HTML-SHAPE: <p> double The area of the shape.</p>
+HTML-SHAPE: </div>
HTML-SHAPE: </div>
HTML-SHAPE: </div>
HTML-SHAPE: <div class="delimiter-container">
@@ -81,6 +105,19 @@ HTML-SHAPE: <code class="language-cpp code-clang-doc">
HTML-SHAPE: double perimeter ()
HTML-SHAPE: </code>
HTML-SHAPE: </pre>
+HTML-SHAPE: <div>
+HTML-SHAPE: <div>
+HTML-SHAPE: <p> Calculates the perimeter of the shape.</p>
+HTML-SHAPE: </div>
+HTML-SHAPE: <div>
+HTML-SHAPE: <p></p>
+HTML-SHAPE: </div>
+HTML-SHAPE: <div>
+HTML-SHAPE: <p></p>
+HTML-SHAPE: </div>
+HTML-SHAPE: <h3>Returns</h3>
+HTML-SHAPE: <p> double The perimeter of the shape.</p>
+HTML-SHAPE: </div>
HTML-SHAPE: </div>
HTML-SHAPE: </div>
HTML-SHAPE: <div class="delimiter-container">
@@ -90,6 +127,14 @@ HTML-SHAPE: <code class="language-cpp code-clang-doc">
HTML-SHAPE: void ~Shape ()
HTML-SHAPE: </code>
HTML-SHAPE: </pre>
+HTML-SHAPE: <div>
+HTML-SHAPE: <div>
+HTML-SHAPE: <p> Virtual destructor.</p>
+HTML-SHAPE: </div>
+HTML-SHAPE: <div>
+HTML-SHAPE: <p></p>
+HTML-SHAPE: </div>
+HTML-SHAPE: </div>
HTML-SHAPE: </div>
HTML-SHAPE: </div>
HTML-SHAPE: </div>
@@ -106,8 +151,8 @@ HTML-CALC: <html lang="en-US">
HTML-CALC: <head>
HTML-CALC: <meta charset="utf-8"/>
HTML-CALC: <title>Calculator</title>
-HTML-CALC: <link rel="stylesheet" type="text/css" href="../clang-doc-mustache.css"/>
-HTML-CALC: <script src="../mustache-index.js"></script>
+HTML-CALC: <link rel="stylesheet" type="text/css" href="./clang-doc-mustache.css"/>
+HTML-CALC: <script src="./mustache-index.js"></script>
HTML-CALC: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
HTML-CALC: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
HTML-CALC: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/cpp.min.js"></script>
@@ -135,7 +180,7 @@ HTML-CALC: <div class="sidebar">
HTML-CALC: <h2>class Calculator</h2>
HTML-CALC: <ul>
HTML-CALC: <li class="sidebar-section">
-HTML-CALC: <a class="sidebar-item" href="#PublicMethods">Public Members</a>
+HTML-CALC: <a class="sidebar-item" href="#PublicMembers">Public Members</a>
HTML-CALC: </li>
HTML-CALC: <ul>
HTML-CALC: <li class="sidebar-item-container">
@@ -172,6 +217,16 @@ HTML-CALC: <div class="content">
HTML-CALC: <section class="hero section-container">
HTML-CALC: <div class="hero__title">
HTML-CALC: <h1 class="hero__title-large">class Calculator</h1>
+HTML-CALC: <div>
+HTML-CALC: <p> A simple calculator class.</p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p> Provides basic arithmetic operations.</p>
+HTML-CALC: </div>
+HTML-CALC: </div>
HTML-CALC: </div>
HTML-CALC: </section>
HTML-CALC: <section id="PublicMembers" class="section-container">
@@ -199,6 +254,36 @@ HTML-CALC: <code class="language-cpp code-clang-doc">
HTML-CALC: int add (int a, int b)
HTML-CALC: </code>
HTML-CALC: </pre>
+HTML-CALC: <div>
+HTML-CALC: <div>
+HTML-CALC: <p> Adds two integers.</p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: <h3>Parameters</h3>
+HTML-CALC: <div>
+HTML-CALC: <b>a</b> <div>
+HTML-CALC: <p> First integer.</p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <b>b</b> <div>
+HTML-CALC: <p> Second integer.</p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: </div>
+HTML-CALC: <h3>Returns</h3>
+HTML-CALC: <p> int The sum of a and b.</p>
+HTML-CALC: </div>
HTML-CALC: </div>
HTML-CALC: </div>
HTML-CALC: <div class="delimiter-container">
@@ -208,6 +293,19 @@ HTML-CALC: <code class="language-cpp code-clang-doc">
HTML-CALC: int subtract (int a, int b)
HTML-CALC: </code>
HTML-CALC: </pre>
+HTML-CALC: <div>
+HTML-CALC: <div>
+HTML-CALC: <p> Subtracts the second integer from the first.</p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: <h3>Returns</h3>
+HTML-CALC: <p> int The result of a - b.</p>
+HTML-CALC: </div>
HTML-CALC: </div>
HTML-CALC: </div>
HTML-CALC: <div class="delimiter-container">
@@ -217,6 +315,36 @@ HTML-CALC: <code class="language-cpp code-clang-doc">
HTML-CALC: int multiply (int a, int b)
HTML-CALC: </code>
HTML-CALC: </pre>
+HTML-CALC: <div>
+HTML-CALC: <div>
+HTML-CALC: <p> Multiplies two integers.</p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: <h3>Parameters</h3>
+HTML-CALC: <div>
+HTML-CALC: <b>a</b> <div>
+HTML-CALC: <p> First integer.</p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <b>b</b> <div>
+HTML-CALC: <p> Second integer.</p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: </div>
+HTML-CALC: <h3>Returns</h3>
+HTML-CALC: <p> int The product of a and b.</p>
+HTML-CALC: </div>
HTML-CALC: </div>
HTML-CALC: </div>
HTML-CALC: <div class="delimiter-container">
@@ -226,6 +354,37 @@ HTML-CALC: <code class="language-cpp code-clang-doc">
HTML-CALC: double divide (int a, int b)
HTML-CALC: </code>
HTML-CALC: </pre>
+HTML-CALC: <div>
+HTML-CALC: <div>
+HTML-CALC: <p> Divides the first integer by the second.</p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: <h3>Parameters</h3>
+HTML-CALC: <div>
+HTML-CALC: <b>a</b> <div>
+HTML-CALC: <p> First integer.</p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <b>b</b> <div>
+HTML-CALC: <p> Second integer.</p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: </div>
+HTML-CALC: <h3>Returns</h3>
+HTML-CALC: <p> double The result of a / b.</p>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
HTML-CALC: </div>
HTML-CALC: </div>
HTML-CALC: <div class="delimiter-container">
@@ -235,6 +394,36 @@ HTML-CALC: <code class="language-cpp code-clang-doc">
HTML-CALC: int mod (int a, int b)
HTML-CALC: </code>
HTML-CALC: </pre>
+HTML-CALC: <div>
+HTML-CALC: <div>
+HTML-CALC: <p> Performs the mod operation on integers.</p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: <h3>Parameters</h3>
+HTML-CALC: <div>
+HTML-CALC: <b>a</b> <div>
+HTML-CALC: <p> First integer.</p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <b>b</b> <div>
+HTML-CALC: <p> Second integer.</p>
+HTML-CALC: </div>
+HTML-CALC: <div>
+HTML-CALC: <p></p>
+HTML-CALC: </div>
+HTML-CALC: </div>
+HTML-CALC: <h3>Returns</h3>
+HTML-CALC: <p> The result of a % b.</p>
+HTML-CALC: </div>
HTML-CALC: </div>
HTML-CALC: </div>
HTML-CALC: </div>
@@ -251,8 +440,8 @@ HTML-RECTANGLE: <html lang="en-US">
HTML-RECTANGLE: <head>
HTML-RECTANGLE: <meta charset="utf-8"/>
HTML-RECTANGLE: <title>Rectangle</title>
-HTML-RECTANGLE: <link rel="stylesheet" type="text/css" href="../clang-doc-mustache.css"/>
-HTML-RECTANGLE: <script src="../mustache-index.js"></script>
+HTML-RECTANGLE: <link rel="stylesheet" type="text/css" href="./clang-doc-mustache.css"/>
+HTML-RECTANGLE: <script src="./mustache-index.js"></script>
HTML-RECTANGLE: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
HTML-RECTANGLE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
HTML-RECTANGLE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/cpp.min.js"></script>
@@ -279,17 +468,6 @@ HTML-RECTANGLE: <div class="container">
HTML-RECTANGLE: <div class="sidebar">
HTML-RECTANGLE: <h2>class Rectangle</h2>
HTML-RECTANGLE: <ul>
-HTML-RECTANGLE: <li class="sidebar-section">
-HTML-RECTANGLE: <a class="sidebar-item" href="#PublicMethods">Protected Members</a>
-HTML-RECTANGLE: </li>
-HTML-RECTANGLE: <ul>
-HTML-RECTANGLE: <li class="sidebar-item-container">
-HTML-RECTANGLE: <a class="sidebar-item" href="#width_">width_</a>
-HTML-RECTANGLE: </li>
-HTML-RECTANGLE: <li class="sidebar-item-container">
-HTML-RECTANGLE: <a class="sidebar-item" href="#height_">height_</a>
-HTML-RECTANGLE: </li>
-HTML-RECTANGLE: </ul>
HTML-RECTANGLE: <li class="sidebar-section">
HTML-RECTANGLE: <a class="sidebar-item" href="#PublicMethods">Public Method</a>
HTML-RECTANGLE: </li>
@@ -311,21 +489,17 @@ HTML-RECTANGLE: <div class="content">
HTML-RECTANGLE: <section class="hero section-container">
HTML-RECTANGLE: <div class="hero__title">
HTML-RECTANGLE: <h1 class="hero__title-large">class Rectangle</h1>
-HTML-RECTANGLE: </div>
-HTML-RECTANGLE: </section>
-HTML-RECTANGLE: <section id="ProtectedMembers" class="section-container">
-HTML-RECTANGLE: <h2>Protected Members</h2>
-HTML-RECTANGLE: <div>
-HTML-RECTANGLE: <div id="width_" class="delimiter-container">
-HTML-RECTANGLE: <pre>
-HTML-RECTANGLE: <code class="language-cpp code-clang-doc" >double width_</code>
-HTML-RECTANGLE: </pre>
-HTML-RECTANGLE: </div>
-HTML-RECTANGLE: <div id="height_" class="delimiter-container">
-HTML-RECTANGLE: <pre>
-HTML-RECTANGLE: <code class="language-cpp code-clang-doc" >double height_</code>
-HTML-RECTANGLE: </pre>
-HTML-RECTANGLE: </div>
+HTML-RECTANGLE: <div class="hero__subtitle">
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <p> Rectangle class derived from Shape.</p>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <p></p>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <p> Represents a rectangle with a given width and height.</p>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: </div>
HTML-RECTANGLE: </div>
HTML-RECTANGLE: </section>
HTML-RECTANGLE: <section id="PublicMethods" class="section-container">
@@ -338,6 +512,31 @@ HTML-RECTANGLE: <code class="language-cpp code-clang-doc">
HTML-RECTANGLE: void Rectangle (double width, double height)
HTML-RECTANGLE: </code>
HTML-RECTANGLE: </pre>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <p> Constructs a new Rectangle object.</p>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <p></p>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <p></p>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: <h3>Parameters</h3>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <b>width</b> <div>
+HTML-RECTANGLE: <p> Width of the rectangle.</p>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <p></p>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <b>height</b> <div>
+HTML-RECTANGLE: <p> Height of the rectangle.</p>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: </div>
HTML-RECTANGLE: </div>
HTML-RECTANGLE: </div>
HTML-RECTANGLE: <div class="delimiter-container">
@@ -347,6 +546,19 @@ HTML-RECTANGLE: <code class="language-cpp code-clang-doc">
HTML-RECTANGLE: double area ()
HTML-RECTANGLE: </code>
HTML-RECTANGLE: </pre>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <p> Calculates the area of the rectangle.</p>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <p></p>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <p></p>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: <h3>Returns</h3>
+HTML-RECTANGLE: <p> double The area of the rectangle.</p>
+HTML-RECTANGLE: </div>
HTML-RECTANGLE: </div>
HTML-RECTANGLE: </div>
HTML-RECTANGLE: <div class="delimiter-container">
@@ -356,6 +568,19 @@ HTML-RECTANGLE: <code class="language-cpp code-clang-doc">
HTML-RECTANGLE: double perimeter ()
HTML-RECTANGLE: </code>
HTML-RECTANGLE: </pre>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <p> Calculates the perimeter of the rectangle.</p>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <p></p>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: <div>
+HTML-RECTANGLE: <p></p>
+HTML-RECTANGLE: </div>
+HTML-RECTANGLE: <h3>Returns</h3>
+HTML-RECTANGLE: <p> double The perimeter of the rectangle.</p>
+HTML-RECTANGLE: </div>
HTML-RECTANGLE: </div>
HTML-RECTANGLE: </div>
HTML-RECTANGLE: </div>
@@ -372,8 +597,8 @@ HTML-CIRCLE: <html lang="en-US">
HTML-CIRCLE: <head>
HTML-CIRCLE: <meta charset="utf-8"/>
HTML-CIRCLE: <title>Circle</title>
-HTML-CIRCLE: <link rel="stylesheet" type="text/css" href="../clang-doc-mustache.css"/>
-HTML-CIRCLE: <script src="../mustache-index.js"></script>
+HTML-CIRCLE: <link rel="stylesheet" type="text/css" href="./clang-doc-mustache.css"/>
+HTML-CIRCLE: <script src="./mustache-index.js"></script>
HTML-CIRCLE: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
HTML-CIRCLE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
HTML-CIRCLE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/cpp.min.js"></script>
@@ -400,14 +625,6 @@ HTML-CIRCLE: <div class="container">
HTML-CIRCLE: <div class="sidebar">
HTML-CIRCLE: <h2>class Circle</h2>
HTML-CIRCLE: <ul>
-HTML-CIRCLE: <li class="sidebar-section">
-HTML-CIRCLE: <a class="sidebar-item" href="#PublicMethods">Protected Members</a>
-HTML-CIRCLE: </li>
-HTML-CIRCLE: <ul>
-HTML-CIRCLE: <li class="sidebar-item-container">
-HTML-CIRCLE: <a class="sidebar-item" href="#radius_">radius_</a>
-HTML-CIRCLE: </li>
-HTML-CIRCLE: </ul>
HTML-CIRCLE: <li class="sidebar-section">
HTML-CIRCLE: <a class="sidebar-item" href="#PublicMethods">Public Method</a>
HTML-CIRCLE: </li>
@@ -429,16 +646,17 @@ HTML-CIRCLE: <div class="content">
HTML-CIRCLE: <section class="hero section-container">
HTML-CIRCLE: <div class="hero__title">
HTML-CIRCLE: <h1 class="hero__title-large">class Circle</h1>
-HTML-CIRCLE: </div>
-HTML-CIRCLE: </section>
-HTML-CIRCLE: <section id="ProtectedMembers" class="section-container">
-HTML-CIRCLE: <h2>Protected Members</h2>
-HTML-CIRCLE: <div>
-HTML-CIRCLE: <div id="radius_" class="delimiter-container">
-HTML-CIRCLE: <pre>
-HTML-CIRCLE: <code class="language-cpp code-clang-doc" >double radius_</code>
-HTML-CIRCLE: </pre>
-HTML-CIRCLE: </div>
+HTML-CIRCLE: <div class="hero__subtitle">
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <p> Circle class derived from Shape.</p>
+HTML-CIRCLE: </div>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <p></p>
+HTML-CIRCLE: </div>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <p> Represents a circle with a given radius.</p>
+HTML-CIRCLE: </div>
+HTML-CIRCLE: </div>
HTML-CIRCLE: </div>
HTML-CIRCLE: </section>
HTML-CIRCLE: <section id="PublicMethods" class="section-container">
@@ -451,6 +669,23 @@ HTML-CIRCLE: <code class="language-cpp code-clang-doc">
HTML-CIRCLE: void Circle (double radius)
HTML-CIRCLE: </code>
HTML-CIRCLE: </pre>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <p> Constructs a new Circle object.</p>
+HTML-CIRCLE: </div>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <p></p>
+HTML-CIRCLE: </div>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <p></p>
+HTML-CIRCLE: </div>
+HTML-CIRCLE: <h3>Parameters</h3>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <b>radius</b> <div>
+HTML-CIRCLE: <p> Radius of the circle.</p>
+HTML-CIRCLE: </div>
+HTML-CIRCLE: </div>
+HTML-CIRCLE: </div>
HTML-CIRCLE: </div>
HTML-CIRCLE: </div>
HTML-CIRCLE: <div class="delimiter-container">
@@ -460,6 +695,19 @@ HTML-CIRCLE: <code class="language-cpp code-clang-doc">
HTML-CIRCLE: double area ()
HTML-CIRCLE: </code>
HTML-CIRCLE: </pre>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <p> Calculates the area of the circle.</p>
+HTML-CIRCLE: </div>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <p></p>
+HTML-CIRCLE: </div>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <p></p>
+HTML-CIRCLE: </div>
+HTML-CIRCLE: <h3>Returns</h3>
+HTML-CIRCLE: <p> double The area of the circle.</p>
+HTML-CIRCLE: </div>
HTML-CIRCLE: </div>
HTML-CIRCLE: </div>
HTML-CIRCLE: <div class="delimiter-container">
@@ -469,6 +717,28 @@ HTML-CIRCLE: <code class="language-cpp code-clang-doc">
HTML-CIRCLE: double perimeter ()
HTML-CIRCLE: </code>
HTML-CIRCLE: </pre>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <p> Calculates the perimeter of the circle.</p>
+HTML-CIRCLE: </div>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <p></p>
+HTML-CIRCLE: </div>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <p></p>
+HTML-CIRCLE: </div>
+HTML-CIRCLE: <h3>Returns</h3>
+HTML-CIRCLE: <p> double The perimeter of the circle.</p>
+HTML-CIRCLE: <h3>Code</h3>
+HTML-CIRCLE: <div>
+HTML-CIRCLE: <pre class="code-block">
+HTML-CIRCLE: <code>
+HTML-CIRCLE: Circle circle(5.0);
+HTML-CIRCLE: double perimeter = circle.perimeter();
+HTML-CIRCLE: </code>
+HTML-CIRCLE: </pre>
+HTML-CIRCLE: </div>
+HTML-CIRCLE: </div>
HTML-CIRCLE: </div>
HTML-CIRCLE: </div>
HTML-CIRCLE: </div>
diff --git a/clang-tools-extra/test/clang-doc/json/class-requires.cpp b/clang-tools-extra/test/clang-doc/json/class-requires.cpp
index 213da93..bf6c889 100644
--- a/clang-tools-extra/test/clang-doc/json/class-requires.cpp
+++ b/clang-tools-extra/test/clang-doc/json/class-requires.cpp
@@ -20,6 +20,7 @@ struct MyClass;
// CHECK-NEXT: "Template": {
// CHECK-NEXT: "Constraints": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Expression": "Addable<T>",
// CHECK-NEXT: "Name": "Addable",
// CHECK-NEXT: "Path": "",
diff --git a/clang-tools-extra/test/clang-doc/json/class-template.cpp b/clang-tools-extra/test/clang-doc/json/class-template.cpp
index 6cdc3e9..149248c 100644
--- a/clang-tools-extra/test/clang-doc/json/class-template.cpp
+++ b/clang-tools-extra/test/clang-doc/json/class-template.cpp
@@ -11,6 +11,7 @@ template<typename T> struct MyClass {
// CHECK: "Name": "method",
// CHECK: "Params": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "Param",
// CHECK-NEXT: "Type": "T"
// CHECK-NEXT: }
diff --git a/clang-tools-extra/test/clang-doc/json/class.cpp b/clang-tools-extra/test/clang-doc/json/class.cpp
index d8317ea..79b8fed 100644
--- a/clang-tools-extra/test/clang-doc/json/class.cpp
+++ b/clang-tools-extra/test/clang-doc/json/class.cpp
@@ -33,35 +33,29 @@ protected:
};
// CHECK: {
-// CHECK-NEXT: "Description": [
-// CHECK-NEXT: {
-// CHECK-NEXT: "FullComment": {
-// CHECK-NEXT: "Children": [
-// CHECK-NEXT: {
-// CHECK-NEXT: "ParagraphComment": {
-// CHECK-NEXT: "Children": [
-// CHECK-NEXT: {
-// CHECK-NEXT: "TextComment": " This is a nice class."
-// CHECK-NEXT: },
-// CHECK-NEXT: {
-// CHECK-NEXT: "TextComment": " It has some nice methods and fields."
-// CHECK-NEXT: },
-// CHECK-NEXT: {
-// CHECK-NEXT: "TextComment": ""
-// CHECK-NEXT: }
-// CHECK-NEXT: ]
-// CHECK: {
-// CHECK-NEXT: "BlockCommandComment": {
-// CHECK-NEXT: "Children": [
-// CHECK-NEXT: {
-// CHECK-NEXT: "ParagraphComment": {
-// CHECK-NEXT: "Children": [
-// CHECK-NEXT: {
-// CHECK-NEXT: "TextComment": " This is a brief description."
-// CHECK-NEXT: }
-// CHECK: "Command": "brief"
+// CHECK-NEXT: "Description": {
+// CHECK-NEXT: "BriefComments": [
+// CHECK-NEXT: [
+// CHECK-NEXT: {
+// CHECK-NEXT: "TextComment": " This is a brief description."
+// CHECK: "HasBriefComments": true,
+// CHECK-NEXT: "HasParagraphComments": true,
+// CHECK-NEXT: "ParagraphComments": [
+// CHECK-NEXT: [
+// CHECK-NEXT: {
+// CHECK-NEXT: "TextComment": " This is a nice class."
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "TextComment": " It has some nice methods and fields."
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "TextComment": ""
+// CHECK-NEXT: }
+// CHECK: "DocumentationFileName": "_ZTV7MyClass",
// CHECK: "Enums": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
+// CHECK-NEXT: "InfoType": "enum",
// CHECK-NEXT: "Location": {
// CHECK-NEXT: "Filename": "{{.*}}class.cpp",
// CHECK-NEXT: "LineNumber": 17
@@ -76,6 +70,7 @@ protected:
// CHECK-NEXT: "Value": "1"
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "BLUE",
// CHECK-NEXT: "ValueExpr": "5"
// CHECK-NEXT: }
@@ -94,6 +89,7 @@ protected:
// CHECK-NEXT: "IsClass": false,
// CHECK-NEXT: "Params": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "",
// CHECK-NEXT: "Type": "int"
// CHECK-NEXT: }
@@ -118,6 +114,7 @@ protected:
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "IsClass": true,
// CHECK-NEXT: "Reference": {
// CHECK-NEXT: "Name": "Foo",
@@ -129,6 +126,11 @@ protected:
// CHECK-NEXT: ],
// COM: FIXME: FullName is not emitted correctly.
// CHECK-NEXT: "FullName": "",
+// CHECK-NEXT: "HasEnums": true,
+// CHECK-NEXT: "HasPublicFunctions": true,
+// CHECK-NEXT: "HasPublicMembers": true,
+// CHECK-NEXT: "HasRecords": true,
+// CHECK-NEXT: "InfoType": "record",
// CHECK-NEXT: "IsTypedef": false,
// CHECK-NEXT: "Location": {
// CHECK-NEXT: "Filename": "{{.*}}class.cpp",
@@ -142,6 +144,7 @@ protected:
// CHECK-NEXT: "Path": "GlobalNamespace",
// CHECK-NEXT: "ProtectedFunctions": [
// CHECK-NEXT: {
+// CHECK-NEXT: "InfoType": "function",
// CHECK-NEXT: "IsStatic": false,
// CHECK-NEXT: "Name": "protectedMethod",
// CHECK-NEXT: "Namespace": [
@@ -166,6 +169,7 @@ protected:
// CHECK-NEXT: ],
// CHECK-NEXT: "PublicFunctions": [
// CHECK-NEXT: {
+// CHECK-NEXT: "InfoType": "function",
// CHECK-NEXT: "IsStatic": false,
// CHECK-NEXT: "Name": "myMethod",
// CHECK-NEXT: "Namespace": [
@@ -174,6 +178,7 @@ protected:
// CHECK-NEXT: ],
// CHECK-NEXT: "Params": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "MyParam",
// CHECK-NEXT: "Type": "int"
// CHECK-NEXT: }
@@ -204,6 +209,8 @@ protected:
// CHECK-NEXT: ],
// CHECK-NEXT: "Records": [
// CHECK-NEXT: {
+// CHECK-NEXT: "DocumentationFileName": "_ZTVN7MyClass11NestedClassE",
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "NestedClass",
// CHECK-NEXT: "Path": "GlobalNamespace{{[\/]+}}MyClass",
// CHECK-NEXT: "QualName": "NestedClass",
@@ -213,6 +220,8 @@ protected:
// CHECK-NEXT: "TagType": "struct",
// CHECK-NEXT: "Typedefs": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
+// CHECK-NEXT: "InfoType": "typedef",
// CHECK-NEXT: "IsUsing": false,
// CHECK-NEXT: "Location": {
// CHECK-NEXT: "Filename": "{{.*}}class.cpp",
diff --git a/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp b/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp
index 34acb68..bb2b4ca 100644
--- a/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp
+++ b/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp
@@ -37,6 +37,7 @@ template<typename T> requires (Incrementable<T> && Decrementable<T>) || PreIncre
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}"
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Expression": "Decrementable<T>",
// CHECK-NEXT: "Name": "Decrementable",
// CHECK-NEXT: "Path": "",
@@ -55,6 +56,7 @@ template<typename T> requires (Incrementable<T> && Decrementable<T>) || PreIncre
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}"
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Expression": "Decrementable<T>",
// CHECK-NEXT: "Name": "Decrementable",
// CHECK-NEXT: "Path": "",
@@ -87,6 +89,7 @@ template<typename T> requires (Incrementable<T> && Decrementable<T>) || PreIncre
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}"
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Expression": "PreDecrementable<T>",
// CHECK-NEXT: "Name": "PreDecrementable",
// CHECK-NEXT: "Path": "",
@@ -112,6 +115,7 @@ template<typename T> requires (Incrementable<T> && Decrementable<T>) || PreIncre
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}"
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Expression": "PreIncrementable<T>",
// CHECK-NEXT: "Name": "PreIncrementable",
// CHECK-NEXT: "Path": "",
diff --git a/clang-tools-extra/test/clang-doc/json/concept.cpp b/clang-tools-extra/test/clang-doc/json/concept.cpp
index b946393..4c81024 100644
--- a/clang-tools-extra/test/clang-doc/json/concept.cpp
+++ b/clang-tools-extra/test/clang-doc/json/concept.cpp
@@ -13,16 +13,14 @@ concept Incrementable = requires(T x) {
// CHECK-NEXT: "Concepts": [
// CHECK-NEXT: {
// CHECK-NEXT: "ConstraintExpression": "requires (T x) { ++x; x++; }",
-// CHECK-NEXT: "Description": [
-// CHECK-NEXT: {
-// CHECK-NEXT: "FullComment": {
-// CHECK-NEXT: "Children": [
-// CHECK-NEXT: {
-// CHECK-NEXT: "ParagraphComment": {
-// CHECK-NEXT: "Children": [
-// CHECK-NEXT: {
-// CHECK-NEXT: "TextComment": " Requires that T suports post and pre-incrementing."
-// CHECK: ],
+// CHECK-NEXT: "Description": {
+// CHECK-NEXT: "HasParagraphComments": true,
+// CHECK-NEXT: "ParagraphComments": [
+// CHECK-NEXT: [
+// CHECK-NEXT: {
+// CHECK-NEXT: "TextComment": " Requires that T suports post and pre-incrementing."
+// CHECK: "End": true,
+// CHECK-NEXT: "InfoType": "concept",
// CHECK-NEXT: "IsType": true,
// CHECK-NEXT: "Name": "Incrementable",
// CHECK-NEXT: "Template": {
diff --git a/clang-tools-extra/test/clang-doc/json/function-requires.cpp b/clang-tools-extra/test/clang-doc/json/function-requires.cpp
index 08ac4c7..59ed39e 100644
--- a/clang-tools-extra/test/clang-doc/json/function-requires.cpp
+++ b/clang-tools-extra/test/clang-doc/json/function-requires.cpp
@@ -14,10 +14,12 @@ template<Incrementable T> Incrementable auto incrementTwo(T t);
// CHECK: "Functions": [
// CHECK-NEXT: {
+// CHECK-NEXT: "InfoType": "function",
// CHECK-NEXT: "IsStatic": false,
// CHECK-NEXT: "Name": "increment",
// CHECK-NEXT: "Params": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "t",
// CHECK-NEXT: "Type": "T"
// CHECK-NEXT: }
@@ -32,6 +34,7 @@ template<Incrementable T> Incrementable auto incrementTwo(T t);
// CHECK-NEXT: "Template": {
// CHECK-NEXT: "Constraints": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Expression": "Incrementable<T>",
// CHECK-NEXT: "Name": "Incrementable",
// CHECK-NEXT: "Path": "",
@@ -46,10 +49,13 @@ template<Incrementable T> Incrementable auto incrementTwo(T t);
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}"
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
+// CHECK-NEXT: "InfoType": "function",
// CHECK-NEXT: "IsStatic": false,
// CHECK-NEXT: "Name": "incrementTwo",
// CHECK-NEXT: "Params": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "t",
// CHECK-NEXT: "Type": "T"
// CHECK-NEXT: }
@@ -64,6 +70,7 @@ template<Incrementable T> Incrementable auto incrementTwo(T t);
// CHECK-NEXT: "Template": {
// CHECK-NEXT: "Constraints": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Expression": "Incrementable<T>",
// CHECK-NEXT: "Name": "Incrementable",
// CHECK-NEXT: "Path": "",
diff --git a/clang-tools-extra/test/clang-doc/json/method-template.cpp b/clang-tools-extra/test/clang-doc/json/method-template.cpp
index ac8450a..14232d0 100644
--- a/clang-tools-extra/test/clang-doc/json/method-template.cpp
+++ b/clang-tools-extra/test/clang-doc/json/method-template.cpp
@@ -9,6 +9,7 @@ struct MyClass {
// CHECK: "PublicFunctions": [
// CHECK-NEXT: {
+// CHECK-NEXT: "InfoType": "function",
// CHECK-NEXT: "IsStatic": false,
// CHECK-NEXT: "Location": {
// CHECK-NEXT: "Filename": "{{.*}}method-template.cpp",
@@ -21,6 +22,7 @@ struct MyClass {
// CHECK-NEXT: ],
// CHECK-NEXT: "Params": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "param",
// CHECK-NEXT: "Type": "T"
// CHECK-NEXT: }
diff --git a/clang-tools-extra/test/clang-doc/json/namespace.cpp b/clang-tools-extra/test/clang-doc/json/namespace.cpp
index 779d7b49..4b6b388 100644
--- a/clang-tools-extra/test/clang-doc/json/namespace.cpp
+++ b/clang-tools-extra/test/clang-doc/json/namespace.cpp
@@ -20,8 +20,11 @@ enum Color {
typedef int MyTypedef;
// CHECK: {
+// CHECK-NEXT: "DocumentationFileName": "index",
// CHECK-NEXT: "Enums": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
+// CHECK-NEXT: "InfoType": "enum",
// CHECK-NEXT: "Location": {
// CHECK-NEXT: "Filename": "{{.*}}namespace.cpp",
// CHECK-NEXT: "LineNumber": 14
@@ -36,6 +39,7 @@ typedef int MyTypedef;
// CHECK-NEXT: "Value": "1"
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "BLUE",
// CHECK-NEXT: "ValueExpr": "5"
// CHECK-NEXT: }
@@ -47,10 +51,13 @@ typedef int MyTypedef;
// CHECK-NEXT: ],
// CHECK-NEXT: "Functions": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
+// CHECK-NEXT: "InfoType": "function",
// CHECK-NEXT: "IsStatic": false,
// CHECK-NEXT: "Name": "myFunction",
// CHECK-NEXT: "Params": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "Param",
// CHECK-NEXT: "Type": "int"
// CHECK-NEXT: }
@@ -65,9 +72,13 @@ typedef int MyTypedef;
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "HasEnums": true,
+// CHECK-NEXT: "HasRecords": true,
+// CHECK-NEXT: "InfoType": "namespace",
// CHECK-NEXT: "Name": "",
// CHECK-NEXT: "Namespaces": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "NestedNamespace",
// CHECK-NEXT: "Path": "",
// CHECK-NEXT: "QualName": "NestedNamespace",
@@ -76,6 +87,8 @@ typedef int MyTypedef;
// CHECK-NEXT: ],
// CHECK-NEXT: "Records": [
// CHECK-NEXT: {
+// CHECK-NEXT: "DocumentationFileName": "_ZTV7MyClass",
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "MyClass",
// CHECK-NEXT: "Path": "GlobalNamespace",
// CHECK-NEXT: "QualName": "MyClass",
@@ -84,6 +97,8 @@ typedef int MyTypedef;
// CHECK-NEXT: ],
// CHECK-NEXT: "Typedefs": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
+// CHECK-NEXT: "InfoType": "typedef",
// CHECK-NEXT: "IsUsing": false,
// CHECK-NEXT: "Location": {
// CHECK-NEXT: "Filename": "{{.*}}namespace.cpp",
@@ -104,6 +119,8 @@ typedef int MyTypedef;
// CHECK-NEXT: "USR": "0000000000000000000000000000000000000000"
// CHECK-NEXT: "Variables": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
+// CHECK-NEXT: "InfoType": "variable",
// CHECK-NEXT: "IsStatic": true,
// CHECK-NEXT: "Location": {
// CHECK-NEXT: "Filename": "{{.*}}namespace.cpp",
diff --git a/clang-tools-extra/test/clang-doc/json/nested-namespace.cpp b/clang-tools-extra/test/clang-doc/json/nested-namespace.cpp
index 54f95c4..255e540 100644
--- a/clang-tools-extra/test/clang-doc/json/nested-namespace.cpp
+++ b/clang-tools-extra/test/clang-doc/json/nested-namespace.cpp
@@ -12,6 +12,8 @@ namespace nested {
// NESTED: "Variables": [
// NESTED-NEXT: {
+// NESTED-NEXT: "End": true,
+// NESTED-NEXT: "InfoType": "variable",
// NESTED-NEXT: "IsStatic": false,
// NESTED-NEXT: "Location": {
// NESTED-NEXT: "Filename": "{{.*}}nested-namespace.cpp",
@@ -24,6 +26,8 @@ namespace nested {
// INNER: "Variables": [
// INNER-NEXT: {
+// INNER-NEXT: "End": true,
+// INNER-NEXT: "InfoType": "variable",
// INNER-NEXT: "IsStatic": false,
// INNER-NEXT: "Location": {
// INNER-NEXT: "Filename": "{{.*}}nested-namespace.cpp",
diff --git a/clang-tools-extra/test/clang-doc/mustache-index.cpp b/clang-tools-extra/test/clang-doc/mustache-index.cpp
index cad4cc8..910233b 100644
--- a/clang-tools-extra/test/clang-doc/mustache-index.cpp
+++ b/clang-tools-extra/test/clang-doc/mustache-index.cpp
@@ -1,6 +1,6 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --format=mustache --output=%t --executor=standalone %s
-// RUN: FileCheck %s < %t/GlobalNamespace/index.html
+// RUN: FileCheck %s < %t/index.html
enum Color {
RED,
@@ -15,7 +15,7 @@ class Foo;
// CHECK-NEXT: </li>
// CHECK-NEXT: <ul>
// CHECK-NEXT: <li class="sidebar-item-container">
-// CHECK-NEXT: <a class="sidebar-item" href="#{{[0-9A-F]*}}">enum Color</a>
+// CHECK-NEXT: <a class="sidebar-item" href="#{{[0-9A-F]*}}">Color</a>
// CHECK-NEXT: </li>
// CHECK-NEXT: </ul>
// CHECK: <li class="sidebar-section">
@@ -69,7 +69,11 @@ class Foo;
// CHECK-NEXT: <h2>Inner Classes</h2>
// CHECK-NEXT: <ul class="class-container">
// CHECK-NEXT: <li id="{{[0-9A-F]*}}" style="max-height: 40px;">
-// CHECK-NEXT: <a href="Foo.html"><pre><code class="language-cpp code-clang-doc" >class Foo</code></pre></a>
+// CHECK-NEXT: <a href="_ZTV3Foo.html">
+// CHECK-NEXT: <pre>
+// CHECK-NEXT: <code class="language-cpp code-clang-doc">class Foo</code>
+// CHECK-NEXT: </pre>
+// CHECK-NEXT: </a>
// CHECK-NEXT: </li>
// CHECK-NEXT: </ul>
// CHECK-NEXT: </section>
diff --git a/clang-tools-extra/test/clang-doc/mustache-separate-namespace.cpp b/clang-tools-extra/test/clang-doc/mustache-separate-namespace.cpp
index ec29b24..7d7d108 100644
--- a/clang-tools-extra/test/clang-doc/mustache-separate-namespace.cpp
+++ b/clang-tools-extra/test/clang-doc/mustache-separate-namespace.cpp
@@ -1,6 +1,6 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --format=mustache --output=%t --executor=standalone %s
-// RUN: FileCheck %s < %t/MyNamespace/index.html
+// RUN: FileCheck %s < %t/MyNamespace.html
namespace MyNamespace {
class Foo;
@@ -8,6 +8,10 @@ namespace MyNamespace {
// CHECK: <ul class="class-container">
// CHECK-NEXT: <li id="{{[0-9A-F]*}}" style="max-height: 40px;">
-// CHECK-NEXT: <a href="Foo.html"><pre><code class="language-cpp code-clang-doc" >class Foo</code></pre></a>
+// CHECK-NEXT: <a href="_ZTVN11MyNamespace3FooE.html">
+// CHECK-NEXT: <pre>
+// CHECK-NEXT: <code class="language-cpp code-clang-doc">class Foo</code>
+// CHECK-NEXT: </pre>
+// CHECK-NEXT: </a>
// CHECK-NEXT: </li>
// CHECK-NEXT: </ul>
diff --git a/clang-tools-extra/test/clang-include-fixer/include_path.cpp b/clang-tools-extra/test/clang-include-fixer/include_path.cpp
index 9185b7a..a6f4a45 100644
--- a/clang-tools-extra/test/clang-include-fixer/include_path.cpp
+++ b/clang-tools-extra/test/clang-include-fixer/include_path.cpp
@@ -1,18 +1,18 @@
-// RUN: mkdir -p %T/clang-include-fixer/include
-// RUN: mkdir -p %T/clang-include-fixer/symbols
-// RUN: mkdir -p %T/clang-include-fixer/build
-// RUN: mkdir -p %T/clang-include-fixer/src
-// RUN: sed 's|test_dir|%/T/clang-include-fixer|g' %S/Inputs/database_template.json > %T/clang-include-fixer/build/compile_commands.json
-// RUN: echo -e '#include "bar.h"\nb::a::bar f;' > %T/clang-include-fixer/src/bar.cpp
-// RUN: echo 'namespace b { namespace a { class bar {}; } }' > %T/clang-include-fixer/include/bar.h
-// RUN: cd %T/clang-include-fixer/build
-// RUN: find-all-symbols -output-dir=%T/clang-include-fixer/symbols -p=. %T/clang-include-fixer/src/bar.cpp
-// RUN: find-all-symbols -merge-dir=%T/clang-include-fixer/symbols %T/clang-include-fixer/build/find_all_symbols.yaml
-// RUN: FileCheck -input-file=%T/clang-include-fixer/build/find_all_symbols.yaml -check-prefix=CHECK-YAML %s
+// RUN: mkdir -p %t.dir/clang-include-fixer/include
+// RUN: mkdir -p %t.dir/clang-include-fixer/symbols
+// RUN: mkdir -p %t.dir/clang-include-fixer/build
+// RUN: mkdir -p %t.dir/clang-include-fixer/src
+// RUN: sed 's|test_dir|%/t.dir/clang-include-fixer|g' %S/Inputs/database_template.json > %t.dir/clang-include-fixer/build/compile_commands.json
+// RUN: echo -e '#include "bar.h"\nb::a::bar f;' > %t.dir/clang-include-fixer/src/bar.cpp
+// RUN: echo 'namespace b { namespace a { class bar {}; } }' > %t.dir/clang-include-fixer/include/bar.h
+// RUN: cd %t.dir/clang-include-fixer/build
+// RUN: find-all-symbols -output-dir=%t.dir/clang-include-fixer/symbols -p=. %t.dir/clang-include-fixer/src/bar.cpp
+// RUN: find-all-symbols -merge-dir=%t.dir/clang-include-fixer/symbols %t.dir/clang-include-fixer/build/find_all_symbols.yaml
+// RUN: FileCheck -input-file=%t.dir/clang-include-fixer/build/find_all_symbols.yaml -check-prefix=CHECK-YAML %s
//
-// RUN: echo 'b::a::bar f;' > %T/clang-include-fixer/src/bar.cpp
-// RUN: clang-include-fixer -db=yaml -input=%T/clang-include-fixer/build/find_all_symbols.yaml -minimize-paths=true -p=. %T/clang-include-fixer/src/bar.cpp
-// RUN: FileCheck -input-file=%T/clang-include-fixer/src/bar.cpp %s
+// RUN: echo 'b::a::bar f;' > %t.dir/clang-include-fixer/src/bar.cpp
+// RUN: clang-include-fixer -db=yaml -input=%t.dir/clang-include-fixer/build/find_all_symbols.yaml -minimize-paths=true -p=. %t.dir/clang-include-fixer/src/bar.cpp
+// RUN: FileCheck -input-file=%t.dir/clang-include-fixer/src/bar.cpp %s
// CHECK-YAML: ..{{[/\\]}}include{{[/\\]}}bar.h
// CHECK: #include "bar.h"
diff --git a/clang-tools-extra/test/clang-include-fixer/multiple_fixes.cpp b/clang-tools-extra/test/clang-include-fixer/multiple_fixes.cpp
index 791417a..6c82e2a 100644
--- a/clang-tools-extra/test/clang-include-fixer/multiple_fixes.cpp
+++ b/clang-tools-extra/test/clang-include-fixer/multiple_fixes.cpp
@@ -1,11 +1,11 @@
// REQUIRES: shell
// RUN: sed -e 's#//.*$##' %s > %t.cpp
-// RUN: mkdir -p %T/clang-include-fixer/multiple-fixes
-// RUN: echo 'foo f;' > %T/clang-include-fixer/multiple-fixes/foo.cpp
-// RUN: echo 'bar b;' > %T/clang-include-fixer/multiple-fixes/bar.cpp
-// RUN: clang-include-fixer -db=fixed -input='foo= "foo.h";bar= "bar.h"' %T/clang-include-fixer/multiple-fixes/*.cpp --
-// RUN: FileCheck -input-file=%T/clang-include-fixer/multiple-fixes/bar.cpp %s -check-prefix=CHECK-BAR
-// RUN: FileCheck -input-file=%T/clang-include-fixer/multiple-fixes/foo.cpp %s -check-prefix=CHECK-FOO
+// RUN: mkdir -p %t.dir/clang-include-fixer/multiple-fixes
+// RUN: echo 'foo f;' > %t.dir/clang-include-fixer/multiple-fixes/foo.cpp
+// RUN: echo 'bar b;' > %t.dir/clang-include-fixer/multiple-fixes/bar.cpp
+// RUN: clang-include-fixer -db=fixed -input='foo= "foo.h";bar= "bar.h"' %t.dir/clang-include-fixer/multiple-fixes/*.cpp --
+// RUN: FileCheck -input-file=%t.dir/clang-include-fixer/multiple-fixes/bar.cpp %s -check-prefix=CHECK-BAR
+// RUN: FileCheck -input-file=%t.dir/clang-include-fixer/multiple-fixes/foo.cpp %s -check-prefix=CHECK-FOO
//
// CHECK-FOO: #include "foo.h"
// CHECK-FOO: foo f;
diff --git a/clang-tools-extra/test/clang-include-fixer/yamldb_autodetect.cpp b/clang-tools-extra/test/clang-include-fixer/yamldb_autodetect.cpp
index 1997390..1978e5d 100644
--- a/clang-tools-extra/test/clang-include-fixer/yamldb_autodetect.cpp
+++ b/clang-tools-extra/test/clang-include-fixer/yamldb_autodetect.cpp
@@ -1,6 +1,6 @@
-// RUN: mkdir -p %T/foo/bar
-// RUN: cp %p/Inputs/fake_yaml_db.yaml %T/find_all_symbols_db.yaml
-// RUN: cd %T/foo
+// RUN: mkdir -p %t.dir/foo/bar
+// RUN: cp %p/Inputs/fake_yaml_db.yaml %t.dir/find_all_symbols_db.yaml
+// RUN: cd %t.dir/foo
// RUN: sed -e 's#//.*$##' %s > bar/test.cpp
// RUN: clang-include-fixer -db=yaml bar/test.cpp --
// RUN: FileCheck %s -input-file=bar/test.cpp
diff --git a/clang-tools-extra/test/clang-move/move-class.cpp b/clang-tools-extra/test/clang-move/move-class.cpp
index a30cb4d..5fb0258 100644
--- a/clang-tools-extra/test/clang-move/move-class.cpp
+++ b/clang-tools-extra/test/clang-move/move-class.cpp
@@ -1,25 +1,25 @@
-// RUN: mkdir -p %T/clang-move/build
-// RUN: mkdir -p %T/clang-move/include
-// RUN: mkdir -p %T/clang-move/src
-// RUN: sed 's|$test_dir|%/T/clang-move|g' %S/Inputs/database_template.json > %T/clang-move/compile_commands.json
-// RUN: cp %S/Inputs/test.h %T/clang-move/include
-// RUN: cp %S/Inputs/test.cpp %T/clang-move/src
-// RUN: touch %T/clang-move/include/test2.h
-// RUN: cd %T/clang-move/build
-// RUN: clang-move -names="a::Foo" -new_cc=%T/clang-move/new_test.cpp -new_header=%T/clang-move/new_test.h -old_cc=../src/test.cpp -old_header=../include/test.h %T/clang-move/src/test.cpp
-// RUN: FileCheck -input-file=%T/clang-move/new_test.cpp -check-prefix=CHECK-NEW-TEST-CPP %s
-// RUN: FileCheck -input-file=%T/clang-move/new_test.h -check-prefix=CHECK-NEW-TEST-H %s
-// RUN: FileCheck -input-file=%T/clang-move/src/test.cpp -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
-// RUN: FileCheck -input-file=%T/clang-move/include/test.h -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
+// RUN: mkdir -p %t.dir/clang-move/build
+// RUN: mkdir -p %t.dir/clang-move/include
+// RUN: mkdir -p %t.dir/clang-move/src
+// RUN: sed 's|$test_dir|%/t.dir/clang-move|g' %S/Inputs/database_template.json > %t.dir/clang-move/compile_commands.json
+// RUN: cp %S/Inputs/test.h %t.dir/clang-move/include
+// RUN: cp %S/Inputs/test.cpp %t.dir/clang-move/src
+// RUN: touch %t.dir/clang-move/include/test2.h
+// RUN: cd %t.dir/clang-move/build
+// RUN: clang-move -names="a::Foo" -new_cc=%t.dir/clang-move/new_test.cpp -new_header=%t.dir/clang-move/new_test.h -old_cc=../src/test.cpp -old_header=../include/test.h %t.dir/clang-move/src/test.cpp
+// RUN: FileCheck -input-file=%t.dir/clang-move/new_test.cpp -check-prefix=CHECK-NEW-TEST-CPP %s
+// RUN: FileCheck -input-file=%t.dir/clang-move/new_test.h -check-prefix=CHECK-NEW-TEST-H %s
+// RUN: FileCheck -input-file=%t.dir/clang-move/src/test.cpp -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
+// RUN: FileCheck -input-file=%t.dir/clang-move/include/test.h -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
//
-// RUN: cp %S/Inputs/test.h %T/clang-move/include
-// RUN: cp %S/Inputs/test.cpp %T/clang-move/src
-// RUN: cd %T/clang-move/build
-// RUN: clang-move -names="a::Foo" -new_cc=%T/clang-move/new_test.cpp -new_header=%T/clang-move/new_test.h -old_cc=%T/clang-move/src/test.cpp -old_header=%T/clang-move/include/test.h %T/clang-move/src/test.cpp
-// RUN: FileCheck -input-file=%T/clang-move/new_test.cpp -check-prefix=CHECK-NEW-TEST-CPP %s
-// RUN: FileCheck -input-file=%T/clang-move/new_test.h -check-prefix=CHECK-NEW-TEST-H %s
-// RUN: FileCheck -input-file=%T/clang-move/src/test.cpp -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
-// RUN: FileCheck -input-file=%T/clang-move/include/test.h -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
+// RUN: cp %S/Inputs/test.h %t.dir/clang-move/include
+// RUN: cp %S/Inputs/test.cpp %t.dir/clang-move/src
+// RUN: cd %t.dir/clang-move/build
+// RUN: clang-move -names="a::Foo" -new_cc=%t.dir/clang-move/new_test.cpp -new_header=%t.dir/clang-move/new_test.h -old_cc=%t.dir/clang-move/src/test.cpp -old_header=%t.dir/clang-move/include/test.h %t.dir/clang-move/src/test.cpp
+// RUN: FileCheck -input-file=%t.dir/clang-move/new_test.cpp -check-prefix=CHECK-NEW-TEST-CPP %s
+// RUN: FileCheck -input-file=%t.dir/clang-move/new_test.h -check-prefix=CHECK-NEW-TEST-H %s
+// RUN: FileCheck -input-file=%t.dir/clang-move/src/test.cpp -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
+// RUN: FileCheck -input-file=%t.dir/clang-move/include/test.h -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
//
//
// CHECK-NEW-TEST-H: #ifndef TEST_H // comment 1
diff --git a/clang-tools-extra/test/clang-move/move-enum-decl.cpp b/clang-tools-extra/test/clang-move/move-enum-decl.cpp
index 42f6f99..f8fb5f6 100644
--- a/clang-tools-extra/test/clang-move/move-enum-decl.cpp
+++ b/clang-tools-extra/test/clang-move/move-enum-decl.cpp
@@ -1,14 +1,14 @@
-// RUN: mkdir -p %T/move-enum
-// RUN: cp %S/Inputs/enum.h %T/move-enum/enum.h
-// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
-// RUN: cd %T/move-enum
+// RUN: mkdir -p %t.dir/move-enum
+// RUN: cp %S/Inputs/enum.h %t.dir/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %t.dir/move-enum/enum.cpp
+// RUN: cd %t.dir/move-enum
//
// -----------------------------------------------------------------------------
// Test moving enum declarations.
// -----------------------------------------------------------------------------
-// RUN: clang-move -names="a::E1" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
-// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE1 %s
+// RUN: clang-move -names="a::E1" -new_cc=%t.dir/move-enum/new_test.cpp -new_header=%t.dir/move-enum/new_test.h -old_cc=%t.dir/move-enum/enum.cpp -old_header=%t.dir/move-enum/enum.h %t.dir/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
+// RUN: FileCheck -input-file=%t.dir/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE1 %s
//
// CHECK-NEW-TEST-H-CASE1: namespace a {
// CHECK-NEW-TEST-H-CASE1-NEXT: enum E1 { Green, Red };
@@ -20,11 +20,11 @@
// -----------------------------------------------------------------------------
// Test moving scoped enum declarations.
// -----------------------------------------------------------------------------
-// RUN: cp %S/Inputs/enum.h %T/move-enum/enum.h
-// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
-// RUN: clang-move -names="a::E2" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
-// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s
+// RUN: cp %S/Inputs/enum.h %t.dir/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %t.dir/move-enum/enum.cpp
+// RUN: clang-move -names="a::E2" -new_cc=%t.dir/move-enum/new_test.cpp -new_header=%t.dir/move-enum/new_test.h -old_cc=%t.dir/move-enum/enum.cpp -old_header=%t.dir/move-enum/enum.h %t.dir/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
+// RUN: FileCheck -input-file=%t.dir/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s
// CHECK-NEW-TEST-H-CASE2: namespace a {
// CHECK-NEW-TEST-H-CASE2-NEXT: enum class E2 { Yellow };
@@ -36,9 +36,9 @@
// -----------------------------------------------------------------------------
// Test not moving class-insided enum declarations.
// -----------------------------------------------------------------------------
-// RUN: cp %S/Inputs/enum.h %T/move-enum/enum.h
-// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
-// RUN: clang-move -names="a::C::E3" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/move-enum/new_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
+// RUN: cp %S/Inputs/enum.h %t.dir/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %t.dir/move-enum/enum.cpp
+// RUN: clang-move -names="a::C::E3" -new_cc=%t.dir/move-enum/new_test.cpp -new_header=%t.dir/move-enum/new_test.h -old_cc=%t.dir/move-enum/enum.cpp -old_header=%t.dir/move-enum/enum.h %t.dir/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/move-enum/new_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
// CHECK-EMPTY: {{^}}{{$}}
diff --git a/clang-tools-extra/test/clang-move/move-function.cpp b/clang-tools-extra/test/clang-move/move-function.cpp
index 0324b80..a52d55c 100644
--- a/clang-tools-extra/test/clang-move/move-function.cpp
+++ b/clang-tools-extra/test/clang-move/move-function.cpp
@@ -1,9 +1,9 @@
-// RUN: mkdir -p %T/move-function
-// RUN: cat %S/Inputs/function_test.h > %T/move-function/function_test.h
-// RUN: cat %S/Inputs/function_test.cpp > %T/move-function/function_test.cpp
-// RUN: cd %T/move-function
-// RUN: clang-move -names="g" -new_header=%T/move-function/new_function_test.h -old_header=../move-function/function_test.h %T/move-function/function_test.cpp --
-// RUN: FileCheck -input-file=%T/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
+// RUN: mkdir -p %t.dir/move-function
+// RUN: cat %S/Inputs/function_test.h > %t.dir/move-function/function_test.h
+// RUN: cat %S/Inputs/function_test.cpp > %t.dir/move-function/function_test.cpp
+// RUN: cd %t.dir/move-function
+// RUN: clang-move -names="g" -new_header=%t.dir/move-function/new_function_test.h -old_header=../move-function/function_test.h %t.dir/move-function/function_test.cpp --
+// RUN: FileCheck -input-file=%t.dir/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
//
// CHECK-NEW-TEST-H-CASE1: #ifndef {{.*}}NEW_FUNCTION_TEST_H
// CHECK-NEW-TEST-H-CASE1: #define {{.*}}NEW_FUNCTION_TEST_H
@@ -12,9 +12,9 @@
// CHECK-NEW-TEST-H-CASE1: {{[[:space:]]+}}
// CHECK-NEW-TEST-H-CASE1: #endif // {{.*}}NEW_FUNCTION_TEST_H
//
-// RUN: cp %S/Inputs/function_test* %T/move-function
-// RUN: clang-move -names="h" -new_header=%T/move-function/new_function_test.h -old_header=../move-function/function_test.h %T/move-function/function_test.cpp --
-// RUN: FileCheck -input-file=%T/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
+// RUN: cp %S/Inputs/function_test* %t.dir/move-function
+// RUN: clang-move -names="h" -new_header=%t.dir/move-function/new_function_test.h -old_header=../move-function/function_test.h %t.dir/move-function/function_test.cpp --
+// RUN: FileCheck -input-file=%t.dir/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
//
// CHECK-NEW-TEST-H-CASE2: #ifndef {{.*}}NEW_FUNCTION_TEST_H
// CHECK-NEW-TEST-H-CASE2: #define {{.*}}NEW_FUNCTION_TEST_H
@@ -25,10 +25,10 @@
// CHECK-NEW-TEST-H-CASE2: {{[[:space:]]+}}
// CHECK-NEW-TEST-H-CASE2: #endif // {{.*}}NEW_FUNCTION_TEST_H
//
-// RUN: cp %S/Inputs/function_test* %T/move-function
-// RUN: clang-move -names="f" -new_header=%T/move-function/new_function_test.h -new_cc=%T/move-function/new_function_test.cpp -old_header=../move-function/function_test.h -old_cc=../move-function/function_test.cpp %T/move-function/function_test.cpp --
-// RUN: FileCheck -input-file=%T/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE3 %s
-// RUN: FileCheck -input-file=%T/move-function/new_function_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE3 %s
+// RUN: cp %S/Inputs/function_test* %t.dir/move-function
+// RUN: clang-move -names="f" -new_header=%t.dir/move-function/new_function_test.h -new_cc=%t.dir/move-function/new_function_test.cpp -old_header=../move-function/function_test.h -old_cc=../move-function/function_test.cpp %t.dir/move-function/function_test.cpp --
+// RUN: FileCheck -input-file=%t.dir/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE3 %s
+// RUN: FileCheck -input-file=%t.dir/move-function/new_function_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE3 %s
//
// CHECK-NEW-TEST-H-CASE3: #ifndef {{.*}}NEW_FUNCTION_TEST_H
// CHECK-NEW-TEST-H-CASE3: #define {{.*}}NEW_FUNCTION_TEST_H
@@ -40,17 +40,17 @@
// CHECK-NEW-TEST-CPP-CASE3: {{[[:space:]]+}}
// CHECK-NEW-TEST-CPP-CASE3: void f() {}
//
-// RUN: cat %S/Inputs/function_test.h > %T/move-function/function_test.h
-// RUN: cat %S/Inputs/function_test.cpp > %T/move-function/function_test.cpp
-// RUN: clang-move -names="A::f" -new_header=%T/move-function/new_function_test.h -new_cc=%T/move-function/new_function_test.cpp -old_header=../move-function/function_test.h -old_cc=../move-function/function_test.cpp %T/move-function/function_test.cpp -dump_result -- | FileCheck %s -check-prefix=CHECK-EMPTY
+// RUN: cat %S/Inputs/function_test.h > %t.dir/move-function/function_test.h
+// RUN: cat %S/Inputs/function_test.cpp > %t.dir/move-function/function_test.cpp
+// RUN: clang-move -names="A::f" -new_header=%t.dir/move-function/new_function_test.h -new_cc=%t.dir/move-function/new_function_test.cpp -old_header=../move-function/function_test.h -old_cc=../move-function/function_test.cpp %t.dir/move-function/function_test.cpp -dump_result -- | FileCheck %s -check-prefix=CHECK-EMPTY
//
// CHECK-EMPTY: [{{[[:space:]]*}}]
//
-// RUN: cat %S/Inputs/function_test.h > %T/move-function/function_test.h
-// RUN: cat %S/Inputs/function_test.cpp > %T/move-function/function_test.cpp
-// RUN: clang-move -names="f,A" -new_header=%T/move-function/new_function_test.h -new_cc=%T/move-function/new_function_test.cpp -old_header=../move-function/function_test.h -old_cc=../move-function/function_test.cpp %T/move-function/function_test.cpp --
-// RUN: FileCheck -input-file=%T/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE4 %s
-// RUN: FileCheck -input-file=%T/move-function/new_function_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE4 %s
+// RUN: cat %S/Inputs/function_test.h > %t.dir/move-function/function_test.h
+// RUN: cat %S/Inputs/function_test.cpp > %t.dir/move-function/function_test.cpp
+// RUN: clang-move -names="f,A" -new_header=%t.dir/move-function/new_function_test.h -new_cc=%t.dir/move-function/new_function_test.cpp -old_header=../move-function/function_test.h -old_cc=../move-function/function_test.cpp %t.dir/move-function/function_test.cpp --
+// RUN: FileCheck -input-file=%t.dir/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE4 %s
+// RUN: FileCheck -input-file=%t.dir/move-function/new_function_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE4 %s
// CHECK-NEW-TEST-H-CASE4: #ifndef {{.*}}NEW_FUNCTION_TEST_H
// CHECK-NEW-TEST-H-CASE4: #define {{.*}}NEW_FUNCTION_TEST_H
diff --git a/clang-tools-extra/test/clang-move/move-multiple-classes.cpp b/clang-tools-extra/test/clang-move/move-multiple-classes.cpp
index 821d567..513b904 100644
--- a/clang-tools-extra/test/clang-move/move-multiple-classes.cpp
+++ b/clang-tools-extra/test/clang-move/move-multiple-classes.cpp
@@ -1,12 +1,12 @@
-// RUN: mkdir -p %T/move-multiple-classes
-// RUN: cp %S/Inputs/multiple_class_test* %T/move-multiple-classes/
-// RUN: cd %T/move-multiple-classes
-// RUN: clang-move -names="c::EnclosingMove5::Nested" -new_cc=%T/move-multiple-classes/new_multiple_class_test.cpp -new_header=%T/move-multiple-classes/new_multiple_class_test.h -old_cc=%T/move-multiple-classes/multiple_class_test.cpp -old_header=../move-multiple-classes/multiple_class_test.h -dump_result %T/move-multiple-classes/multiple_class_test.cpp -- -std=c++11| FileCheck %s -check-prefix=CHECK-EMPTY
-// RUN: clang-move -names="a::Move1, b::Move2,c::Move3,c::Move4,c::EnclosingMove5" -new_cc=%T/move-multiple-classes/new_multiple_class_test.cpp -new_header=%T/move-multiple-classes/new_multiple_class_test.h -old_cc=%T/move-multiple-classes/multiple_class_test.cpp -old_header=../move-multiple-classes/multiple_class_test.h %T/move-multiple-classes/multiple_class_test.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/move-multiple-classes/new_multiple_class_test.cpp -check-prefix=CHECK-NEW-TEST-CPP %s
-// RUN: FileCheck -input-file=%T/move-multiple-classes/new_multiple_class_test.h -check-prefix=CHECK-NEW-TEST-H %s
-// RUN: FileCheck -input-file=%T/move-multiple-classes/multiple_class_test.cpp -check-prefix=CHECK-OLD-TEST-CPP %s
-// RUN: FileCheck -input-file=%T/move-multiple-classes/multiple_class_test.h -check-prefix=CHECK-OLD-TEST-H %s
+// RUN: mkdir -p %t.dir/move-multiple-classes
+// RUN: cp %S/Inputs/multiple_class_test* %t.dir/move-multiple-classes/
+// RUN: cd %t.dir/move-multiple-classes
+// RUN: clang-move -names="c::EnclosingMove5::Nested" -new_cc=%t.dir/move-multiple-classes/new_multiple_class_test.cpp -new_header=%t.dir/move-multiple-classes/new_multiple_class_test.h -old_cc=%t.dir/move-multiple-classes/multiple_class_test.cpp -old_header=../move-multiple-classes/multiple_class_test.h -dump_result %t.dir/move-multiple-classes/multiple_class_test.cpp -- -std=c++11| FileCheck %s -check-prefix=CHECK-EMPTY
+// RUN: clang-move -names="a::Move1, b::Move2,c::Move3,c::Move4,c::EnclosingMove5" -new_cc=%t.dir/move-multiple-classes/new_multiple_class_test.cpp -new_header=%t.dir/move-multiple-classes/new_multiple_class_test.h -old_cc=%t.dir/move-multiple-classes/multiple_class_test.cpp -old_header=../move-multiple-classes/multiple_class_test.h %t.dir/move-multiple-classes/multiple_class_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/move-multiple-classes/new_multiple_class_test.cpp -check-prefix=CHECK-NEW-TEST-CPP %s
+// RUN: FileCheck -input-file=%t.dir/move-multiple-classes/new_multiple_class_test.h -check-prefix=CHECK-NEW-TEST-H %s
+// RUN: FileCheck -input-file=%t.dir/move-multiple-classes/multiple_class_test.cpp -check-prefix=CHECK-OLD-TEST-CPP %s
+// RUN: FileCheck -input-file=%t.dir/move-multiple-classes/multiple_class_test.h -check-prefix=CHECK-OLD-TEST-H %s
//
// CHECK-EMPTY: [{{[[:space:]]*}}]
//
diff --git a/clang-tools-extra/test/clang-move/move-template-class.cpp b/clang-tools-extra/test/clang-move/move-template-class.cpp
index 1a6a60b..29ed65e 100644
--- a/clang-tools-extra/test/clang-move/move-template-class.cpp
+++ b/clang-tools-extra/test/clang-move/move-template-class.cpp
@@ -1,18 +1,18 @@
-// RUN: mkdir -p %T/move-template-class
-// RUN: cp %S/Inputs/template_class_test* %T/move-template-class
-// RUN: cd %T/move-template-class
-// RUN: clang-move -names="A,B" -new_cc=%T/move-template-class/new_template_class_test.cpp -new_header=%T/move-template-class/new_template_class_test.h -old_cc=%T/move-template-class/template_class_test.cpp -old_header=../move-template-class/template_class_test.h %T/move-template-class/template_class_test.cpp --
-// RUN: FileCheck -input-file=%T/move-template-class/template_class_test.cpp -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
-// RUN: FileCheck -input-file=%T/move-template-class/template_class_test.h -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
-// RUN: FileCheck -input-file=%T/move-template-class/new_template_class_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE1 %s
-// RUN: FileCheck -input-file=%T/move-template-class/new_template_class_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
+// RUN: mkdir -p %t.dir/move-template-class
+// RUN: cp %S/Inputs/template_class_test* %t.dir/move-template-class
+// RUN: cd %t.dir/move-template-class
+// RUN: clang-move -names="A,B" -new_cc=%t.dir/move-template-class/new_template_class_test.cpp -new_header=%t.dir/move-template-class/new_template_class_test.h -old_cc=%t.dir/move-template-class/template_class_test.cpp -old_header=../move-template-class/template_class_test.h %t.dir/move-template-class/template_class_test.cpp --
+// RUN: FileCheck -input-file=%t.dir/move-template-class/template_class_test.cpp -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
+// RUN: FileCheck -input-file=%t.dir/move-template-class/template_class_test.h -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s
+// RUN: FileCheck -input-file=%t.dir/move-template-class/new_template_class_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE1 %s
+// RUN: FileCheck -input-file=%t.dir/move-template-class/new_template_class_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
//
-// RUN: cp %S/Inputs/template_class_test* %T/move-template-class
-// RUN: clang-move -names="A" -new_cc=%T/move-template-class/new_template_class_test.cpp -new_header=%T/move-template-class/new_template_class_test.h -old_cc=%T/move-template-class/template_class_test.cpp -old_header=../move-template-class/template_class_test.h %T/move-template-class/template_class_test.cpp --
-// RUN: FileCheck -input-file=%T/move-template-class/template_class_test.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s
-// RUN: FileCheck -input-file=%T/move-template-class/template_class_test.cpp -check-prefix=CHECK-OLD-TEST-CPP-CASE2 %s
-// RUN: FileCheck -input-file=%T/move-template-class/new_template_class_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
-// RUN: FileCheck -input-file=%T/move-template-class/new_template_class_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE2 %s
+// RUN: cp %S/Inputs/template_class_test* %t.dir/move-template-class
+// RUN: clang-move -names="A" -new_cc=%t.dir/move-template-class/new_template_class_test.cpp -new_header=%t.dir/move-template-class/new_template_class_test.h -old_cc=%t.dir/move-template-class/template_class_test.cpp -old_header=../move-template-class/template_class_test.h %t.dir/move-template-class/template_class_test.cpp --
+// RUN: FileCheck -input-file=%t.dir/move-template-class/template_class_test.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s
+// RUN: FileCheck -input-file=%t.dir/move-template-class/template_class_test.cpp -check-prefix=CHECK-OLD-TEST-CPP-CASE2 %s
+// RUN: FileCheck -input-file=%t.dir/move-template-class/new_template_class_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
+// RUN: FileCheck -input-file=%t.dir/move-template-class/new_template_class_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE2 %s
//
//
// CHECK-OLD-TEST-EMPTY: {{^}}{{$}}
diff --git a/clang-tools-extra/test/clang-move/move-type-alias.cpp b/clang-tools-extra/test/clang-move/move-type-alias.cpp
index ab70237..54d2b0e 100644
--- a/clang-tools-extra/test/clang-move/move-type-alias.cpp
+++ b/clang-tools-extra/test/clang-move/move-type-alias.cpp
@@ -1,14 +1,14 @@
-// RUN: mkdir -p %T/move-type-alias
-// RUN: cp %S/Inputs/type_alias.h %T/move-type-alias/type_alias.h
-// RUN: echo '#include "type_alias.h"' > %T/move-type-alias/type_alias.cpp
-// RUN: cd %T/move-type-alias
+// RUN: mkdir -p %t.dir/move-type-alias
+// RUN: cp %S/Inputs/type_alias.h %t.dir/move-type-alias/type_alias.h
+// RUN: echo '#include "type_alias.h"' > %t.dir/move-type-alias/type_alias.cpp
+// RUN: cd %t.dir/move-type-alias
//
// -----------------------------------------------------------------------------
// Test moving typedef declarations.
// -----------------------------------------------------------------------------
-// RUN: clang-move -names="Int1" -new_cc=%T/move-type-alias/new_test.cpp -new_header=%T/move-type-alias/new_test.h -old_cc=%T/move-type-alias/type_alias.cpp -old_header=%T/move-type-alias/type_alias.h %T/move-type-alias/type_alias.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/move-type-alias/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
-// RUN: FileCheck -input-file=%T/move-type-alias/type_alias.h -check-prefix=CHECK-OLD-TEST-H-CASE1 %s
+// RUN: clang-move -names="Int1" -new_cc=%t.dir/move-type-alias/new_test.cpp -new_header=%t.dir/move-type-alias/new_test.h -old_cc=%t.dir/move-type-alias/type_alias.cpp -old_header=%t.dir/move-type-alias/type_alias.h %t.dir/move-type-alias/type_alias.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/move-type-alias/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
+// RUN: FileCheck -input-file=%t.dir/move-type-alias/type_alias.h -check-prefix=CHECK-OLD-TEST-H-CASE1 %s
// CHECK-NEW-TEST-H-CASE1: typedef int Int1;
@@ -18,11 +18,11 @@
// -----------------------------------------------------------------------------
// Test moving type alias declarations.
// -----------------------------------------------------------------------------
-// RUN: cp %S/Inputs/type_alias.h %T/move-type-alias/type_alias.h
-// RUN: echo '#include "type_alias.h"' > %T/move-type-alias/type_alias.cpp
-// RUN: clang-move -names="Int2" -new_cc=%T/move-type-alias/new_test.cpp -new_header=%T/move-type-alias/new_test.h -old_cc=%T/move-type-alias/type_alias.cpp -old_header=%T/move-type-alias/type_alias.h %T/move-type-alias/type_alias.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/move-type-alias/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
-// RUN: FileCheck -input-file=%T/move-type-alias/type_alias.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s
+// RUN: cp %S/Inputs/type_alias.h %t.dir/move-type-alias/type_alias.h
+// RUN: echo '#include "type_alias.h"' > %t.dir/move-type-alias/type_alias.cpp
+// RUN: clang-move -names="Int2" -new_cc=%t.dir/move-type-alias/new_test.cpp -new_header=%t.dir/move-type-alias/new_test.h -old_cc=%t.dir/move-type-alias/type_alias.cpp -old_header=%t.dir/move-type-alias/type_alias.h %t.dir/move-type-alias/type_alias.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/move-type-alias/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
+// RUN: FileCheck -input-file=%t.dir/move-type-alias/type_alias.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s
// CHECK-NEW-TEST-H-CASE2: using Int2 = int;
@@ -32,10 +32,10 @@
// -----------------------------------------------------------------------------
// Test moving template type alias declarations.
// -----------------------------------------------------------------------------
-// RUN: cp %S/Inputs/type_alias.h %T/move-type-alias/type_alias.h
-// RUN: echo '#include "type_alias.h"' > %T/move-type-alias/type_alias.cpp
-// RUN: clang-move -names="B" -new_cc=%T/move-type-alias/new_test.cpp -new_header=%T/move-type-alias/new_test.h -old_cc=%T/move-type-alias/type_alias.cpp -old_header=%T/move-type-alias/type_alias.h %T/move-type-alias/type_alias.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/move-type-alias/new_test.h -check-prefix=CHECK-OLD-TEST-H-CASE3 %s
+// RUN: cp %S/Inputs/type_alias.h %t.dir/move-type-alias/type_alias.h
+// RUN: echo '#include "type_alias.h"' > %t.dir/move-type-alias/type_alias.cpp
+// RUN: clang-move -names="B" -new_cc=%t.dir/move-type-alias/new_test.cpp -new_header=%t.dir/move-type-alias/new_test.h -old_cc=%t.dir/move-type-alias/type_alias.cpp -old_header=%t.dir/move-type-alias/type_alias.h %t.dir/move-type-alias/type_alias.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/move-type-alias/new_test.h -check-prefix=CHECK-OLD-TEST-H-CASE3 %s
// CHECK-NEW-TEST-H-CASE3: template<class T> using B = A<T>;
// CHECK-OLD-TEST-H-CASE3-NOT: template<class T> using B = A<T>;
@@ -44,9 +44,9 @@
// -----------------------------------------------------------------------------
// Test not moving class-insided typedef declarations.
// -----------------------------------------------------------------------------
-// RUN: cp %S/Inputs/type_alias.h %T/move-type-alias/type_alias.h
-// RUN: echo '#include "type_alias.h"' > %T/move-type-alias/type_alias.cpp
-// RUN: clang-move -names="C::Int3" -new_cc=%T/move-type-alias/new_test.cpp -new_header=%T/move-type-alias/new_test.h -old_cc=%T/move-type-alias/type_alias.cpp -old_header=%T/move-type-alias/type_alias.h %T/move-type-alias/type_alias.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/move-type-alias/new_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
+// RUN: cp %S/Inputs/type_alias.h %t.dir/move-type-alias/type_alias.h
+// RUN: echo '#include "type_alias.h"' > %t.dir/move-type-alias/type_alias.cpp
+// RUN: clang-move -names="C::Int3" -new_cc=%t.dir/move-type-alias/new_test.cpp -new_header=%t.dir/move-type-alias/new_test.h -old_cc=%t.dir/move-type-alias/type_alias.cpp -old_header=%t.dir/move-type-alias/type_alias.h %t.dir/move-type-alias/type_alias.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/move-type-alias/new_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
// CHECK-EMPTY: {{^}}{{$}}
diff --git a/clang-tools-extra/test/clang-move/move-used-helper-decls.cpp b/clang-tools-extra/test/clang-move/move-used-helper-decls.cpp
index b4aed2c..3092976 100644
--- a/clang-tools-extra/test/clang-move/move-used-helper-decls.cpp
+++ b/clang-tools-extra/test/clang-move/move-used-helper-decls.cpp
@@ -1,13 +1,13 @@
-// RUN: mkdir -p %T/used-helper-decls
-// RUN: cp %S/Inputs/helper_decls_test* %T/used-helper-decls/
-// RUN: cd %T/used-helper-decls
+// RUN: mkdir -p %t.dir/used-helper-decls
+// RUN: cp %S/Inputs/helper_decls_test* %t.dir/used-helper-decls/
+// RUN: cd %t.dir/used-helper-decls
// ----------------------------------------------------------------------------
// Test moving used helper function and its transitively used functions.
// ----------------------------------------------------------------------------
-// RUN: clang-move -names="a::Class1" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS1-CPP %s
-// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS1-CPP %s
+// RUN: clang-move -names="a::Class1" -new_cc=%t.dir/used-helper-decls/new_helper_decls_test.cpp -new_header=%t.dir/used-helper-decls/new_helper_decls_test.h -old_cc=%t.dir/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %t.dir/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS1-CPP %s
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS1-CPP %s
// CHECK-NEW-CLASS1-CPP: #include "{{.*}}new_helper_decls_test.h"
// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
@@ -31,10 +31,10 @@
// ----------------------------------------------------------------------------
// Test moving used helper function and its transitively used static variables.
// ----------------------------------------------------------------------------
-// RUN: cp %S/Inputs/helper_decls_test* %T/used-helper-decls/
-// RUN: clang-move -names="a::Class2" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS2-CPP %s
-// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS2-CPP %s
+// RUN: cp %S/Inputs/helper_decls_test* %t.dir/used-helper-decls/
+// RUN: clang-move -names="a::Class2" -new_cc=%t.dir/used-helper-decls/new_helper_decls_test.cpp -new_header=%t.dir/used-helper-decls/new_helper_decls_test.h -old_cc=%t.dir/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %t.dir/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS2-CPP %s
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS2-CPP %s
// CHECK-NEW-CLASS2-CPP: #include "{{.*}}new_helper_decls_test.h"
// CHECK-NEW-CLASS2-CPP-SAME: {{[[:space:]]}}
@@ -67,10 +67,10 @@
// ----------------------------------------------------------------------------
// Test using a static member variable of a helper class.
// ----------------------------------------------------------------------------
-// RUN: cp %S/Inputs/helper_decls_test* %T/used-helper-decls/
-// RUN: clang-move -names="a::Class3" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS3-CPP %s
-// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS3-CPP %s
+// RUN: cp %S/Inputs/helper_decls_test* %t.dir/used-helper-decls/
+// RUN: clang-move -names="a::Class3" -new_cc=%t.dir/used-helper-decls/new_helper_decls_test.cpp -new_header=%t.dir/used-helper-decls/new_helper_decls_test.h -old_cc=%t.dir/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %t.dir/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS3-CPP %s
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS3-CPP %s
// CHECK-NEW-CLASS3-CPP: #include "{{.*}}new_helper_decls_test.h"
// CHECK-NEW-CLASS3-CPP-SAME: {{[[:space:]]}}
@@ -99,10 +99,10 @@
// ----------------------------------------------------------------------------
// Test moving helper classes.
// ----------------------------------------------------------------------------
-// RUN: cp %S/Inputs/helper_decls_test* %T/used-helper-decls/
-// RUN: clang-move -names="a::Class4" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS4-CPP %s
-// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS4-CPP %s
+// RUN: cp %S/Inputs/helper_decls_test* %t.dir/used-helper-decls/
+// RUN: clang-move -names="a::Class4" -new_cc=%t.dir/used-helper-decls/new_helper_decls_test.cpp -new_header=%t.dir/used-helper-decls/new_helper_decls_test.h -old_cc=%t.dir/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %t.dir/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS4-CPP %s
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS4-CPP %s
// CHECK-NEW-CLASS4-CPP: #include "{{.*}}new_helper_decls_test.h"
// CHECK-NEW-CLASS4-CPP-SAME: {{[[:space:]]}}
@@ -120,10 +120,10 @@
// ----------------------------------------------------------------------------
// Test moving helper variables and helper functions together.
// ----------------------------------------------------------------------------
-// RUN: cp %S/Inputs/helper_decls_test* %T/used-helper-decls/
-// RUN: clang-move -names="a::Class5" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS5-CPP %s
-// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS5-CPP %s
+// RUN: cp %S/Inputs/helper_decls_test* %t.dir/used-helper-decls/
+// RUN: clang-move -names="a::Class5" -new_cc=%t.dir/used-helper-decls/new_helper_decls_test.cpp -new_header=%t.dir/used-helper-decls/new_helper_decls_test.h -old_cc=%t.dir/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %t.dir/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS5-CPP %s
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS5-CPP %s
// CHECK-NEW-CLASS5-CPP: #include "{{.*}}new_helper_decls_test.h"
// CHECK-NEW-CLASS5-CPP-SAME: {{[[:space:]]}}
@@ -153,10 +153,10 @@
// ----------------------------------------------------------------------------
// Test moving helper variables and their transitively used helper classes.
// ----------------------------------------------------------------------------
-// RUN: cp %S/Inputs/helper_decls_test* %T/used-helper-decls/
-// RUN: clang-move -names="a::Class6" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS6-CPP %s
-// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS6-CPP %s
+// RUN: cp %S/Inputs/helper_decls_test* %t.dir/used-helper-decls/
+// RUN: clang-move -names="a::Class6" -new_cc=%t.dir/used-helper-decls/new_helper_decls_test.cpp -new_header=%t.dir/used-helper-decls/new_helper_decls_test.h -old_cc=%t.dir/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %t.dir/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS6-CPP %s
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS6-CPP %s
// CHECK-NEW-CLASS6-CPP: #include "{{.*}}new_helper_decls_test.h"
// CHECK-NEW-CLASS6-CPP-SAME: {{[[:space:]]}}
@@ -186,10 +186,10 @@
// ----------------------------------------------------------------------------
// Test moving classes where its methods use helpers.
// ----------------------------------------------------------------------------
-// RUN: cp %S/Inputs/helper_decls_test* %T/used-helper-decls/
-// RUN: clang-move -names="a::Class7" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS7-CPP %s
-// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS7-CPP %s
+// RUN: cp %S/Inputs/helper_decls_test* %t.dir/used-helper-decls/
+// RUN: clang-move -names="a::Class7" -new_cc=%t.dir/used-helper-decls/new_helper_decls_test.cpp -new_header=%t.dir/used-helper-decls/new_helper_decls_test.h -old_cc=%t.dir/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %t.dir/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS7-CPP %s
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS7-CPP %s
// CHECK-NEW-CLASS7-CPP: #include "{{.*}}new_helper_decls_test.h"
// CHECK-NEW-CLASS7-CPP-SAME: {{[[:space:]]}}
@@ -218,10 +218,10 @@
// ----------------------------------------------------------------------------
// Test moving helper function and its transitively used helper variables.
// ----------------------------------------------------------------------------
-// RUN: cp %S/Inputs/helper_decls_test* %T/used-helper-decls/
-// RUN: clang-move -names="a::Fun1" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-FUN1-CPP %s
-// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-FUN1-CPP %s
+// RUN: cp %S/Inputs/helper_decls_test* %t.dir/used-helper-decls/
+// RUN: clang-move -names="a::Fun1" -new_cc=%t.dir/used-helper-decls/new_helper_decls_test.cpp -new_header=%t.dir/used-helper-decls/new_helper_decls_test.h -old_cc=%t.dir/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %t.dir/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-FUN1-CPP %s
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-FUN1-CPP %s
// CHECK-NEW-FUN1-CPP: #include "{{.*}}new_helper_decls_test.h"
// CHECK-NEW-FUN1-CPP-SAME: {{[[:space:]]}}
@@ -244,11 +244,11 @@
// ----------------------------------------------------------------------------
// Test no moving helpers when moving inline functions in header.
// ----------------------------------------------------------------------------
-// RUN: cp %S/Inputs/helper_decls_test* %T/used-helper-decls/
-// RUN: clang-move -names="a::Fun2" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-FUN2-CPP %s
-// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.h -check-prefix=CHECK-NEW-FUN2-H %s
-// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.h -check-prefix=CHECK-OLD-FUN2-H %s
+// RUN: cp %S/Inputs/helper_decls_test* %t.dir/used-helper-decls/
+// RUN: clang-move -names="a::Fun2" -new_cc=%t.dir/used-helper-decls/new_helper_decls_test.cpp -new_header=%t.dir/used-helper-decls/new_helper_decls_test.h -old_cc=%t.dir/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %t.dir/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-FUN2-CPP %s
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/new_helper_decls_test.h -check-prefix=CHECK-NEW-FUN2-H %s
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/helper_decls_test.h -check-prefix=CHECK-OLD-FUN2-H %s
// CHECK-NEW-FUN2-H: namespace a {
// CHECK-NEW-FUN2-H-NEXT: inline void Fun2() {}
@@ -262,10 +262,10 @@
// ----------------------------------------------------------------------------
// Test moving used helper function and its transitively used functions.
// ----------------------------------------------------------------------------
-// RUN: cp %S/Inputs/helper_decls_test* %T/used-helper-decls/
-// RUN: clang-move -names="b::Fun3" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-FUN3-CPP %s
-// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-FUN3-CPP %s
+// RUN: cp %S/Inputs/helper_decls_test* %t.dir/used-helper-decls/
+// RUN: clang-move -names="b::Fun3" -new_cc=%t.dir/used-helper-decls/new_helper_decls_test.cpp -new_header=%t.dir/used-helper-decls/new_helper_decls_test.h -old_cc=%t.dir/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %t.dir/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-FUN3-CPP %s
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-FUN3-CPP %s
// CHECK-NEW-FUN3-CPP: #include "{{.*}}new_helper_decls_test.h"
// CHECK-NEW-FUN3-CPP-SAME: {{[[:space:]]}}
@@ -294,12 +294,12 @@
// ----------------------------------------------------------------------------
// Test moving all symbols in headers.
// ----------------------------------------------------------------------------
-// RUN: cp %S/Inputs/helper_decls_test* %T/used-helper-decls/
-// RUN: clang-move -names="a::Class1, a::Class2, a::Class3, a::Class4, a::Class5, a::Class5, a::Class6, a::Class7, a::Fun1, a::Fun2, b::Fun3" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.h -check-prefix=CHECK-NEW-H %s
-// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CPP %s
-// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
-// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -allow-empty -check-prefix=CHECK-EMPTY %s
+// RUN: cp %S/Inputs/helper_decls_test* %t.dir/used-helper-decls/
+// RUN: clang-move -names="a::Class1, a::Class2, a::Class3, a::Class4, a::Class5, a::Class5, a::Class6, a::Class7, a::Fun1, a::Fun2, b::Fun3" -new_cc=%t.dir/used-helper-decls/new_helper_decls_test.cpp -new_header=%t.dir/used-helper-decls/new_helper_decls_test.h -old_cc=%t.dir/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %t.dir/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/new_helper_decls_test.h -check-prefix=CHECK-NEW-H %s
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CPP %s
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/helper_decls_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
+// RUN: FileCheck -input-file=%t.dir/used-helper-decls/helper_decls_test.cpp -allow-empty -check-prefix=CHECK-EMPTY %s
// CHECK-NEW-H: namespace a {
diff --git a/clang-tools-extra/test/clang-move/move-var.cpp b/clang-tools-extra/test/clang-move/move-var.cpp
index 4a3554c..bacba0b 100644
--- a/clang-tools-extra/test/clang-move/move-var.cpp
+++ b/clang-tools-extra/test/clang-move/move-var.cpp
@@ -1,11 +1,11 @@
-// RUN: mkdir -p %T/move-var
-// RUN: cp %S/Inputs/var_test* %T/move-var
-// RUN: cd %T/move-var
-// RUN: clang-move -names="a::kGlobalInt" -new_header=%T/move-var/new_var_test.h -old_header=../move-var/var_test.h -old_cc=../move-var/var_test.cpp -new_cc=%T/move-var/new_var_test.cpp %T/move-var/var_test.cpp --
-// RUN: FileCheck -input-file=%T/move-var/var_test.h -check-prefix=CHECK-OLD-VAR-H-CASE1 %s
-// RUN: FileCheck -input-file=%T/move-var/var_test.cpp -check-prefix=CHECK-OLD-VAR-CPP-CASE1 %s
-// RUN: FileCheck -input-file=%T/move-var/new_var_test.h -check-prefix=CHECK-NEW-VAR-H-CASE1 %s
-// RUN: FileCheck -input-file=%T/move-var/new_var_test.cpp -check-prefix=CHECK-NEW-VAR-CPP-CASE1 %s
+// RUN: mkdir -p %t.dir/move-var
+// RUN: cp %S/Inputs/var_test* %t.dir/move-var
+// RUN: cd %t.dir/move-var
+// RUN: clang-move -names="a::kGlobalInt" -new_header=%t.dir/move-var/new_var_test.h -old_header=../move-var/var_test.h -old_cc=../move-var/var_test.cpp -new_cc=%t.dir/move-var/new_var_test.cpp %t.dir/move-var/var_test.cpp --
+// RUN: FileCheck -input-file=%t.dir/move-var/var_test.h -check-prefix=CHECK-OLD-VAR-H-CASE1 %s
+// RUN: FileCheck -input-file=%t.dir/move-var/var_test.cpp -check-prefix=CHECK-OLD-VAR-CPP-CASE1 %s
+// RUN: FileCheck -input-file=%t.dir/move-var/new_var_test.h -check-prefix=CHECK-NEW-VAR-H-CASE1 %s
+// RUN: FileCheck -input-file=%t.dir/move-var/new_var_test.cpp -check-prefix=CHECK-NEW-VAR-CPP-CASE1 %s
// CHECK-OLD-VAR-H-CASE1-NOT: extern int kGlobalInt;
// CHECK-OLD-VAR-H-CASE1: int kGlobalInt = 3;
@@ -18,12 +18,12 @@
// CHECK-NEW-VAR-CPP-CASE1: int kGlobalInt = 1;
-// RUN: cp %S/Inputs/var_test* %T/move-var
-// RUN: clang-move -names="a::kGlobalStr" -new_header=%T/move-var/new_var_test.h -old_header=../move-var/var_test.h -old_cc=../move-var/var_test.cpp -new_cc=%T/move-var/new_var_test.cpp %T/move-var/var_test.cpp --
-// RUN: FileCheck -input-file=%T/move-var/var_test.h -check-prefix=CHECK-OLD-VAR-H-CASE2 %s
-// RUN: FileCheck -input-file=%T/move-var/var_test.cpp -check-prefix=CHECK-OLD-VAR-CPP-CASE2 %s
-// RUN: FileCheck -input-file=%T/move-var/new_var_test.h -check-prefix=CHECK-NEW-VAR-H-CASE2 %s
-// RUN: FileCheck -input-file=%T/move-var/new_var_test.cpp -check-prefix=CHECK-NEW-VAR-CPP-CASE2 %s
+// RUN: cp %S/Inputs/var_test* %t.dir/move-var
+// RUN: clang-move -names="a::kGlobalStr" -new_header=%t.dir/move-var/new_var_test.h -old_header=../move-var/var_test.h -old_cc=../move-var/var_test.cpp -new_cc=%t.dir/move-var/new_var_test.cpp %t.dir/move-var/var_test.cpp --
+// RUN: FileCheck -input-file=%t.dir/move-var/var_test.h -check-prefix=CHECK-OLD-VAR-H-CASE2 %s
+// RUN: FileCheck -input-file=%t.dir/move-var/var_test.cpp -check-prefix=CHECK-OLD-VAR-CPP-CASE2 %s
+// RUN: FileCheck -input-file=%t.dir/move-var/new_var_test.h -check-prefix=CHECK-NEW-VAR-H-CASE2 %s
+// RUN: FileCheck -input-file=%t.dir/move-var/new_var_test.cpp -check-prefix=CHECK-NEW-VAR-CPP-CASE2 %s
// CHECK-OLD-VAR-H-CASE2-NOT: extern const char *const kGlobalStr;
// CHECK-OLD-VAR-H-CASE2: const char *const kGlobalStr = "Hello2";
@@ -36,10 +36,10 @@
// CHECK-NEW-VAR-CPP-CASE2: const char *const kGlobalStr = "Hello";
-// RUN: cp %S/Inputs/var_test* %T/move-var
-// RUN: clang-move -names="kEvilInt" -new_header=%T/move-var/new_var_test.h -old_header=../move-var/var_test.h -old_cc=../move-var/var_test.cpp -new_cc=%T/move-var/new_var_test.cpp %T/move-var/var_test.cpp --
-// RUN: FileCheck -input-file=%T/move-var/var_test.h -check-prefix=CHECK-OLD-VAR-H-CASE3 %s
-// RUN: FileCheck -input-file=%T/move-var/new_var_test.h -check-prefix=CHECK-NEW-VAR-H-CASE3 %s
+// RUN: cp %S/Inputs/var_test* %t.dir/move-var
+// RUN: clang-move -names="kEvilInt" -new_header=%t.dir/move-var/new_var_test.h -old_header=../move-var/var_test.h -old_cc=../move-var/var_test.cpp -new_cc=%t.dir/move-var/new_var_test.cpp %t.dir/move-var/var_test.cpp --
+// RUN: FileCheck -input-file=%t.dir/move-var/var_test.h -check-prefix=CHECK-OLD-VAR-H-CASE3 %s
+// RUN: FileCheck -input-file=%t.dir/move-var/new_var_test.h -check-prefix=CHECK-NEW-VAR-H-CASE3 %s
// CHECK-OLD-VAR-H-CASE3-NOT: int kEvilInt = 2;
diff --git a/clang-tools-extra/test/clang-move/no-move-macro-helpers.cpp b/clang-tools-extra/test/clang-move/no-move-macro-helpers.cpp
index 282eee0..e7a5b4e 100644
--- a/clang-tools-extra/test/clang-move/no-move-macro-helpers.cpp
+++ b/clang-tools-extra/test/clang-move/no-move-macro-helpers.cpp
@@ -1,16 +1,16 @@
-// RUN: mkdir -p %T/no-move-macro-helper
-// RUN: cat %S/Inputs/macro_helper_test.h > %T/no-move-macro-helper/macro_helper_test.h
-// RUN: cat %S/Inputs/macro_helper_test.cpp > %T/no-move-macro-helper/macro_helper_test.cpp
-// RUN: cd %T/no-move-macro-helper
+// RUN: mkdir -p %t.dir/no-move-macro-helper
+// RUN: cat %S/Inputs/macro_helper_test.h > %t.dir/no-move-macro-helper/macro_helper_test.h
+// RUN: cat %S/Inputs/macro_helper_test.cpp > %t.dir/no-move-macro-helper/macro_helper_test.cpp
+// RUN: cd %t.dir/no-move-macro-helper
//
// -----------------------------------------------------------------------------
// Test no moving helpers in macro.
// -----------------------------------------------------------------------------
-// RUN: clang-move -names="A" -new_cc=%T/no-move-macro-helper/new_test.cpp -new_header=%T/no-move-macro-helper/new_test.h -old_cc=%T/no-move-macro-helper/macro_helper_test.cpp -old_header=%T/no-move-macro-helper/macro_helper_test.h %T/no-move-macro-helper/macro_helper_test.cpp -- -std=c++11
-// RUN: FileCheck -input-file=%T/no-move-macro-helper/new_test.h -check-prefix=CHECK-NEW-TEST-CASE1-H %s
-// RUN: FileCheck -input-file=%T/no-move-macro-helper/new_test.cpp -check-prefix=CHECK-NEW-TEST-CASE1-CPP %s
-// RUN: FileCheck -input-file=%T/no-move-macro-helper/macro_helper_test.h -check-prefix=CHECK-OLD-TEST-CASE1-H %s
-// RUN: FileCheck -input-file=%T/no-move-macro-helper/macro_helper_test.cpp -check-prefix=CHECK-OLD-TEST-CASE1-CPP %s
+// RUN: clang-move -names="A" -new_cc=%t.dir/no-move-macro-helper/new_test.cpp -new_header=%t.dir/no-move-macro-helper/new_test.h -old_cc=%t.dir/no-move-macro-helper/macro_helper_test.cpp -old_header=%t.dir/no-move-macro-helper/macro_helper_test.h %t.dir/no-move-macro-helper/macro_helper_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.dir/no-move-macro-helper/new_test.h -check-prefix=CHECK-NEW-TEST-CASE1-H %s
+// RUN: FileCheck -input-file=%t.dir/no-move-macro-helper/new_test.cpp -check-prefix=CHECK-NEW-TEST-CASE1-CPP %s
+// RUN: FileCheck -input-file=%t.dir/no-move-macro-helper/macro_helper_test.h -check-prefix=CHECK-OLD-TEST-CASE1-H %s
+// RUN: FileCheck -input-file=%t.dir/no-move-macro-helper/macro_helper_test.cpp -check-prefix=CHECK-OLD-TEST-CASE1-CPP %s
// CHECK-NEW-TEST-CASE1-H: class A {};
@@ -24,14 +24,14 @@
// -----------------------------------------------------------------------------
// Test moving all.
// -----------------------------------------------------------------------------
-// RUN: cat %S/Inputs/macro_helper_test.h > %T/no-move-macro-helper/macro_helper_test.h
-// RUN: cat %S/Inputs/macro_helper_test.cpp > %T/no-move-macro-helper/macro_helper_test.cpp
-// RUN: clang-move -names="A, f1" -new_cc=%T/no-move-macro-helper/new_test.cpp -new_header=%T/no-move-macro-helper/new_test.h -old_cc=%T/no-move-macro-helper/macro_helper_test.cpp -old_header=%T/no-move-macro-helper/macro_helper_test.h %T/no-move-macro-helper/macro_helper_test.cpp -- -std=c++11
+// RUN: cat %S/Inputs/macro_helper_test.h > %t.dir/no-move-macro-helper/macro_helper_test.h
+// RUN: cat %S/Inputs/macro_helper_test.cpp > %t.dir/no-move-macro-helper/macro_helper_test.cpp
+// RUN: clang-move -names="A, f1" -new_cc=%t.dir/no-move-macro-helper/new_test.cpp -new_header=%t.dir/no-move-macro-helper/new_test.h -old_cc=%t.dir/no-move-macro-helper/macro_helper_test.cpp -old_header=%t.dir/no-move-macro-helper/macro_helper_test.h %t.dir/no-move-macro-helper/macro_helper_test.cpp -- -std=c++11
//
-// RUN: FileCheck -input-file=%T/no-move-macro-helper/new_test.h -check-prefix=CHECK-NEW-TEST-CASE2-H %s
-// RUN: FileCheck -input-file=%T/no-move-macro-helper/new_test.cpp -check-prefix=CHECK-NEW-TEST-CASE2-CPP %s
-// RUN: FileCheck -input-file=%T/no-move-macro-helper/macro_helper_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
-// RUN: FileCheck -input-file=%T/no-move-macro-helper/macro_helper_test.cpp -allow-empty -check-prefix=CHECK-EMPTY %s
+// RUN: FileCheck -input-file=%t.dir/no-move-macro-helper/new_test.h -check-prefix=CHECK-NEW-TEST-CASE2-H %s
+// RUN: FileCheck -input-file=%t.dir/no-move-macro-helper/new_test.cpp -check-prefix=CHECK-NEW-TEST-CASE2-CPP %s
+// RUN: FileCheck -input-file=%t.dir/no-move-macro-helper/macro_helper_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
+// RUN: FileCheck -input-file=%t.dir/no-move-macro-helper/macro_helper_test.cpp -allow-empty -check-prefix=CHECK-EMPTY %s
// CHECK-NEW-TEST-CASE2-H: class A {};
// CHECK-NEW-TEST-CASE2-H-NEXT:void f1();
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.c
new file mode 100644
index 0000000..55f5884
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.c
@@ -0,0 +1,54 @@
+// RUN: %check_clang_tidy %s bugprone-invalid-enum-default-initialization %t
+
+enum Enum1 {
+ Enum1_A = 1,
+ Enum1_B
+};
+
+struct Struct1 {
+ int a;
+ enum Enum1 b;
+};
+
+struct Struct2 {
+ struct Struct1 a;
+ char b;
+};
+
+enum Enum1 E1 = {};
+// CHECK-NOTES: :[[@LINE-1]]:17: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+// CHECK-NOTES: :3:6: note: enum is defined here
+enum Enum1 E2[10] = {};
+// CHECK-NOTES: :[[@LINE-1]]:21: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+// CHECK-NOTES: :3:6: note: enum is defined here
+enum Enum1 E3[10] = {Enum1_A};
+// CHECK-NOTES: :[[@LINE-1]]:21: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+// CHECK-NOTES: :3:6: note: enum is defined here
+enum Enum1 E4[2][2] = {{Enum1_A}, {Enum1_A}};
+// CHECK-NOTES: :[[@LINE-1]]:24: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+// CHECK-NOTES: :3:6: note: enum is defined here
+// CHECK-NOTES: :[[@LINE-3]]:35: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+// CHECK-NOTES: :3:6: note: enum is defined here
+enum Enum1 E5[2][2] = {{Enum1_A, Enum1_A}};
+// CHECK-NOTES: :[[@LINE-1]]:23: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+// CHECK-NOTES: :3:6: note: enum is defined here
+
+
+struct Struct1 S1[2][2] = {{{1, Enum1_A}, {2, Enum1_A}}};
+// CHECK-NOTES: :[[@LINE-1]]:27: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+// CHECK-NOTES: :3:6: note: enum is defined here
+
+struct Struct2 S2[3] = {{1}};
+// CHECK-NOTES: :[[@LINE-1]]:24: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+// CHECK-NOTES: :3:6: note: enum is defined here
+// CHECK-NOTES: :[[@LINE-3]]:26: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+// CHECK-NOTES: :3:6: note: enum is defined here
+
+union Union1 {
+ enum Enum1 a;
+ int b;
+};
+
+// no warnings for union
+union Union1 U1 = {};
+union Union1 U2[3] = {};
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.cpp
new file mode 100644
index 0000000..eb3d563
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/invalid-enum-default-initialization.cpp
@@ -0,0 +1,145 @@
+// RUN: %check_clang_tidy -std=c++17 %s bugprone-invalid-enum-default-initialization %t
+
+enum class Enum0: int {
+ A = 0,
+ B
+};
+
+enum class Enum1: int {
+ A = 1,
+ B
+};
+
+enum Enum2 {
+ Enum_A = 4,
+ Enum_B
+};
+
+Enum0 E0_1{};
+Enum0 E0_2 = Enum0();
+Enum0 E0_3;
+Enum0 E0_4{0};
+Enum0 E0_5{Enum0::A};
+Enum0 E0_6{Enum0::B};
+
+Enum1 E1_1{};
+// CHECK-NOTES: :[[@LINE-1]]:11: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+// CHECK-NOTES: :8:12: note: enum is defined here
+Enum1 E1_2 = Enum1();
+// CHECK-NOTES: :[[@LINE-1]]:14: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+// CHECK-NOTES: :8:12: note: enum is defined here
+Enum1 E1_3;
+Enum1 E1_4{0};
+Enum1 E1_5{Enum1::A};
+Enum1 E1_6{Enum1::B};
+
+Enum2 E2_1{};
+// CHECK-NOTES: :[[@LINE-1]]:11: warning: enum value of type 'Enum2' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+// CHECK-NOTES: :13:6: note: enum is defined here
+Enum2 E2_2 = Enum2();
+// CHECK-NOTES: :[[@LINE-1]]:14: warning: enum value of type 'Enum2' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+// CHECK-NOTES: :13:6: note: enum is defined here
+
+void f1() {
+ static Enum1 S; // FIMXE: warn for this?
+ Enum1 A;
+ Enum1 B = Enum1();
+ // CHECK-NOTES: :[[@LINE-1]]:13: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+ // CHECK-NOTES: :8:12: note: enum is defined here
+ int C = int();
+}
+
+void f2() {
+ Enum1 A{};
+ // CHECK-NOTES: :[[@LINE-1]]:10: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+ // CHECK-NOTES: :8:12: note: enum is defined here
+ Enum1 B = Enum1();
+ // CHECK-NOTES: :[[@LINE-1]]:13: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+ // CHECK-NOTES: :8:12: note: enum is defined here
+ Enum1 C[5] = {{}};
+ // CHECK-NOTES: :[[@LINE-1]]:16: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+ // CHECK-NOTES: :8:12: note: enum is defined here
+ // CHECK-NOTES: :[[@LINE-3]]:17: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+ // CHECK-NOTES: :8:12: note: enum is defined here
+ Enum1 D[5] = {}; // FIMXE: warn for this?
+ // CHECK-NOTES: :[[@LINE-1]]:16: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+ // CHECK-NOTES: :8:12: note: enum is defined here
+}
+
+struct S1 {
+ Enum1 E_1{};
+ // CHECK-NOTES: :[[@LINE-1]]:12: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+ // CHECK-NOTES: :8:12: note: enum is defined here
+ Enum1 E_2 = Enum1();
+ // CHECK-NOTES: :[[@LINE-1]]:15: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+ // CHECK-NOTES: :8:12: note: enum is defined here
+ Enum1 E_3;
+ Enum1 E_4;
+ Enum1 E_5;
+
+ S1() :
+ E_3{},
+ // CHECK-NOTES: :[[@LINE-1]]:8: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+ // CHECK-NOTES: :8:12: note: enum is defined here
+ E_4(),
+ // CHECK-NOTES: :[[@LINE-1]]:8: warning: enum value of type 'Enum1' initialized with invalid value of 0, enum doesn't have a zero-value enumerator
+ // CHECK-NOTES: :8:12: note: enum is defined here
+ E_5{Enum1::B}
+ {}
+};
+
+struct S2 {
+ Enum0 X;
+ Enum1 Y;
+ Enum2 Z;
+};
+
+struct S3 {
+ S2 X;
+ int Y;
+};
+
+struct S4 : public S3 {
+ int Z;
+};
+
+struct S5 {
+ S2 X[3];
+ int Y;
+};
+
+S2 VarS2{};
+// CHECK-NOTES: :[[@LINE-1]]:9: warning: enum value of type 'Enum1' initialized with invalid value of 0
+// CHECK-NOTES: :8:12: note: enum is defined here
+// CHECK-NOTES: :[[@LINE-3]]:9: warning: enum value of type 'Enum2' initialized with invalid value of 0
+// CHECK-NOTES: :13:6: note: enum is defined here
+S3 VarS3{};
+// CHECK-NOTES: :[[@LINE-1]]:10: warning: enum value of type 'Enum1' initialized with invalid value of 0
+// CHECK-NOTES: :8:12: note: enum is defined here
+// CHECK-NOTES: :[[@LINE-3]]:10: warning: enum value of type 'Enum2' initialized with invalid value of 0
+// CHECK-NOTES: :13:6: note: enum is defined here
+S4 VarS4{};
+// CHECK-NOTES: :[[@LINE-1]]:10: warning: enum value of type 'Enum1' initialized with invalid value of 0
+// CHECK-NOTES: :8:12: note: enum is defined here
+// CHECK-NOTES: :[[@LINE-3]]:10: warning: enum value of type 'Enum2' initialized with invalid value of 0
+// CHECK-NOTES: :13:6: note: enum is defined here
+S5 VarS5{};
+// CHECK-NOTES: :[[@LINE-1]]:10: warning: enum value of type 'Enum1' initialized with invalid value of 0
+// CHECK-NOTES: :8:12: note: enum is defined here
+
+enum class EnumFwd;
+
+EnumFwd Fwd{};
+
+enum class EnumEmpty {};
+
+EnumEmpty Empty{};
+
+template<typename T>
+struct Templ {
+ T Mem1{};
+ // CHECK-NOTES: :[[@LINE-1]]:9: warning: enum value of type 'Enum1' initialized with invalid value of 0
+ // CHECK-NOTES: :8:12: note: enum is defined here
+};
+
+Templ<Enum1> TemplVar;
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/signed-char-misuse-c23.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone/signed-char-misuse-c23.c
new file mode 100644
index 0000000..ad6e31d
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/signed-char-misuse-c23.c
@@ -0,0 +1,201 @@
+// RUN: %check_clang_tidy %s bugprone-signed-char-misuse %t -- -- -std=c23
+
+///////////////////////////////////////////////////////////////////
+/// Test cases correctly caught by the check.
+
+int SimpleVarDeclaration() {
+ signed char CCharacter = -5;
+ int NCharacter = CCharacter;
+ // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse]
+
+ return NCharacter;
+}
+
+int SimpleAssignment() {
+ signed char CCharacter = -5;
+ int NCharacter;
+ NCharacter = CCharacter;
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse]
+
+ return NCharacter;
+}
+
+int NegativeConstValue() {
+ const signed char CCharacter = -5;
+ int NCharacter = CCharacter;
+ // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse]
+
+ return NCharacter;
+}
+
+int CharPointer(signed char *CCharacter) {
+ int NCharacter = *CCharacter;
+ // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse]
+
+ return NCharacter;
+}
+
+int SignedUnsignedCharEquality(signed char SCharacter) {
+ unsigned char USCharacter = 'a';
+ if (SCharacter == USCharacter) // CHECK-MESSAGES: [[@LINE]]:7: warning: comparison between 'signed char' and 'unsigned char' [bugprone-signed-char-misuse]
+ return 1;
+ return 0;
+}
+
+int SignedUnsignedCharIneqiality(signed char SCharacter) {
+ unsigned char USCharacter = 'a';
+ if (SCharacter != USCharacter) // CHECK-MESSAGES: [[@LINE]]:7: warning: comparison between 'signed char' and 'unsigned char' [bugprone-signed-char-misuse]
+ return 1;
+ return 0;
+}
+
+int CompareWithNonAsciiConstant(unsigned char USCharacter) {
+ const signed char SCharacter = -5;
+ if (USCharacter == SCharacter) // CHECK-MESSAGES: [[@LINE]]:7: warning: comparison between 'signed char' and 'unsigned char' [bugprone-signed-char-misuse]
+ return 1;
+ return 0;
+}
+
+int CompareWithUnsignedNonAsciiConstant(signed char SCharacter) {
+ const unsigned char USCharacter = 128;
+ if (USCharacter == SCharacter) // CHECK-MESSAGES: [[@LINE]]:7: warning: comparison between 'signed char' and 'unsigned char' [bugprone-signed-char-misuse]
+ return 1;
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////
+/// Test cases correctly ignored by the check.
+
+// Enum with a fixed underlying type of signed char.
+enum EType1 : signed char {
+ EType1_M128 = -128,
+ EType1_1 = 1,
+};
+
+enum EType1 es1_1 = EType1_M128;
+enum EType1 es1_2 = EType1_1;
+enum EType1 es1_3 = -128;
+
+void assign(enum EType1 *es) {
+ *es = EType1_M128;
+}
+
+// Type aliased enum with a fixed underlying type of signed char.
+typedef signed char int8_t;
+typedef enum EType2 : int8_t {
+ EType2_M128 = -128,
+ EType2_1 = 1,
+} EType2_t;
+
+EType2_t es2_1 = EType2_M128;
+EType2_t es2_2 = EType2_1;
+EType2_t es2_3 = -128;
+
+// Enum with a fixed underlying type of unsigned char.
+enum EType3 : unsigned char {
+ EType3_1 = 1,
+ EType3_128 = 128,
+};
+
+enum EType3 es3_1 = EType3_1;
+enum EType3 es3_2 = EType3_128;
+enum EType3 es3_3 = 128;
+
+
+int UnsignedCharCast() {
+ unsigned char CCharacter = 'a';
+ int NCharacter = CCharacter;
+
+ return NCharacter;
+}
+
+int PositiveConstValue() {
+ const signed char CCharacter = 5;
+ int NCharacter = CCharacter;
+
+ return NCharacter;
+}
+
+// signed char -> integer cast is not the direct child of declaration expression.
+int DescendantCast() {
+ signed char CCharacter = 'a';
+ int NCharacter = 10 + CCharacter;
+
+ return NCharacter;
+}
+
+// signed char -> integer cast is not the direct child of assignment expression.
+int DescendantCastAssignment() {
+ signed char CCharacter = 'a';
+ int NCharacter;
+ NCharacter = 10 + CCharacter;
+
+ return NCharacter;
+}
+
+// bool is an integer type in clang; make sure to ignore it.
+bool BoolVarDeclaration() {
+ signed char CCharacter = 'a';
+ bool BCharacter = CCharacter == 'b';
+
+ return BCharacter;
+}
+
+// bool is an integer type in clang; make sure to ignore it.
+bool BoolAssignment() {
+ signed char CCharacter = 'a';
+ bool BCharacter;
+ BCharacter = CCharacter == 'b';
+
+ return BCharacter;
+}
+
+// char is an integer type in clang; make sure to ignore it.
+unsigned char CharToCharCast() {
+ signed char SCCharacter = 'a';
+ unsigned char USCharacter;
+ USCharacter = SCCharacter;
+
+ return USCharacter;
+}
+
+int SameCharTypeComparison(signed char SCharacter) {
+ signed char SCharacter2 = 'a';
+ if (SCharacter == SCharacter2)
+ return 1;
+ return 0;
+}
+
+int SameCharTypeComparison2(unsigned char USCharacter) {
+ unsigned char USCharacter2 = 'a';
+ if (USCharacter == USCharacter2)
+ return 1;
+ return 0;
+}
+
+int CharIntComparison(signed char SCharacter) {
+ int ICharacter = 10;
+ if (SCharacter == ICharacter)
+ return 1;
+ return 0;
+}
+
+int CompareWithAsciiLiteral(unsigned char USCharacter) {
+ if (USCharacter == 'x')
+ return 1;
+ return 0;
+}
+
+int CompareWithAsciiConstant(unsigned char USCharacter) {
+ const signed char SCharacter = 'a';
+ if (USCharacter == SCharacter)
+ return 1;
+ return 0;
+}
+
+int CompareWithUnsignedAsciiConstant(signed char SCharacter) {
+ const unsigned char USCharacter = 'a';
+ if (USCharacter == SCharacter)
+ return 1;
+ return 0;
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unhandled-self-assignment.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unhandled-self-assignment.cpp
index 8610393..c2a8ddc 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unhandled-self-assignment.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unhandled-self-assignment.cpp
@@ -28,6 +28,13 @@ template <class T>
class auto_ptr {
};
+namespace pmr {
+ template <typename TYPE = void>
+ class allocator {};
+}
+
+struct allocator_arg_t {} allocator_arg;
+
} // namespace std
void assert(int expression){};
@@ -229,6 +236,122 @@ bool operator!=(Foo2 &, Foo2 &) {
};
}
+// Missing call to `swap` function
+class AllocatorAwareClassNoSwap {
+ // pointer member to trigger bugprone-unhandled-self-assignment
+ void *foo = nullptr;
+
+ public:
+ using allocator_type = std::pmr::allocator<>;
+
+ AllocatorAwareClassNoSwap(const AllocatorAwareClassNoSwap& other) {
+ }
+
+ AllocatorAwareClassNoSwap(const AllocatorAwareClassNoSwap& other, const allocator_type& alloc) {
+ }
+
+ AllocatorAwareClassNoSwap& operator=(const AllocatorAwareClassNoSwap& other) {
+ // CHECK-MESSAGES: [[@LINE-1]]:32: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+ AllocatorAwareClassNoSwap tmp(other, get_allocator());
+ return *this;
+ }
+
+ allocator_type get_allocator() const {
+ return allocator_type();
+ }
+};
+
+// "Wrong" type is passed to member `swap` function
+class AllocatorAwareClassSwapWrongArgType {
+ // pointer member to trigger bugprone-unhandled-self-assignment
+ void *foo = nullptr;
+
+ public:
+ using allocator_type = std::pmr::allocator<>;
+
+ AllocatorAwareClassSwapWrongArgType(const AllocatorAwareClassSwapWrongArgType& other) {
+ }
+
+ AllocatorAwareClassSwapWrongArgType(const AllocatorAwareClassSwapWrongArgType& other, const allocator_type& alloc) {
+ }
+
+ AllocatorAwareClassSwapWrongArgType& operator=(const AllocatorAwareClassSwapWrongArgType& other) {
+ // CHECK-MESSAGES: [[@LINE-1]]:42: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+ int tmp = 0;
+ swap(tmp);
+
+ return *this;
+ }
+
+ void swap(int&) noexcept {
+ }
+
+ allocator_type get_allocator() const {
+ return allocator_type();
+ }
+};
+
+
+// Making ADL `swap` call but with wrong argument type
+class AllocatorAwareClassAdlSwapWrongArgType {
+ // pointer member to trigger bugprone-unhandled-self-assignment
+ void *foo = nullptr;
+
+ public:
+ using allocator_type = std::pmr::allocator<>;
+
+ AllocatorAwareClassAdlSwapWrongArgType(const AllocatorAwareClassAdlSwapWrongArgType& other) {
+ }
+
+ AllocatorAwareClassAdlSwapWrongArgType(const AllocatorAwareClassAdlSwapWrongArgType& other, const allocator_type& alloc) {
+ }
+
+ AllocatorAwareClassAdlSwapWrongArgType& operator=(const AllocatorAwareClassAdlSwapWrongArgType& other) {
+ // CHECK-MESSAGES: [[@LINE-1]]:45: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+ int tmp = 0;
+ swap(*this, tmp);
+
+ return *this;
+ }
+
+ allocator_type get_allocator() const {
+ return allocator_type();
+ }
+
+ friend void swap(AllocatorAwareClassAdlSwapWrongArgType&, int&) {
+ }
+};
+
+// `this` isn't passed to `swap`
+class AllocatorAwareClassAdlSwapWrongArgs {
+ // pointer member to trigger bugprone-unhandled-self-assignment
+ void *foo = nullptr;
+
+ public:
+ using allocator_type = std::pmr::allocator<>;
+
+ AllocatorAwareClassAdlSwapWrongArgs(const AllocatorAwareClassAdlSwapWrongArgs& other) {
+ }
+
+ AllocatorAwareClassAdlSwapWrongArgs(const AllocatorAwareClassAdlSwapWrongArgs& other, const allocator_type& alloc) {
+ }
+
+ AllocatorAwareClassAdlSwapWrongArgs& operator=(const AllocatorAwareClassAdlSwapWrongArgs& other) {
+ // CHECK-MESSAGES: [[@LINE-1]]:42: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+ AllocatorAwareClassAdlSwapWrongArgs tmp1(other, get_allocator());
+ AllocatorAwareClassAdlSwapWrongArgs tmp2(*this, get_allocator());
+ swap(tmp1, tmp2);
+ return *this;
+ }
+
+ allocator_type get_allocator() const {
+ return allocator_type();
+ }
+
+ friend void swap(AllocatorAwareClassAdlSwapWrongArgs&, AllocatorAwareClassAdlSwapWrongArgs&) {
+ }
+};
+
///////////////////////////////////////////////////////////////////
/// Test cases correctly ignored by the check.
@@ -540,6 +663,89 @@ public:
Uy *getUy() const { return Ptr2; }
};
+// Support "extended" copy/move constructors
+class AllocatorAwareClass {
+ // pointer member to trigger bugprone-unhandled-self-assignment
+ void *foo = nullptr;
+
+ public:
+ using allocator_type = std::pmr::allocator<>;
+
+ AllocatorAwareClass(const AllocatorAwareClass& other) {
+ }
+
+ AllocatorAwareClass(const AllocatorAwareClass& other, const allocator_type& alloc) {
+ }
+
+ AllocatorAwareClass& operator=(const AllocatorAwareClass& other) {
+ AllocatorAwareClass tmp(other, get_allocator());
+ swap(tmp);
+ return *this;
+ }
+
+ void swap(AllocatorAwareClass& other) noexcept {
+ }
+
+ allocator_type get_allocator() const {
+ return allocator_type();
+ }
+};
+
+// Support "extended" copy/move constructors + std::swap
+class AllocatorAwareClassStdSwap {
+ // pointer member to trigger bugprone-unhandled-self-assignment
+ void *foo = nullptr;
+
+ public:
+ using allocator_type = std::pmr::allocator<>;
+
+ AllocatorAwareClassStdSwap(const AllocatorAwareClassStdSwap& other) {
+ }
+
+ AllocatorAwareClassStdSwap(const AllocatorAwareClassStdSwap& other, const allocator_type& alloc) {
+ }
+
+ AllocatorAwareClassStdSwap& operator=(const AllocatorAwareClassStdSwap& other) {
+ using std::swap;
+
+ AllocatorAwareClassStdSwap tmp(other, get_allocator());
+ swap(*this, tmp);
+ return *this;
+ }
+
+ allocator_type get_allocator() const {
+ return allocator_type();
+ }
+};
+
+// Support "extended" copy/move constructors + ADL swap
+class AllocatorAwareClassAdlSwap {
+ // pointer member to trigger bugprone-unhandled-self-assignment
+ void *foo = nullptr;
+
+ public:
+ using allocator_type = std::pmr::allocator<>;
+
+ AllocatorAwareClassAdlSwap(const AllocatorAwareClassAdlSwap& other) {
+ }
+
+ AllocatorAwareClassAdlSwap(const AllocatorAwareClassAdlSwap& other, const allocator_type& alloc) {
+ }
+
+ AllocatorAwareClassAdlSwap& operator=(const AllocatorAwareClassAdlSwap& other) {
+ AllocatorAwareClassAdlSwap tmp(other, get_allocator());
+ swap(*this, tmp);
+ return *this;
+ }
+
+ allocator_type get_allocator() const {
+ return allocator_type();
+ }
+
+ friend void swap(AllocatorAwareClassAdlSwap&, AllocatorAwareClassAdlSwap&) {
+ }
+};
+
///////////////////////////////////////////////////////////////////
/// Test cases which should be caught by the check.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-new-mlir-op-builder.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-new-mlir-op-builder.cpp
new file mode 100644
index 0000000..0971a16
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-new-mlir-op-builder.cpp
@@ -0,0 +1,76 @@
+// RUN: %check_clang_tidy --match-partial-fixes %s llvm-use-new-mlir-op-builder %t
+
+namespace mlir {
+class Location {};
+class OpBuilder {
+public:
+ template <typename OpTy, typename... Args>
+ OpTy create(Location location, Args &&...args) {
+ return OpTy(args...);
+ }
+ Location getUnknownLoc() { return Location(); }
+};
+class ImplicitLocOpBuilder : public OpBuilder {
+public:
+ template <typename OpTy, typename... Args>
+ OpTy create(Args &&...args) {
+ return OpTy(args...);
+ }
+};
+struct ModuleOp {
+ ModuleOp() {}
+ static ModuleOp create(OpBuilder &builder, Location location) {
+ return ModuleOp();
+ }
+};
+struct NamedOp {
+ NamedOp(const char* name) {}
+ static NamedOp create(OpBuilder &builder, Location location, const char* name) {
+ return NamedOp(name);
+ }
+};
+} // namespace mlir
+
+#define ASSIGN(A, B, C, D) C A = B.create<C>(B.getUnknownLoc(), D)
+
+template <typename T>
+void g(mlir::OpBuilder &b) {
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use 'OpType::create(builder, ...)' instead of 'builder.create<OpType>(...)' [llvm-use-new-mlir-op-builder]
+ // CHECK-FIXES: T::create(b, b.getUnknownLoc(), "gaz")
+ b.create<T>(b.getUnknownLoc(), "gaz");
+}
+
+void f() {
+ mlir::OpBuilder builder;
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use 'OpType::create(builder, ...)' instead of 'builder.create<OpType>(...)' [llvm-use-new-mlir-op-builder]
+ // CHECK-FIXES: mlir:: ModuleOp::create(builder, builder.getUnknownLoc())
+ builder.create<mlir:: ModuleOp>(builder.getUnknownLoc());
+
+ using mlir::NamedOp;
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use 'OpType::create(builder, ...)' instead of 'builder.create<OpType>(...)' [llvm-use-new-mlir-op-builder]
+ // CHECK-FIXES: NamedOp::create(builder, builder.getUnknownLoc(), "baz")
+ builder.create<NamedOp>(builder.getUnknownLoc(), "baz");
+
+ // CHECK-MESSAGES: :[[@LINE+4]]:3: warning: use 'OpType::create(builder, ...)' instead of 'builder.create<OpType>(...)' [llvm-use-new-mlir-op-builder]
+ // CHECK-FIXES: NamedOp::create(builder,
+ // CHECK-FIXES: builder.getUnknownLoc(),
+ // CHECK-FIXES: "caz")
+ builder.
+ create<NamedOp>(
+ builder.getUnknownLoc(),
+ "caz");
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use 'OpType::create(builder, ...)' instead of 'builder.create<OpType>(...)' [llvm-use-new-mlir-op-builder]
+ ASSIGN(op, builder, NamedOp, "daz");
+
+ g<NamedOp>(builder);
+
+ mlir::ImplicitLocOpBuilder ib;
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use 'OpType::create(builder, ...)' instead of 'builder.create<OpType>(...)' [llvm-use-new-mlir-op-builder]
+ // CHECK-FIXES: mlir::ModuleOp::create(ib)
+ ib.create<mlir::ModuleOp>( );
+
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use 'OpType::create(builder, ...)' instead of 'builder.create<OpType>(...)' [llvm-use-new-mlir-op-builder]
+ // CHECK-FIXES: mlir::OpBuilder().create<mlir::ModuleOp>(builder.getUnknownLoc());
+ mlir::OpBuilder().create<mlir::ModuleOp>(builder.getUnknownLoc());
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/header-include-cycle.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/header-include-cycle.cpp
index d3c71ad..3694bdd 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/header-include-cycle.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/header-include-cycle.cpp
@@ -1,15 +1,15 @@
-// RUN: rm -rf %T/misc-header-include-cycle-headers
-// RUN: mkdir %T/misc-header-include-cycle-headers
-// RUN: cp -r %S/Inputs/header-include-cycle* %T/misc-header-include-cycle-headers/
-// RUN: mkdir %T/misc-header-include-cycle-headers/system
-// RUN: cp -r %S/Inputs/system/header-include-cycle* %T/misc-header-include-cycle-headers/system
-// RUN: cp %s %T/header-include-cycle.cpp
-// RUN: clang-tidy %T%{fs-sep}header-include-cycle.cpp -checks='-*,misc-header-include-cycle' -header-filter=.* \
+// RUN: rm -rf %t.dir/misc-header-include-cycle-headers
+// RUN: mkdir -p %t.dir/misc-header-include-cycle-headers
+// RUN: cp -r %S/Inputs/header-include-cycle* %t.dir/misc-header-include-cycle-headers/
+// RUN: mkdir %t.dir/misc-header-include-cycle-headers/system
+// RUN: cp -r %S/Inputs/system/header-include-cycle* %t.dir/misc-header-include-cycle-headers/system
+// RUN: cp %s %t.dir/header-include-cycle.cpp
+// RUN: clang-tidy %t.dir%{fs-sep}header-include-cycle.cpp -checks='-*,misc-header-include-cycle' -header-filter=.* \
// RUN: -config="{CheckOptions: {misc-header-include-cycle.IgnoredFilesList: 'header-include-cycle.self-e.hpp'}}" \
-// RUN: -- -I%T%{fs-sep}misc-header-include-cycle-headers -isystem %T%{fs-sep}misc-header-include-cycle-headers%{fs-sep}system \
-// RUN: --include %T%{fs-sep}misc-header-include-cycle-headers%{fs-sep}header-include-cycle.self-i.hpp | FileCheck %s \
+// RUN: -- -I%t.dir%{fs-sep}misc-header-include-cycle-headers -isystem %t.dir%{fs-sep}misc-header-include-cycle-headers%{fs-sep}system \
+// RUN: --include %t.dir%{fs-sep}misc-header-include-cycle-headers%{fs-sep}header-include-cycle.self-i.hpp | FileCheck %s \
// RUN: -check-prefix=CHECK-MESSAGES "-implicit-check-not={{note|warning|error}}:" --dump-input=fail
-// RUN: rm -rf %T/misc-header-include-cycle-headers
+// RUN: rm -rf %t.dir/misc-header-include-cycle-headers
#ifndef MAIN_GUARD
#define MAIN_GUARD
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/unused-parameters.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/unused-parameters.cpp
index f1918e9..c963cb5 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/unused-parameters.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/unused-parameters.cpp
@@ -1,11 +1,11 @@
-// RUN: echo "static void staticFunctionHeader(int i) {;}" > %T/header.h
-// RUN: echo "static void staticFunctionHeader(int /*i*/) {;}" > %T/header-fixed.h
-// RUN: %check_clang_tidy --match-partial-fixes -std=c++11 %s misc-unused-parameters %t -- -header-filter='.*' -- -fno-delayed-template-parsing
-// RUN: diff %T/header.h %T/header-fixed.h
+// RUN: mkdir -p %t.dir
+// RUN: echo "static void staticFunctionHeader(int i) {;}" > %t.dir/header.h
+// RUN: echo "static void staticFunctionHeader(int /*i*/) {;}" > %t.dir/header-fixed.h
+// RUN: %check_clang_tidy --match-partial-fixes -std=c++11 %s misc-unused-parameters %t.dir/code -- -header-filter='.*' -- -fno-delayed-template-parsing
+// RUN: diff %t.dir/header.h %t.dir/header-fixed.h
// FIXME: Make the test work in all language modes.
#include "header.h"
-// CHECK-MESSAGES: header.h:1:38: warning
// Basic removal
// =============
@@ -306,3 +306,5 @@ void test() {
// Do not warn on naked functions.
[[gnu::naked]] int nakedFunction(int a, float b, const char *c) { ; }
__attribute__((naked)) void nakedFunction(int a, int b) { ; }
+
+// CHECK-MESSAGES: header.h:1:38: warning
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/concat-nested-namespaces.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/concat-nested-namespaces.cpp
index a4f50dd..78adbeb 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/concat-nested-namespaces.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/concat-nested-namespaces.cpp
@@ -1,10 +1,11 @@
-// RUN: cp %S/Inputs/concat-nested-namespaces/modernize-concat-nested-namespaces.h %T/modernize-concat-nested-namespaces.h
-// RUN: %check_clang_tidy --match-partial-fixes -std=c++17 -check-suffix=NORMAL %s modernize-concat-nested-namespaces %t -- -header-filter=".*" -- -I %T
-// RUN: FileCheck -input-file=%T/modernize-concat-nested-namespaces.h %S/Inputs/concat-nested-namespaces/modernize-concat-nested-namespaces.h -check-prefix=CHECK-FIXES
+// RUN: mkdir -p %t.dir
+// RUN: cp %S/Inputs/concat-nested-namespaces/modernize-concat-nested-namespaces.h %t.dir/modernize-concat-nested-namespaces.h
+// RUN: %check_clang_tidy --match-partial-fixes -std=c++17 -check-suffix=NORMAL %s modernize-concat-nested-namespaces %t.dir/code -- -header-filter=".*" -- -I %t.dir
+// RUN: FileCheck -input-file=%t.dir/modernize-concat-nested-namespaces.h %S/Inputs/concat-nested-namespaces/modernize-concat-nested-namespaces.h -check-prefix=CHECK-FIXES
// Restore header file and re-run with c++20:
-// RUN: cp %S/Inputs/concat-nested-namespaces/modernize-concat-nested-namespaces.h %T/modernize-concat-nested-namespaces.h
-// RUN: %check_clang_tidy --match-partial-fixes -std=c++20 -check-suffixes=NORMAL,CPP20 %s modernize-concat-nested-namespaces %t -- -header-filter=".*" -- -I %T
-// RUN: FileCheck -input-file=%T/modernize-concat-nested-namespaces.h %S/Inputs/concat-nested-namespaces/modernize-concat-nested-namespaces.h -check-prefix=CHECK-FIXES
+// RUN: cp %S/Inputs/concat-nested-namespaces/modernize-concat-nested-namespaces.h %t.dir/modernize-concat-nested-namespaces.h
+// RUN: %check_clang_tidy --match-partial-fixes -std=c++20 -check-suffixes=NORMAL,CPP20 %s modernize-concat-nested-namespaces %t.dir/code -- -header-filter=".*" -- -I %t.dir
+// RUN: FileCheck -input-file=%t.dir/modernize-concat-nested-namespaces.h %S/Inputs/concat-nested-namespaces/modernize-concat-nested-namespaces.h -check-prefix=CHECK-FIXES
#include "modernize-concat-nested-namespaces.h"
// CHECK-MESSAGES-NORMAL-DAG: modernize-concat-nested-namespaces.h:1:1: warning: nested namespaces can be concatenated [modernize-concat-nested-namespaces]
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/pass-by-value-header.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/pass-by-value-header.cpp
index 5d2f1af..461a637 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/pass-by-value-header.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/pass-by-value-header.cpp
@@ -1,6 +1,7 @@
-// RUN: cp %S/Inputs/pass-by-value/header.h %T/pass-by-value-header.h
-// RUN: clang-tidy %s -checks='-*,modernize-pass-by-value' -header-filter='.*' -fix -- -std=c++11 -I %T | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not="{{warning|error}}:"
-// RUN: FileCheck -input-file=%T/pass-by-value-header.h %s -check-prefix=CHECK-FIXES
+// RUN: mkdir -p %t.dir
+// RUN: cp %S/Inputs/pass-by-value/header.h %t.dir/pass-by-value-header.h
+// RUN: clang-tidy %s -checks='-*,modernize-pass-by-value' -header-filter='.*' -fix -- -std=c++11 -I %t.dir | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not="{{warning|error}}:"
+// RUN: FileCheck -input-file=%t.dir/pass-by-value-header.h %s -check-prefix=CHECK-FIXES
// FIXME: Make the test work in all language modes.
#include "pass-by-value-header.h"
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/pass-by-value-multi-fixes.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/pass-by-value-multi-fixes.cpp
index 238e445..b77c74b 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/pass-by-value-multi-fixes.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/pass-by-value-multi-fixes.cpp
@@ -1,12 +1,13 @@
-// RUN: cat %S/Inputs/pass-by-value/header-with-fix.h > %T/pass-by-value-header-with-fix.h
-// RUN: sed -e 's#//.*$##' %s > %t.cpp
-// RUN: clang-tidy %t.cpp -checks='-*,modernize-pass-by-value' -header-filter='.*' -fix -- -std=c++11 -I %T | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not="{{warning|error}}:"
-// RUN: FileCheck -input-file=%t.cpp %s -check-prefix=CHECK-FIXES
-// RUN: FileCheck -input-file=%T/pass-by-value-header-with-fix.h %s -check-prefix=CHECK-HEADER-FIXES
+// RUN: mkdir -p %t.dir
+// RUN: cat %S/Inputs/pass-by-value/header-with-fix.h > %t.dir/pass-by-value-header-with-fix.h
+// RUN: sed -e 's#//.*$##' %s > %t.dir/code.cpp
+// RUN: clang-tidy %t.dir/code.cpp -checks='-*,modernize-pass-by-value' -header-filter='.*' -fix -- -std=c++11 -I %t.dir | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not="{{warning|error}}:"
+// RUN: FileCheck -input-file=%t.dir/code.cpp %s -check-prefix=CHECK-FIXES
+// RUN: FileCheck -input-file=%t.dir/pass-by-value-header-with-fix.h %s -check-prefix=CHECK-HEADER-FIXES
#include "pass-by-value-header-with-fix.h"
// CHECK-HEADER-FIXES: Foo(S s);
Foo::Foo(const S &s) : s(s) {}
-// CHECK-MESSAGES: :9:10: warning: pass by value and use std::move [modernize-pass-by-value]
+// CHECK-MESSAGES: :10:10: warning: pass by value and use std::move [modernize-pass-by-value]
// CHECK-FIXES: #include <utility>
// CHECK-FIXES: Foo::Foo(S s) : s(std::move(s)) {}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp
index cdadeed..88e0636 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp
@@ -224,3 +224,55 @@ std::array a{1,2,3};
std::array<int,2> b{10, 11};
using array = std::array<int, 2>;
array c{10, 11};
+
+struct S16 {
+ int a;
+ int b;
+};
+
+using S17 = S16;
+
+S17 s171{1, 2};
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use designated initializer list to initialize 'S17' (aka 'S16') [modernize-use-designated-initializers]
+// CHECK-MESSAGES: :[[@LINE-9]]:1: note: aggregate type is defined here
+// CHECK-FIXES: S17 s171{.a=1, .b=2};
+// CHECK-MESSAGES-POD: :[[@LINE-4]]:9: warning: use designated initializer list to initialize 'S17' (aka 'S16') [modernize-use-designated-initializers]
+// CHECK-MESSAGES-POD: :[[@LINE-12]]:1: note: aggregate type is defined here
+// CHECK-FIXES-POD: S17 s171{.a=1, .b=2};
+
+S17 s172{.a=1, 2};
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use designated init expression to initialize field 'b' [modernize-use-designated-initializers]
+// CHECK-MESSAGES-POD: :[[@LINE-2]]:16: warning: use designated init expression to initialize field 'b' [modernize-use-designated-initializers]
+// CHECK-FIXES: S17 s172{.a=1, .b=2};
+
+S17 s173{.a=1, .b=2}; // no issue
+
+typedef S16 S18;
+
+S18 s181{1, 2};
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use designated initializer list to initialize 'S18' (aka 'S16') [modernize-use-designated-initializers]
+// CHECK-MESSAGES-POD: :[[@LINE-2]]:9: warning: use designated initializer list to initialize 'S18' (aka 'S16') [modernize-use-designated-initializers]
+
+S18 s182{1, .b=2};
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use designated init expression to initialize field 'a' [modernize-use-designated-initializers]
+// CHECK-MESSAGES-POD: :[[@LINE-2]]:10: warning: use designated init expression to initialize field 'a' [modernize-use-designated-initializers]
+// CHECK-FIXES: S18 s182{.a=1, .b=2};
+
+S18 s183{.a=1, .b=2}; // no issue
+
+struct S19 {
+ int i;
+ S17 s17;
+ S18 s18;
+};
+
+S19 s191{1, {2, .b=3}, {4, 5}};
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use designated initializer list to initialize 'S19' [modernize-use-designated-initializers]
+// CHECK-MESSAGES: :[[@LINE-8]]:1: note: aggregate type is defined here
+// CHECK-MESSAGES: :[[@LINE-3]]:14: warning: use designated init expression to initialize field 'a' [modernize-use-designated-initializers]
+// CHECK-MESSAGES: :[[@LINE-4]]:24: warning: use designated initializer list to initialize 'S18' (aka 'S16') [modernize-use-designated-initializers]
+// CHECK-MESSAGES-POD: :[[@LINE-5]]:9: warning: use designated initializer list to initialize 'S19' [modernize-use-designated-initializers]
+// CHECK-MESSAGES-POD: :[[@LINE-12]]:1: note: aggregate type is defined here
+// CHECK-MESSAGES-POD: :[[@LINE-7]]:14: warning: use designated init expression to initialize field 'a' [modernize-use-designated-initializers]
+// CHECK-MESSAGES-POD: :[[@LINE-8]]:24: warning: use designated initializer list to initialize 'S18' (aka 'S16') [modernize-use-designated-initializers]
+// CHECK-FIXES: S19 s191{.i=1, .s17={.a=2, .b=3}, .s18={.a=4, .b=5}};
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp
index 7da0bb0..0f3458e 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp
@@ -2,7 +2,7 @@
// RUN: -std=c++20 %s modernize-use-std-format %t -- \
// RUN: -config="{CheckOptions: { \
// RUN: modernize-use-std-format.StrictMode: true, \
-// RUN: modernize-use-std-format.StrFormatLikeFunctions: '::strprintf; mynamespace::strprintf2; bad_format_type_strprintf', \
+// RUN: modernize-use-std-format.StrFormatLikeFunctions: '::strprintf; mynamespace::strprintf2; any_format_type_strprintf', \
// RUN: modernize-use-std-format.ReplacementFormatFunction: 'fmt::format', \
// RUN: modernize-use-std-format.FormatHeader: '<fmt/core.h>' \
// RUN: }}" \
@@ -10,7 +10,7 @@
// RUN: %check_clang_tidy -check-suffixes=,NOTSTRICT \
// RUN: -std=c++20 %s modernize-use-std-format %t -- \
// RUN: -config="{CheckOptions: { \
-// RUN: modernize-use-std-format.StrFormatLikeFunctions: '::strprintf; mynamespace::strprintf2; bad_format_type_strprintf', \
+// RUN: modernize-use-std-format.StrFormatLikeFunctions: '::strprintf; mynamespace::strprintf2; any_format_type_strprintf', \
// RUN: modernize-use-std-format.ReplacementFormatFunction: 'fmt::format', \
// RUN: modernize-use-std-format.FormatHeader: '<fmt/core.h>' \
// RUN: }}" \
@@ -56,12 +56,17 @@ std::string A(const std::string &in)
struct S {
S(...);
};
-std::string bad_format_type_strprintf(const S &, ...);
+std::string any_format_type_strprintf(const S &, ...);
-std::string unsupported_format_parameter_type()
+void unsupported_format_parameter_types()
{
// No fixes here because the format parameter of the function called is not a
// string.
- return bad_format_type_strprintf("");
-// CHECK-MESSAGES: [[@LINE-1]]:10: warning: unable to use 'fmt::format' instead of 'bad_format_type_strprintf' because first argument is not a narrow string literal [modernize-use-std-format]
+ auto s1 = any_format_type_strprintf(L"");
+ auto s2 = any_format_type_strprintf(42);
+
+ // But if we do pass a character string then that ought to be acceptable.
+ auto s3 = any_format_type_strprintf("Hello %s", "world");
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'fmt::format' instead of 'any_format_type_strprintf' [modernize-use-std-format]
+ // CHECK-FIXES: auto s3 = fmt::format("Hello {}", "world");
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
index 1a241e3..ea97d5b 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
@@ -16,8 +16,8 @@
namespace absl
{
-template <typename S, typename... Args>
-std::string StrFormat(const S &format, const Args&... args);
+template <typename... Args>
+std::string StrFormat(const std::string_view &format, const Args&... args);
} // namespace absl
template <typename T>
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-absl.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-absl.cpp
index 83fbd2e..3dab6e9 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-absl.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-absl.cpp
@@ -9,15 +9,15 @@
#include <cstdio>
#include <string.h>
+#include <string>
namespace absl
{
-// Use const char * for the format since the real type is hard to mock up.
template <typename... Args>
-int PrintF(const char *format, const Args&... args);
+int PrintF(const std::string_view &format, const Args&... args);
template <typename... Args>
-int FPrintF(FILE* output, const char *format, const Args&... args);
+int FPrintF(FILE* output, const std::string_view &format, const Args&... args);
}
void printf_simple() {
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
index 687b8c0..2c6a651 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
@@ -1,8 +1,8 @@
// RUN: %check_clang_tidy -std=c++23 %s modernize-use-std-print %t -- \
// RUN: -config="{CheckOptions: \
// RUN: { \
-// RUN: modernize-use-std-print.PrintfLikeFunctions: 'unqualified_printf;::myprintf; mynamespace::myprintf2; bad_format_type_printf; fmt::printf', \
-// RUN: modernize-use-std-print.FprintfLikeFunctions: '::myfprintf; mynamespace::myfprintf2; bad_format_type_fprintf; fmt::fprintf' \
+// RUN: modernize-use-std-print.PrintfLikeFunctions: 'unqualified_printf;::myprintf; mynamespace::myprintf2; any_format_type_printf; fmt::printf', \
+// RUN: modernize-use-std-print.FprintfLikeFunctions: '::myfprintf; mynamespace::myfprintf2; any_format_type_fprintf; fmt::fprintf' \
// RUN: } \
// RUN: }" \
// RUN: -- -isystem %clang_tidy_headers
@@ -98,18 +98,25 @@ void wide_string_not_supported() {
struct S {
S(...) {}
};
-int bad_format_type_printf(const S &, ...);
-int bad_format_type_fprintf(FILE *, const S &, ...);
+int any_format_type_printf(const S &, ...);
+int any_format_type_fprintf(FILE *, const S &, ...);
void unsupported_format_parameter_type()
{
// No fixes here because the format parameter of the function called is not a
// string.
- bad_format_type_printf("Hello %s", "world");
-// CHECK-MESSAGES: [[@LINE-1]]:3: warning: unable to use 'std::print' instead of 'bad_format_type_printf' because first argument is not a narrow string literal [modernize-use-std-print]
-
- bad_format_type_fprintf(stderr, "Hello %s", "world");
-// CHECK-MESSAGES: [[@LINE-1]]:3: warning: unable to use 'std::print' instead of 'bad_format_type_fprintf' because first argument is not a narrow string literal [modernize-use-std-print]
+ any_format_type_printf(L"Hello %s", "world");
+ any_format_type_fprintf(stderr, L"Hello %s", "world");
+ any_format_type_printf(42);
+ any_format_type_fprintf(stderr, 42L);
+
+ // But if we do pass a character string then that ought to be acceptable.
+ any_format_type_printf("Hello %s\n", "world");
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'any_format_type_printf' [modernize-use-std-print]
+ // CHECK-FIXES: std::println("Hello {}", "world");
+ any_format_type_fprintf(stderr, "Hello %s\n", "world");
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'any_format_type_fprintf' [modernize-use-std-print]
+ // CHECK-FIXES: std::println(stderr, "Hello {}", "world");
}
namespace fmt {
diff --git a/clang-tools-extra/test/clang-tidy/checkers/portability/restrict-system-includes-transitive.cpp b/clang-tools-extra/test/clang-tidy/checkers/portability/restrict-system-includes-transitive.cpp
index 744f45f..ff7c66b 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/portability/restrict-system-includes-transitive.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/portability/restrict-system-includes-transitive.cpp
@@ -1,12 +1,12 @@
-// RUN: rm -rf %T/Headers
-// RUN: mkdir %T/Headers
-// RUN: cp -r %S/Inputs/restrict-system-includes %T/Headers/portability-restrict-system-includes
+// RUN: rm -rf %t.dir/Headers
+// RUN: mkdir -p %t.dir/Headers
+// RUN: cp -r %S/Inputs/restrict-system-includes %t.dir/Headers/portability-restrict-system-includes
// RUN: %check_clang_tidy -std=c++11 %s portability-restrict-system-includes %t \
// RUN: -- -config="{CheckOptions: {portability-restrict-system-includes.Includes: 'transitive.h,s.h'}}" \
// RUN: -system-headers -header-filter=.* \
-// RUN: -- -I %T/Headers/portability-restrict-system-includes -isystem %T/Headers/portability-restrict-system-includes/system
-// RUN: FileCheck -input-file=%T/Headers/portability-restrict-system-includes/transitive2.h %s -check-prefix=CHECK-FIXES
-// RUN: rm -rf %T/Headers
+// RUN: -- -I %t.dir/Headers/portability-restrict-system-includes -isystem %t.dir/Headers/portability-restrict-system-includes/system
+// RUN: FileCheck -input-file=%t.dir/Headers/portability-restrict-system-includes/transitive2.h %s -check-prefix=CHECK-FIXES
+// RUN: rm -rf %t.dir/Headers
// FIXME: Make the test work in all language modes.
// transitive.h includes <r.h> and <t.h>
diff --git a/clang-tools-extra/test/clang-tidy/checkers/portability/template-virtual-member-function.cpp b/clang-tools-extra/test/clang-tidy/checkers/portability/template-virtual-member-function.cpp
index 94786ae..2a67b79 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/portability/template-virtual-member-function.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/portability/template-virtual-member-function.cpp
@@ -171,3 +171,20 @@ struct NoInstantiation<int, U>{
};
};
} // namespace PartialSpecializationNoInstantiation
+
+namespace PureVirtual {
+
+template<typename T>
+struct Base {
+ virtual void foo() = 0;
+};
+
+struct Derived : public Base<int> {
+ void foo() {}
+};
+
+void test() {
+ Derived{}.foo();
+}
+
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-symlink.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-symlink.cpp
index 34dc340..7c99f70 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-symlink.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-symlink.cpp
@@ -2,11 +2,12 @@
// in the header file so it fails if runs multiple times with different
// `-std` flags as check_clang_tidy doesn by default.
//
-// RUN: rm -rf %T/symlink
-// RUN: cp -r %S/Inputs/identifier-naming/symlink %T/symlink
-// RUN: mkdir -p %T/symlink/build
-// RUN: ln -s %T/symlink/include/test.h %T/symlink/build/test.h
-// RUN: %check_clang_tidy -std=c++20 %s readability-identifier-naming %t -- --header-filter="test.h" --config-file=%S/Inputs/identifier-naming/symlink/include/.clang-tidy -- -I %T/symlink/build
+// RUN: rm -rf %t.dir
+// RUN: mkdir -p %t.dir
+// RUN: cp -r %S/Inputs/identifier-naming/symlink %t.dir/symlink
+// RUN: mkdir -p %t.dir/symlink/build
+// RUN: ln -s %t.dir/symlink/include/test.h %t.dir/symlink/build/test.h
+// RUN: %check_clang_tidy -std=c++20 %s readability-identifier-naming %t.dir -- --header-filter="test.h" --config-file=%S/Inputs/identifier-naming/symlink/include/.clang-tidy -- -I %t.dir/symlink/build
// UNSUPPORTED: system-windows
#include "test.h"
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto.cpp
index 77afdca..83b7b1d 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto.cpp
@@ -2,6 +2,11 @@
// RUN: -config='{CheckOptions: { \
// RUN: readability-qualified-auto.AllowedTypes: "[iI]terator$;my::ns::Ignored1;std::array<.*>::Ignored2;MyIgnoredPtr" \
// RUN: }}'
+// RUN: %check_clang_tidy %s readability-qualified-auto %t \
+// RUN: -config='{CheckOptions: { \
+// RUN: readability-qualified-auto.AllowedTypes: "[iI]terator$;my::ns::Ignored1;std::array<.*>::Ignored2;MyIgnoredPtr", \
+// RUN: readability-qualified-auto.IgnoreAliasing: false \
+// RUN: }}' -check-suffix=ALIAS --
namespace typedefs {
typedef int *MyPtr;
@@ -10,22 +15,36 @@ typedef const int *CMyPtr;
typedef const int &CMyRef;
MyPtr getPtr();
+MyPtr* getPtrPtr();
MyRef getRef();
CMyPtr getCPtr();
+CMyPtr* getCPtrPtr();
CMyRef getCRef();
void foo() {
auto TdNakedPtr = getPtr();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto TdNakedPtr' can be declared as 'auto *TdNakedPtr'
// CHECK-FIXES: {{^}} auto *TdNakedPtr = getPtr();
+ auto TdNakedPtrPtr = getPtrPtr();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto TdNakedPtrPtr' can be declared as 'auto *TdNakedPtrPtr'
+ // CHECK-FIXES: {{^}} auto *TdNakedPtrPtr = getPtrPtr();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto TdNakedPtrPtr' can be declared as 'auto *TdNakedPtrPtr'
+ // CHECK-FIXES-ALIAS: {{^}} auto *TdNakedPtrPtr = getPtrPtr();
auto &TdNakedRef = getRef();
auto TdNakedRefDeref = getRef();
auto TdNakedCPtr = getCPtr();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto TdNakedCPtr' can be declared as 'const auto *TdNakedCPtr'
// CHECK-FIXES: {{^}} const auto *TdNakedCPtr = getCPtr();
+ auto TdNakedCPtrPtr = getCPtrPtr();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto TdNakedCPtrPtr' can be declared as 'auto *TdNakedCPtrPtr'
+ // CHECK-FIXES: {{^}} auto *TdNakedCPtrPtr = getCPtrPtr();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto TdNakedCPtrPtr' can be declared as 'auto *TdNakedCPtrPtr'
+ // CHECK-FIXES-ALIAS: {{^}} auto *TdNakedCPtrPtr = getCPtrPtr();
auto &TdNakedCRef = getCRef();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto &TdNakedCRef' can be declared as 'const auto &TdNakedCRef'
// CHECK-FIXES: {{^}} const auto &TdNakedCRef = getCRef();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto &TdNakedCRef' can be declared as 'const auto &TdNakedCRef'
+ // CHECK-FIXES-ALIAS: {{^}} const auto &TdNakedCRef = getCRef();
auto TdNakedCRefDeref = getCRef();
}
@@ -38,6 +57,7 @@ using CMyPtr = const int *;
using CMyRef = const int &;
MyPtr getPtr();
+MyPtr* getPtrPtr();
MyRef getRef();
CMyPtr getCPtr();
CMyRef getCRef();
@@ -46,6 +66,11 @@ void foo() {
auto UNakedPtr = getPtr();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto UNakedPtr' can be declared as 'auto *UNakedPtr'
// CHECK-FIXES: {{^}} auto *UNakedPtr = getPtr();
+ auto UNakedPtrPtr = getPtrPtr();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto UNakedPtrPtr' can be declared as 'auto *UNakedPtrPtr'
+ // CHECK-FIXES: {{^}} auto *UNakedPtrPtr = getPtrPtr();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto UNakedPtrPtr' can be declared as 'auto *UNakedPtrPtr'
+ // CHECK-FIXES-ALIAS: {{^}} auto *UNakedPtrPtr = getPtrPtr();
auto &UNakedRef = getRef();
auto UNakedRefDeref = getRef();
auto UNakedCPtr = getCPtr();
@@ -54,6 +79,8 @@ void foo() {
auto &UNakedCRef = getCRef();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto &UNakedCRef' can be declared as 'const auto &UNakedCRef'
// CHECK-FIXES: {{^}} const auto &UNakedCRef = getCRef();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto &UNakedCRef' can be declared as 'const auto &UNakedCRef'
+ // CHECK-FIXES-ALIAS: {{^}} const auto &UNakedCRef = getCRef();
auto UNakedCRefDeref = getCRef();
}
@@ -77,45 +104,67 @@ void foo() {
auto NakedPtr = getIntPtr();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto NakedPtr' can be declared as 'auto *NakedPtr'
// CHECK-FIXES: {{^}} auto *NakedPtr = getIntPtr();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto NakedPtr' can be declared as 'auto *NakedPtr'
+ // CHECK-FIXES-ALIAS: {{^}} auto *NakedPtr = getIntPtr();
auto NakedCPtr = getCIntPtr();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto NakedCPtr' can be declared as 'const auto *NakedCPtr'
// CHECK-FIXES: {{^}} const auto *NakedCPtr = getCIntPtr();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto NakedCPtr' can be declared as 'const auto *NakedCPtr'
+ // CHECK-FIXES-ALIAS: {{^}} const auto *NakedCPtr = getCIntPtr();
const auto ConstPtr = getIntPtr();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'const auto ConstPtr' can be declared as 'auto *const ConstPtr'
// CHECK-FIXES: {{^}} auto *const ConstPtr = getIntPtr();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'const auto ConstPtr' can be declared as 'auto *const ConstPtr'
+ // CHECK-FIXES-ALIAS: {{^}} auto *const ConstPtr = getIntPtr();
const auto ConstCPtr = getCIntPtr();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'const auto ConstCPtr' can be declared as 'const auto *const ConstCPtr'
// CHECK-FIXES: {{^}} const auto *const ConstCPtr = getCIntPtr();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'const auto ConstCPtr' can be declared as 'const auto *const ConstCPtr'
+ // CHECK-FIXES-ALIAS: {{^}} const auto *const ConstCPtr = getCIntPtr();
volatile auto VolatilePtr = getIntPtr();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'volatile auto VolatilePtr' can be declared as 'auto *volatile VolatilePtr'
// CHECK-FIXES: {{^}} auto *volatile VolatilePtr = getIntPtr();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'volatile auto VolatilePtr' can be declared as 'auto *volatile VolatilePtr'
+ // CHECK-FIXES-ALIAS: {{^}} auto *volatile VolatilePtr = getIntPtr();
volatile auto VolatileCPtr = getCIntPtr();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'volatile auto VolatileCPtr' can be declared as 'const auto *volatile VolatileCPtr'
// CHECK-FIXES: {{^}} const auto *volatile VolatileCPtr = getCIntPtr();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'volatile auto VolatileCPtr' can be declared as 'const auto *volatile VolatileCPtr'
+ // CHECK-FIXES-ALIAS: {{^}} const auto *volatile VolatileCPtr = getCIntPtr();
auto *QualPtr = getIntPtr();
auto *QualCPtr = getCIntPtr();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto *QualCPtr' can be declared as 'const auto *QualCPtr'
// CHECK-FIXES: {{^}} const auto *QualCPtr = getCIntPtr();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto *QualCPtr' can be declared as 'const auto *QualCPtr'
+ // CHECK-FIXES-ALIAS: {{^}} const auto *QualCPtr = getCIntPtr();
auto *const ConstantQualCPtr = getCIntPtr();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto *const ConstantQualCPtr' can be declared as 'const auto *const ConstantQualCPtr'
// CHECK-FIXES: {{^}} const auto *const ConstantQualCPtr = getCIntPtr();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto *const ConstantQualCPtr' can be declared as 'const auto *const ConstantQualCPtr'
+ // CHECK-FIXES-ALIAS: {{^}} const auto *const ConstantQualCPtr = getCIntPtr();
auto *volatile VolatileQualCPtr = getCIntPtr();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto *volatile VolatileQualCPtr' can be declared as 'const auto *volatile VolatileQualCPtr'
// CHECK-FIXES: {{^}} const auto *volatile VolatileQualCPtr = getCIntPtr();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto *volatile VolatileQualCPtr' can be declared as 'const auto *volatile VolatileQualCPtr'
+ // CHECK-FIXES-ALIAS: {{^}} const auto *volatile VolatileQualCPtr = getCIntPtr();
const auto *ConstQualCPtr = getCIntPtr();
auto &Ref = *getIntPtr();
auto &CRef = *getCIntPtr();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto &CRef' can be declared as 'const auto &CRef'
// CHECK-FIXES: {{^}} const auto &CRef = *getCIntPtr();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto &CRef' can be declared as 'const auto &CRef'
+ // CHECK-FIXES-ALIAS: {{^}} const auto &CRef = *getCIntPtr();
const auto &ConstCRef = *getCIntPtr();
if (auto X = getCIntPtr()) {
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'auto X' can be declared as 'const auto *X'
// CHECK-FIXES: {{^}} if (const auto *X = getCIntPtr()) {
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:7: warning: 'auto X' can be declared as 'const auto *X'
+ // CHECK-FIXES-ALIAS: {{^}} if (const auto *X = getCIntPtr()) {
}
}
@@ -153,6 +202,8 @@ void loopRef(std::vector<int> &Mutate, const std::vector<int> &Constant) {
for (auto &Data : Constant) {
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto &Data' can be declared as 'const auto &Data'
// CHECK-FIXES: {{^}} for (const auto &Data : Constant) {
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:8: warning: 'auto &Data' can be declared as 'const auto &Data'
+ // CHECK-FIXES-ALIAS: {{^}} for (const auto &Data : Constant) {
observe(Data);
}
}
@@ -161,11 +212,15 @@ void loopPtr(const std::vector<int *> &Mutate, const std::vector<const int *> &C
for (auto Data : Mutate) {
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'auto *Data'
// CHECK-FIXES: {{^}} for (auto *Data : Mutate) {
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:8: warning: 'auto Data' can be declared as 'auto *Data'
+ // CHECK-FIXES-ALIAS: {{^}} for (auto *Data : Mutate) {
change(*Data);
}
for (auto Data : Constant) {
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'const auto *Data'
// CHECK-FIXES: {{^}} for (const auto *Data : Constant) {
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:8: warning: 'auto Data' can be declared as 'const auto *Data'
+ // CHECK-FIXES-ALIAS: {{^}} for (const auto *Data : Constant) {
observe(*Data);
}
}
@@ -175,12 +230,16 @@ void tempLoopPtr(std::vector<T *> &MutateTemplate, std::vector<const T *> &Const
for (auto Data : MutateTemplate) {
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'auto *Data'
// CHECK-FIXES: {{^}} for (auto *Data : MutateTemplate) {
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:8: warning: 'auto Data' can be declared as 'auto *Data'
+ // CHECK-FIXES-ALIAS: {{^}} for (auto *Data : MutateTemplate) {
change(*Data);
}
//FixMe
for (auto Data : ConstantTemplate) {
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'const auto *Data'
// CHECK-FIXES: {{^}} for (const auto *Data : ConstantTemplate) {
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:8: warning: 'auto Data' can be declared as 'const auto *Data'
+ // CHECK-FIXES-ALIAS: {{^}} for (const auto *Data : ConstantTemplate) {
observe(*Data);
}
}
@@ -192,12 +251,16 @@ public:
for (auto Data : MClassTemplate) {
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'auto Data' can be declared as 'auto *Data'
// CHECK-FIXES: {{^}} for (auto *Data : MClassTemplate) {
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:10: warning: 'auto Data' can be declared as 'auto *Data'
+ // CHECK-FIXES-ALIAS: {{^}} for (auto *Data : MClassTemplate) {
change(*Data);
}
//FixMe
for (auto Data : CClassTemplate) {
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'auto Data' can be declared as 'const auto *Data'
// CHECK-FIXES: {{^}} for (const auto *Data : CClassTemplate) {
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:10: warning: 'auto Data' can be declared as 'const auto *Data'
+ // CHECK-FIXES-ALIAS: {{^}} for (const auto *Data : CClassTemplate) {
observe(*Data);
}
}
@@ -223,21 +286,31 @@ void baz() {
auto MyFunctionPtr = getPtrFunction();
// CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto MyFunctionPtr' can be declared as 'auto *MyFunctionPtr'
// CHECK-FIXES-NOT: {{^}} auto *MyFunctionPtr = getPtrFunction();
+ // CHECK-MESSAGES-NOT-ALIAS: :[[@LINE-1]]:3: warning: 'auto MyFunctionPtr' can be declared as 'auto *MyFunctionPtr'
+ // CHECK-FIXES-NOT-ALIAS: {{^}} auto *MyFunctionPtr = getPtrFunction();
auto MyFunctionVal = getValFunction();
// CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto MyFunctionVal' can be declared as 'auto *MyFunctionVal'
// CHECK-FIXES-NOT: {{^}} auto *MyFunctionVal = getValFunction();
+ // CHECK-MESSAGES-NOT-ALIAS: :[[@LINE-3]]:3: warning: 'auto MyFunctionVal' can be declared as 'auto *MyFunctionVal'
+ // CHECK-FIXES-NOT-ALIAS: {{^}} auto *MyFunctionVal = getValFunction();
auto LambdaTest = [] { return 0; };
// CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto LambdaTest' can be declared as 'auto *LambdaTest'
// CHECK-FIXES-NOT: {{^}} auto *LambdaTest = [] { return 0; };
+ // CHECK-MESSAGES-NOT-ALIAS: :[[@LINE-3]]:3: warning: 'auto LambdaTest' can be declared as 'auto *LambdaTest'
+ // CHECK-FIXES-NOT-ALIAS: {{^}} auto *LambdaTest = [] { return 0; };
auto LambdaTest2 = +[] { return 0; };
// CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto LambdaTest2' can be declared as 'auto *LambdaTest2'
// CHECK-FIXES-NOT: {{^}} auto *LambdaTest2 = +[] { return 0; };
+ // CHECK-MESSAGES-NOT-ALIAS: :[[@LINE-3]]:3: warning: 'auto LambdaTest2' can be declared as 'auto *LambdaTest2'
+ // CHECK-FIXES-NOT-ALIAS: {{^}} auto *LambdaTest2 = +[] { return 0; };
auto MyFunctionRef = *getPtrFunction();
// CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto MyFunctionRef' can be declared as 'auto *MyFunctionRef'
// CHECK-FIXES-NOT: {{^}} auto *MyFunctionRef = *getPtrFunction();
+ // CHECK-MESSAGES-NOT-ALIAS: :[[@LINE-3]]:3: warning: 'auto MyFunctionRef' can be declared as 'auto *MyFunctionRef'
+ // CHECK-FIXES-NOT-ALIAS: {{^}} auto *MyFunctionRef = *getPtrFunction();
auto &MyFunctionRef2 = *getPtrFunction();
}
@@ -339,10 +412,14 @@ void ignored_types() {
auto arr_not_ignored2 = new std::array<int, 4>::NotIgnored2();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto arr_not_ignored2' can be declared as 'auto *arr_not_ignored2'
// CHECK-FIXES: auto *arr_not_ignored2 = new std::array<int, 4>::NotIgnored2();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto arr_not_ignored2' can be declared as 'auto *arr_not_ignored2'
+ // CHECK-FIXES-ALIAS: auto *arr_not_ignored2 = new std::array<int, 4>::NotIgnored2();
auto not_ignored2 = new std::Ignored2();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto not_ignored2' can be declared as 'auto *not_ignored2'
// CHECK-FIXES: auto *not_ignored2 = new std::Ignored2();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto not_ignored2' can be declared as 'auto *not_ignored2'
+ // CHECK-FIXES-ALIAS: auto *not_ignored2 = new std::Ignored2();
auto ignored1 = new my::ns::Ignored1();
// CHECK-MESSAGES-NOT: warning: 'auto ignored1' can be declared as 'auto *ignored1'
@@ -351,14 +428,20 @@ void ignored_types() {
auto not_ignored1 = new my::ns::NotIgnored1();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto not_ignored1' can be declared as 'auto *not_ignored1'
// CHECK-FIXES: auto *not_ignored1 = new my::ns::NotIgnored1();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto not_ignored1' can be declared as 'auto *not_ignored1'
+ // CHECK-FIXES-ALIAS: auto *not_ignored1 = new my::ns::NotIgnored1();
auto not2_ignored1 = new my::ns::NotIgnored2();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto not2_ignored1' can be declared as 'auto *not2_ignored1'
// CHECK-FIXES: auto *not2_ignored1 = new my::ns::NotIgnored2();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto not2_ignored1' can be declared as 'auto *not2_ignored1'
+ // CHECK-FIXES-ALIAS: auto *not2_ignored1 = new my::ns::NotIgnored2();
auto not3_ignored1 = new my::Ignored1();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto not3_ignored1' can be declared as 'auto *not3_ignored1'
// CHECK-FIXES: auto *not3_ignored1 = new my::Ignored1();
+ // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto not3_ignored1' can be declared as 'auto *not3_ignored1'
+ // CHECK-FIXES-ALIAS: auto *not3_ignored1 = new my::Ignored1();
}
template <typename T>
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-diff.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-diff.cpp
index 2e18a43..25be90f 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-diff.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-diff.cpp
@@ -1,15 +1,19 @@
// REQUIRES: shell
// RUN: sed 's/placeholder_for_f/f/' %s > %t.cpp
// RUN: clang-tidy -checks=-*,modernize-use-override %t.cpp -- -std=c++11 | FileCheck -check-prefix=CHECK-SANITY %s
-// RUN: not diff -U0 %s %t.cpp | %clang_tidy_diff -checks=-*,modernize-use-override -- -std=c++11 2>&1 | FileCheck %s
+// RUN: not diff -U0 %s %t.cpp | %clang_tidy_diff -checks=-*,modernize-use-override -- -std=c++11 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-JMAX
// RUN: not diff -U0 %s %t.cpp | %clang_tidy_diff -checks=-*,modernize-use-override -quiet -- -std=c++11 2>&1 | FileCheck -check-prefix=CHECK-QUIET %s
-// RUN: mkdir -p %T/compilation-database-test/
-// RUN: echo '[{"directory": "%T", "command": "clang++ -o test.o -std=c++11 %t.cpp", "file": "%t.cpp"}]' > %T/compilation-database-test/compile_commands.json
-// RUN: not diff -U0 %s %t.cpp | %clang_tidy_diff -checks=-*,modernize-use-override -path %T/compilation-database-test 2>&1 | FileCheck -check-prefix=CHECK %s
+// RUN: mkdir -p %t.dir/compilation-database-test/
+// RUN: echo '[{"directory": "%t.dir", "command": "clang++ -o test.o -std=c++11 %t.cpp", "file": "%t.cpp"}]' > %t.dir/compilation-database-test/compile_commands.json
+// RUN: not diff -U0 %s %t.cpp | %clang_tidy_diff -checks=-*,modernize-use-override -path %t.dir/compilation-database-test 2>&1 | FileCheck -check-prefix=CHECK %s
+
+// RUN: not diff -U0 %s %t.cpp | %clang_tidy_diff -checks=-*,modernize-use-override -j 1 -- -std=c++11 2>&1 | FileCheck %s --check-prefix=CHECK-J1
+// CHECK-J1: Running clang-tidy in 1 threads...
struct A {
virtual void f() {}
virtual void g() {}
};
+// CHECK-JMAX: Running clang-tidy in {{[1-9][0-9]*}} threads...
// CHECK-NOT: warning:
// CHECK-QUIET-NOT: warning:
struct B : public A {
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-run-with-database.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-run-with-database.cpp
index 3c4e849..9ca0ab3 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-run-with-database.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-run-with-database.cpp
@@ -1,28 +1,28 @@
-// RUN: mkdir -p %T/compilation-database-test/include
-// RUN: mkdir -p %T/compilation-database-test/a
-// RUN: mkdir -p %T/compilation-database-test/b
-// RUN: echo 'int *AA = 0;' > %T/compilation-database-test/a/a.cpp
-// RUN: echo 'int *AB = 0;' > %T/compilation-database-test/a/b.cpp
-// RUN: echo 'int *BB = 0;' > %T/compilation-database-test/b/b.cpp
-// RUN: echo 'int *BC = 0;' > %T/compilation-database-test/b/c.cpp
-// RUN: echo 'int *BD = 0;' > %T/compilation-database-test/b/d.cpp
-// RUN: echo 'int *HP = 0;' > %T/compilation-database-test/include/header.h
-// RUN: echo '#include "header.h"' > %T/compilation-database-test/include.cpp
-// RUN: sed 's|test_dir|%/T/compilation-database-test|g' %S/Inputs/compilation-database/template.json > %T/compile_commands.json
+// RUN: mkdir -p %t.dir/compilation-database-test/include
+// RUN: mkdir -p %t.dir/compilation-database-test/a
+// RUN: mkdir -p %t.dir/compilation-database-test/b
+// RUN: echo 'int *AA = 0;' > %t.dir/compilation-database-test/a/a.cpp
+// RUN: echo 'int *AB = 0;' > %t.dir/compilation-database-test/a/b.cpp
+// RUN: echo 'int *BB = 0;' > %t.dir/compilation-database-test/b/b.cpp
+// RUN: echo 'int *BC = 0;' > %t.dir/compilation-database-test/b/c.cpp
+// RUN: echo 'int *BD = 0;' > %t.dir/compilation-database-test/b/d.cpp
+// RUN: echo 'int *HP = 0;' > %t.dir/compilation-database-test/include/header.h
+// RUN: echo '#include "header.h"' > %t.dir/compilation-database-test/include.cpp
+// RUN: sed 's|test_dir|%/t.dir/compilation-database-test|g' %S/Inputs/compilation-database/template.json > %t.dir/compile_commands.json
// Regression test: shouldn't crash.
-// RUN: not clang-tidy --checks=-*,modernize-use-nullptr -p %T %T/compilation-database-test/b/not-exist -header-filter=.* 2>&1 | FileCheck %s -check-prefix=CHECK-NOT-EXIST
+// RUN: not clang-tidy --checks=-*,modernize-use-nullptr -p %t.dir %t.dir/compilation-database-test/b/not-exist -header-filter=.* 2>&1 | FileCheck %s -check-prefix=CHECK-NOT-EXIST
// CHECK-NOT-EXIST: Error while processing {{.*[/\\]}}not-exist.
// CHECK-NOT-EXIST: unable to handle compilation
// CHECK-NOT-EXIST: Found compiler error
-// RUN: clang-tidy --checks=-*,modernize-use-nullptr -p %T %T/compilation-database-test/a/a.cpp %T/compilation-database-test/a/b.cpp %T/compilation-database-test/b/b.cpp %T/compilation-database-test/b/c.cpp %T/compilation-database-test/b/d.cpp %T/compilation-database-test/include.cpp -header-filter=.* -fix
-// RUN: FileCheck -input-file=%T/compilation-database-test/a/a.cpp %s -check-prefix=CHECK-FIX1
-// RUN: FileCheck -input-file=%T/compilation-database-test/a/b.cpp %s -check-prefix=CHECK-FIX2
-// RUN: FileCheck -input-file=%T/compilation-database-test/b/b.cpp %s -check-prefix=CHECK-FIX3
-// RUN: FileCheck -input-file=%T/compilation-database-test/b/c.cpp %s -check-prefix=CHECK-FIX4
-// RUN: FileCheck -input-file=%T/compilation-database-test/b/d.cpp %s -check-prefix=CHECK-FIX5
-// RUN: FileCheck -input-file=%T/compilation-database-test/include/header.h %s -check-prefix=CHECK-FIX6
+// RUN: clang-tidy --checks=-*,modernize-use-nullptr -p %t.dir %t.dir/compilation-database-test/a/a.cpp %t.dir/compilation-database-test/a/b.cpp %t.dir/compilation-database-test/b/b.cpp %t.dir/compilation-database-test/b/c.cpp %t.dir/compilation-database-test/b/d.cpp %t.dir/compilation-database-test/include.cpp -header-filter=.* -fix
+// RUN: FileCheck -input-file=%t.dir/compilation-database-test/a/a.cpp %s -check-prefix=CHECK-FIX1
+// RUN: FileCheck -input-file=%t.dir/compilation-database-test/a/b.cpp %s -check-prefix=CHECK-FIX2
+// RUN: FileCheck -input-file=%t.dir/compilation-database-test/b/b.cpp %s -check-prefix=CHECK-FIX3
+// RUN: FileCheck -input-file=%t.dir/compilation-database-test/b/c.cpp %s -check-prefix=CHECK-FIX4
+// RUN: FileCheck -input-file=%t.dir/compilation-database-test/b/d.cpp %s -check-prefix=CHECK-FIX5
+// RUN: FileCheck -input-file=%t.dir/compilation-database-test/include/header.h %s -check-prefix=CHECK-FIX6
// CHECK-FIX1: int *AA = nullptr;
// CHECK-FIX2: int *AB = nullptr;
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-store-check-profile-one-tu.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-store-check-profile-one-tu.cpp
index f0939f7..192fbf5 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-store-check-profile-one-tu.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-store-check-profile-one-tu.cpp
@@ -1,9 +1,9 @@
-// RUN: rm -rf %T/out
-// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' -store-check-profile=%T/out %s -- 2>&1 | not FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK-CONSOLE %s
-// RUN: cat %T/out/*-clang-tidy-store-check-profile-one-tu.cpp.json | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK-FILE %s
-// RUN: rm -rf %T/out
-// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' -store-check-profile=%T/out %s -- 2>&1
-// RUN: cat %T/out/*-clang-tidy-store-check-profile-one-tu.cpp.json | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK-FILE %s
+// RUN: rm -rf %t.dir/out
+// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' -store-check-profile=%t.dir/out %s -- 2>&1 | not FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK-CONSOLE %s
+// RUN: cat %t.dir/out/*-clang-tidy-store-check-profile-one-tu.cpp.json | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK-FILE %s
+// RUN: rm -rf %t.dir/out
+// RUN: clang-tidy -enable-check-profile -checks='-*,readability-function-size' -store-check-profile=%t.dir/out %s -- 2>&1
+// RUN: cat %t.dir/out/*-clang-tidy-store-check-profile-one-tu.cpp.json | FileCheck --match-full-lines -implicit-check-not='{{warning:|error:}}' -check-prefix=CHECK-FILE %s
// CHECK-CONSOLE-NOT: ===-------------------------------------------------------------------------===
// CHECK-CONSOLE-NOT: {{.*}} --- Name ---
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
index 57d930b..610d1da 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
@@ -14,15 +14,15 @@
// Now create a directory with a compilation database file and ensure we don't
// use it after failing to parse commands from the command line:
//
-// RUN: mkdir -p %T/diagnostics/
-// RUN: echo '[{"directory": "%/T/diagnostics/","command": "clang++ -fan-option-from-compilation-database -c %/T/diagnostics/input.cpp", "file": "%/T/diagnostics/input.cpp"}]' > %T/diagnostics/compile_commands.json
-// RUN: cat %s > %T/diagnostics/input.cpp
-// RUN: not clang-tidy -checks='-*,modernize-use-override' %T/diagnostics/nonexistent.cpp -- 2>&1 | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s
-// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %T/diagnostics/input.cpp -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s
-// RUN: not clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %T/diagnostics/input.cpp -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s
-// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %T/diagnostics/input.cpp -- -DMACRO_FROM_COMMAND_LINE 2>&1 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
-// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %T/diagnostics/input.cpp 2>&1 | FileCheck -check-prefix=CHECK5 -implicit-check-not='{{warning:|error:}}' %s
-// RUN: not clang-tidy -checks='-*,modernize-use-override' %T/diagnostics/input.cpp -- -DCOMPILATION_ERROR 2>&1 | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: mkdir -p %t.dir/diagnostics/
+// RUN: echo '[{"directory": "%/t.dir/diagnostics/","command": "clang++ -fan-option-from-compilation-database -c %/T/diagnostics/input.cpp", "file": "%/T/diagnostics/input.cpp"}]' > %t.dir/diagnostics/compile_commands.json
+// RUN: cat %s > %t.dir/diagnostics/input.cpp
+// RUN: not clang-tidy -checks='-*,modernize-use-override' %t.dir/diagnostics/nonexistent.cpp -- 2>&1 | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %t.dir/diagnostics/input.cpp -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %t.dir/diagnostics/input.cpp -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %t.dir/diagnostics/input.cpp -- -DMACRO_FROM_COMMAND_LINE 2>&1 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %t.dir/diagnostics/input.cpp 2>&1 | FileCheck -check-prefix=CHECK5 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,modernize-use-override' %t.dir/diagnostics/input.cpp -- -DCOMPILATION_ERROR 2>&1 | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s
// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE -std=c++20 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined,clang-diagnostic-literal-conversion' %s -- -DMACRO_FROM_COMMAND_LINE -std=c++20 -Wno-macro-redefined | FileCheck --check-prefix=CHECK7 -implicit-check-not='{{warning:|error:}}' %s
// RUN: clang-tidy -checks='-*,modernize-use-override' %s -- -std=c++20 -DPR64602
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/export-relpath.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/export-relpath.cpp
index 5bfd41f..5fd7303 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/export-relpath.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/export-relpath.cpp
@@ -1,14 +1,15 @@
-// RUN: rm -rf %T/clang-tidy/export-relpath
-// RUN: mkdir -p %T/clang-tidy/export-relpath/subdir
-// RUN: cp %s %T/clang-tidy/export-relpath/subdir/source.cpp
-// RUN: echo '[{ "directory": "%/T/clang-tidy/export-relpath/subdir", "command": "clang++ source.cpp", "file": "%/T/clang-tidy/export-relpath/subdir/source.cpp"}]' > %T/clang-tidy/export-relpath/subdir/compile_commands.json
+// RUN: mkdir -p %t.dir
+// RUN: rm -rf %t.dir/clang-tidy/export-relpath
+// RUN: mkdir -p %t.dir/clang-tidy/export-relpath/subdir
+// RUN: cp %s %t.dir/clang-tidy/export-relpath/subdir/source.cpp
+// RUN: echo '[{ "directory": "%/t.dir/clang-tidy/export-relpath/subdir", "command": "clang++ source.cpp", "file": "%/T/clang-tidy/export-relpath/subdir/source.cpp"}]' > %t.dir/clang-tidy/export-relpath/subdir/compile_commands.json
//
// Check that running clang-tidy in './subdir' and storing results
// in './fixes.yaml' works as expected.
//
-// RUN: cd %T/clang-tidy/export-relpath
+// RUN: cd %t.dir/clang-tidy/export-relpath
// RUN: clang-tidy -p subdir subdir/source.cpp -checks='-*,google-explicit-constructor,llvm-namespace-comment' -export-fixes=./fixes.yaml
-// RUN: FileCheck -input-file=%T/clang-tidy/export-relpath/fixes.yaml -check-prefix=CHECK-YAML %s
+// RUN: FileCheck -input-file=%t.dir/clang-tidy/export-relpath/fixes.yaml -check-prefix=CHECK-YAML %s
namespace i {
void f(); // So that the namespace isn't empty.
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/list-checks.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/list-checks.cpp
index 674c118..73bb5b7 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/list-checks.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/list-checks.cpp
@@ -1,4 +1,4 @@
-// RUN: mkdir -p %T/clang-tidy/list-checks/
-// RUN: echo '{Checks: "-*,google-*"}' > %T/clang-tidy/.clang-tidy
-// RUN: cd %T/clang-tidy/list-checks
+// RUN: mkdir -p %t.dir/clang-tidy/list-checks/
+// RUN: echo '{Checks: "-*,google-*"}' > %t.dir/clang-tidy/.clang-tidy
+// RUN: cd %t.dir/clang-tidy/list-checks
// RUN: clang-tidy -list-checks | grep "^ *google-"
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/read_file_config.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/read_file_config.cpp
index 3e39b4d..8b12f45 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/read_file_config.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/read_file_config.cpp
@@ -1,10 +1,10 @@
// REQUIRES: static-analyzer
-// RUN: mkdir -p %T/read-file-config/
-// RUN: cp %s %T/read-file-config/test.cpp
-// RUN: echo 'Checks: "-*,modernize-use-nullptr"' > %T/read-file-config/.clang-tidy
-// RUN: echo '[{"command": "cc -c -o test.o test.cpp", "directory": "%/T/read-file-config", "file": "%/T/read-file-config/test.cpp"}]' > %T/read-file-config/compile_commands.json
-// RUN: clang-tidy %T/read-file-config/test.cpp | not grep "warning: .*\[clang-analyzer-deadcode.DeadStores\]$"
-// RUN: clang-tidy -checks="-*,clang-analyzer-*" %T/read-file-config/test.cpp | grep "warning: .*\[clang-analyzer-deadcode.DeadStores\]$"
+// RUN: mkdir -p %t.dir/read-file-config/
+// RUN: cp %s %t.dir/read-file-config/test.cpp
+// RUN: echo 'Checks: "-*,modernize-use-nullptr"' > %t.dir/read-file-config/.clang-tidy
+// RUN: echo '[{"command": "cc -c -o test.o test.cpp", "directory": "%/t.dir/read-file-config", "file": "%/t.dir/read-file-config/test.cpp"}]' > %t.dir/read-file-config/compile_commands.json
+// RUN: clang-tidy %t.dir/read-file-config/test.cpp | not grep "warning: .*\[clang-analyzer-deadcode.DeadStores\]$"
+// RUN: clang-tidy -checks="-*,clang-analyzer-*" %t.dir/read-file-config/test.cpp | grep "warning: .*\[clang-analyzer-deadcode.DeadStores\]$"
void f() {
int x;
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/run-clang-tidy.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/run-clang-tidy.cpp
index 505ee28..6337686 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/run-clang-tidy.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/run-clang-tidy.cpp
@@ -8,7 +8,11 @@
// RUN: echo " modernize-use-auto.MinTypeNameLength: '0'" >> %t/.clang-tidy
// RUN: cp "%s" "%t/test.cpp"
// RUN: cd "%t"
-// RUN: not %run_clang_tidy "test.cpp"
+// RUN: not %run_clang_tidy "test.cpp" 2>&1 | FileCheck %s --check-prefix=CHECK-JMAX
+// CHECK-JMAX: Running clang-tidy in {{[1-9][0-9]*}} threads for
+
+// RUN: not %run_clang_tidy -j 1 "test.cpp" 2>&1 | FileCheck %s --check-prefix=CHECK-J1
+// CHECK-J1: Running clang-tidy in 1 threads for
int main()
{
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/static-analyzer-config.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/static-analyzer-config.cpp
index 725f877..6a9641e 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/static-analyzer-config.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/static-analyzer-config.cpp
@@ -16,5 +16,5 @@ void af2() {
void *p = my_malloc(12);
my_free(p);
free(p);
- // CHECK: warning: Attempt to free released memory [clang-analyzer-unix.Malloc]
+ // CHECK: warning: Attempt to release already released memory [clang-analyzer-unix.Malloc]
}
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/static-analyzer.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/static-analyzer.cpp
index af9693a..c45f219 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/static-analyzer.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/static-analyzer.cpp
@@ -7,12 +7,12 @@ void f() {
int *p = new int(42);
delete p;
delete p;
- // CHECK: warning: Attempt to free released memory [clang-analyzer-cplusplus.NewDelete]
+ // CHECK: warning: Attempt to release already released memory [clang-analyzer-cplusplus.NewDelete]
}
void g() {
void *q = malloc(132);
free(q);
free(q);
- // CHECK: warning: Attempt to free released memory [clang-analyzer-unix.Malloc]
+ // CHECK: warning: Attempt to release already released memory [clang-analyzer-unix.Malloc]
}
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/verify-config.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/verify-config.cpp
index 93f6f9f..30d4933 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/verify-config.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/verify-config.cpp
@@ -19,22 +19,22 @@
// CHECK-VERIFY: command-line option '-checks': warning: unknown check 'llvm-includeorder'; did you mean 'llvm-include-order' [-verify-config]
// CHECK-VERIFY: command-line option '-checks': warning: unknown check 'my-made-up-check' [-verify-config]
-// RUN: echo -e 'Checks: |\n bugprone-argument-comment\n bugprone-assert-side-effect,\n bugprone-bool-pointer-implicit-conversion\n readability-use-anyof*' > %T/MyClangTidyConfig
+// RUN: echo -e 'Checks: |\n bugprone-argument-comment\n bugprone-assert-side-effect,\n bugprone-bool-pointer-implicit-conversion\n readability-use-anyof*' > %t.MyClangTidyConfig
// RUN: clang-tidy -verify-config \
-// RUN: --config-file=%T/MyClangTidyConfig | FileCheck %s -check-prefix=CHECK-VERIFY-BLOCK-OK
+// RUN: --config-file=%t.MyClangTidyConfig | FileCheck %s -check-prefix=CHECK-VERIFY-BLOCK-OK
// CHECK-VERIFY-BLOCK-OK: No config errors detected.
-// RUN: echo -e 'Checks: |\n bugprone-arguments-*\n bugprone-assert-side-effects\n bugprone-bool-pointer-implicit-conversion' > %T/MyClangTidyConfigBad
+// RUN: echo -e 'Checks: |\n bugprone-arguments-*\n bugprone-assert-side-effects\n bugprone-bool-pointer-implicit-conversion' > %t.MyClangTidyConfigBad
// RUN: not clang-tidy -verify-config \
-// RUN: --config-file=%T/MyClangTidyConfigBad 2>&1 | FileCheck %s -check-prefix=CHECK-VERIFY-BLOCK-BAD
+// RUN: --config-file=%t.MyClangTidyConfigBad 2>&1 | FileCheck %s -check-prefix=CHECK-VERIFY-BLOCK-BAD
// CHECK-VERIFY-BLOCK-BAD: command-line option '-config': warning: check glob 'bugprone-arguments-*' doesn't match any known check [-verify-config]
// CHECK-VERIFY-BLOCK-BAD: command-line option '-config': warning: unknown check 'bugprone-assert-side-effects'; did you mean 'bugprone-assert-side-effect' [-verify-config]
-// RUN: echo -e 'Checks: "-*,clang-analyzer-optin.cplusplus.UninitializedObject"\nCheckOptions:\n clang-analyzer-optin.cplusplus.UninitializedObject:Pedantic: true' > %T/MyClangTidyConfigCSA
-// RUN: clang-tidy --verify-config --config-file=%T/MyClangTidyConfigCSA 2>&1 | FileCheck %s -check-prefix=CHECK-VERIFY-CSA-OK -implicit-check-not='{{warnings|error}}'
+// RUN: echo -e 'Checks: "-*,clang-analyzer-optin.cplusplus.UninitializedObject"\nCheckOptions:\n clang-analyzer-optin.cplusplus.UninitializedObject:Pedantic: true' > %t.MyClangTidyConfigCSA
+// RUN: clang-tidy --verify-config --config-file=%t.MyClangTidyConfigCSA 2>&1 | FileCheck %s -check-prefix=CHECK-VERIFY-CSA-OK -implicit-check-not='{{warnings|error}}'
// CHECK-VERIFY-CSA-OK: No config errors detected.
-// RUN: echo -e 'Checks: "-*,clang-analyzer-optin.cplusplus.UninitializedObject"\nCheckOptions:\n clang-analyzer-optin.cplusplus.UninitializedObject.Pedantic: true' > %T/MyClangTidyConfigCSABad
-// RUN: not clang-tidy --verify-config --config-file=%T/MyClangTidyConfigCSABad 2>&1 | FileCheck %s -check-prefix=CHECK-VERIFY-CSA-BAD -implicit-check-not='{{warnings|error}}'
+// RUN: echo -e 'Checks: "-*,clang-analyzer-optin.cplusplus.UninitializedObject"\nCheckOptions:\n clang-analyzer-optin.cplusplus.UninitializedObject.Pedantic: true' > %t.MyClangTidyConfigCSABad
+// RUN: not clang-tidy --verify-config --config-file=%t.MyClangTidyConfigCSABad 2>&1 | FileCheck %s -check-prefix=CHECK-VERIFY-CSA-BAD -implicit-check-not='{{warnings|error}}'
// CHECK-VERIFY-CSA-BAD: command-line option '-config': warning: unknown check option 'clang-analyzer-optin.cplusplus.UninitializedObject.Pedantic'; did you mean 'clang-analyzer-optin.cplusplus.UninitializedObject:Pedantic' [-verify-config]
diff --git a/clang-tools-extra/test/modularize/NoProblemsAssistant.modularize b/clang-tools-extra/test/modularize/NoProblemsAssistant.modularize
index 7ddc726..39c06dc 100644
--- a/clang-tools-extra/test/modularize/NoProblemsAssistant.modularize
+++ b/clang-tools-extra/test/modularize/NoProblemsAssistant.modularize
@@ -1,5 +1,7 @@
+# RUN: mkdir -p %t.dir/Output
+# RUN: cd %t.dir
# RUN: modularize -module-map-path=Output/NoProblemsAssistant.txt -root-module=Root -prefix=%S/Input %s
-# RUN: FileCheck --input-file=%T/NoProblemsAssistant.txt %s
+# RUN: FileCheck --input-file=Output/NoProblemsAssistant.txt %s
SomeTypes.h
SomeDecls.h
diff --git a/clang-tools-extra/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp b/clang-tools-extra/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp
index 87b0d69..0b92118 100644
--- a/clang-tools-extra/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp
+++ b/clang-tools-extra/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp
@@ -33,8 +33,7 @@ makeTUDiagnostics(const std::string &MainSourceFile, StringRef DiagnosticName,
// before applying.
TEST(ApplyReplacementsTest, mergeDiagnosticsWithNoFixes) {
DiagnosticOptions DiagOpts;
- DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), DiagOpts);
+ DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts);
FileManager Files((FileSystemOptions()));
SourceManager SM(Diagnostics, Files);
TUReplacements TURs;
diff --git a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp
index 32b0846..602058f 100644
--- a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp
@@ -86,132 +86,3 @@ TEST(HTMLMustacheGeneratorTest, createResources) {
verifyFileContents(PathBuf, "JavaScript");
}
}
-
-TEST(HTMLGeneratorTest, emitFunctionHTML) {
-#if ENABLE_LOCAL_TEST
- auto G = getHTMLMustacheGenerator();
- assert(G && "Could not find HTMLMustacheGenerator");
- ClangDocContext CDCtx = getClangDocContext();
- std::string Buffer;
- llvm::raw_string_ostream Actual(Buffer);
-
- unittest::TempDir RootTestDirectory("emitRecordHTML",
- /*Unique=*/true);
- CDCtx.OutDirectory = RootTestDirectory.path();
-
- getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx);
-
- // FIXME: This is a terrible hack, since we can't initialize the templates
- // directly. We'll need to update the interfaces so that we can call
- // SetupTemplateFiles() from outsize of HTMLMustacheGenerator.cpp
- EXPECT_THAT_ERROR(G->generateDocs(RootTestDirectory.path(), {}, CDCtx),
- Succeeded())
- << "Failed to generate docs.";
-
- CDCtx.RepositoryUrl = "http://www.repository.com";
-
- FunctionInfo I;
- I.Name = "f";
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
-
- I.DefLoc = Location(10, 10, "dir/test.cpp", true);
- I.Loc.emplace_back(12, 12, "test.cpp");
-
- I.Access = AccessSpecifier::AS_none;
-
- SmallString<16> PathTo;
- llvm::sys::path::native("path/to", PathTo);
- I.ReturnType = doc::TypeInfo(
- Reference(EmptySID, "float", InfoType::IT_default, "float", PathTo));
- I.Params.emplace_back(doc::TypeInfo("int", PathTo), "P");
- I.IsMethod = true;
- I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
-
- auto Err = G->generateDocForInfo(&I, Actual, CDCtx);
- assert(!Err);
- std::string Expected = R"raw(IT_Function
-)raw";
-
- // FIXME: Functions are not handled yet.
- EXPECT_EQ(Expected, Actual.str());
-#endif
-}
-
-TEST(HTMLMustacheGeneratorTest, emitCommentHTML) {
-#if ENABLE_LOCAL_TEST
- auto G = getHTMLMustacheGenerator();
- assert(G && "Could not find HTMLMustacheGenerator");
- ClangDocContext CDCtx = getClangDocContext();
- std::string Buffer;
- llvm::raw_string_ostream Actual(Buffer);
-
- unittest::TempDir RootTestDirectory("emitCommentHTML",
- /*Unique=*/true);
- CDCtx.OutDirectory = RootTestDirectory.path();
-
- getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx);
-
- // FIXME: This is a terrible hack, since we can't initialize the templates
- // directly. We'll need to update the interfaces so that we can call
- // SetupTemplateFiles() from outsize of HTMLMustacheGenerator.cpp
- EXPECT_THAT_ERROR(G->generateDocs(RootTestDirectory.path(), {}, CDCtx),
- Succeeded())
- << "Failed to generate docs.";
-
- CDCtx.RepositoryUrl = "http://www.repository.com";
-
- FunctionInfo I;
- I.Name = "f";
- I.DefLoc = Location(10, 10, "test.cpp", true);
- I.ReturnType = doc::TypeInfo("void");
- I.Params.emplace_back(doc::TypeInfo("int"), "I");
- I.Params.emplace_back(doc::TypeInfo("int"), "J");
- I.Access = AccessSpecifier::AS_none;
-
- CommentInfo Top;
- Top.Kind = "FullComment";
-
- Top.Children.emplace_back(std::make_unique<CommentInfo>());
- CommentInfo *BlankLine = Top.Children.back().get();
- BlankLine->Kind = "ParagraphComment";
- BlankLine->Children.emplace_back(std::make_unique<CommentInfo>());
- BlankLine->Children.back()->Kind = "TextComment";
-
- Top.Children.emplace_back(std::make_unique<CommentInfo>());
- CommentInfo *Brief = Top.Children.back().get();
- Brief->Kind = "ParagraphComment";
- Brief->Children.emplace_back(std::make_unique<CommentInfo>());
- Brief->Children.back()->Kind = "TextComment";
- Brief->Children.back()->Name = "ParagraphComment";
- Brief->Children.back()->Text = " Brief description.";
-
- Top.Children.emplace_back(std::make_unique<CommentInfo>());
- CommentInfo *Extended = Top.Children.back().get();
- Extended->Kind = "ParagraphComment";
- Extended->Children.emplace_back(std::make_unique<CommentInfo>());
- Extended->Children.back()->Kind = "TextComment";
- Extended->Children.back()->Text = " Extended description that";
- Extended->Children.emplace_back(std::make_unique<CommentInfo>());
- Extended->Children.back()->Kind = "TextComment";
- Extended->Children.back()->Text = " continues onto the next line.";
-
- Top.Children.emplace_back(std::make_unique<CommentInfo>());
- CommentInfo *Entities = Top.Children.back().get();
- Entities->Kind = "ParagraphComment";
- Entities->Children.emplace_back(std::make_unique<CommentInfo>());
- Entities->Children.back()->Kind = "TextComment";
- Entities->Children.back()->Name = "ParagraphComment";
- Entities->Children.back()->Text =
- " Comment with html entities: &, <, >, \", \'.";
-
- I.Description.emplace_back(std::move(Top));
-
- auto Err = G->generateDocForInfo(&I, Actual, CDCtx);
- assert(!Err);
- std::string Expected = R"raw(IT_Function
-)raw";
-
- // FIXME: Functions are not handled yet.
- EXPECT_EQ(Expected, Actual.str());
-#endif
-}
diff --git a/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp
index 5927235b..07c761f 100644
--- a/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp
@@ -63,7 +63,11 @@ TEST(JSONGeneratorTest, emitRecordJSON) {
"Bases": [
{
"Access": "public",
+ "End": true,
"FullName": "",
+ "HasPublicFunctions": true,
+ "HasPublicMembers": true,
+ "InfoType": "record",
"IsParent": true,
"IsTypedef": false,
"IsVirtual": true,
@@ -72,6 +76,7 @@ TEST(JSONGeneratorTest, emitRecordJSON) {
"Path": "path/to/F",
"PublicFunctions": [
{
+ "InfoType": "function",
"IsStatic": false,
"Name": "InheritedFunctionOne",
"ReturnType": {
@@ -96,8 +101,11 @@ TEST(JSONGeneratorTest, emitRecordJSON) {
],
"Enums": [
{
+ "End": true,
+ "InfoType": "enum",
"Members": [
{
+ "End": true,
"Name": "RED",
"Value": "0"
}
@@ -108,6 +116,10 @@ TEST(JSONGeneratorTest, emitRecordJSON) {
}
],
"FullName": "",
+ "HasEnums": true,
+ "HasPublicFunctions": true,
+ "HasRecords": true,
+ "InfoType": "record",
"IsTypedef": false,
"Location": {
"Filename": "main.cpp",
@@ -120,6 +132,7 @@ TEST(JSONGeneratorTest, emitRecordJSON) {
],
"Parents": [
{
+ "End": true,
"Name": "F",
"Path": "",
"QualName": "",
@@ -135,6 +148,7 @@ TEST(JSONGeneratorTest, emitRecordJSON) {
],
"PublicFunctions": [
{
+ "InfoType": "function",
"IsStatic": false,
"Name": "OneFunction",
"ReturnType": {
@@ -149,6 +163,7 @@ TEST(JSONGeneratorTest, emitRecordJSON) {
],
"Records": [
{
+ "End": true,
"Name": "ChildStruct",
"Path": "path/to/A/r",
"QualName": "path::to::A::r::ChildStruct",
@@ -164,6 +179,7 @@ TEST(JSONGeneratorTest, emitRecordJSON) {
"USR": "0000000000000000000000000000000000000000",
"VirtualParents": [
{
+ "End": true,
"Name": "G",
"Path": "path/to/G",
"QualName": "path::to::G::G",
@@ -201,6 +217,8 @@ TEST(JSONGeneratorTest, emitNamespaceJSON) {
std::string Expected = R"raw({
"Enums": [
{
+ "End": true,
+ "InfoType": "enum",
"Name": "OneEnum",
"Scoped": false,
"USR": "0000000000000000000000000000000000000000"
@@ -208,6 +226,8 @@ TEST(JSONGeneratorTest, emitNamespaceJSON) {
],
"Functions": [
{
+ "End": true,
+ "InfoType": "function",
"IsStatic": false,
"Name": "OneFunction",
"ReturnType": {
@@ -220,12 +240,16 @@ TEST(JSONGeneratorTest, emitNamespaceJSON) {
"USR": "0000000000000000000000000000000000000000"
}
],
+ "HasEnums": true,
+ "HasRecords": true,
+ "InfoType": "namespace",
"Name": "Namespace",
"Namespace": [
"A"
],
"Namespaces": [
{
+ "End": true,
"Name": "ChildNamespace",
"Path": "path/to/A/Namespace",
"QualName": "path::to::A::Namespace::ChildNamespace",
@@ -235,6 +259,7 @@ TEST(JSONGeneratorTest, emitNamespaceJSON) {
"Path": "path/to/A",
"Records": [
{
+ "End": true,
"Name": "ChildStruct",
"Path": "path/to/A/Namespace",
"QualName": "path::to::A::Namespace::ChildStruct",
diff --git a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp
index d3ca26a..410cebf 100644
--- a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp
+++ b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp
@@ -318,7 +318,8 @@ TEST(CheckOptionsValidation, MissingOptions) {
ClangTidyGlobalOptions(), Options));
ClangTidyDiagnosticConsumer DiagConsumer(Context);
auto DiagOpts = std::make_unique<DiagnosticOptions>();
- DiagnosticsEngine DE(new DiagnosticIDs(), *DiagOpts, &DiagConsumer, false);
+ DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer,
+ false);
Context.setDiagnosticsEngine(std::move(DiagOpts), &DE);
TestCheck TestCheck(&Context);
EXPECT_FALSE(TestCheck.getLocal("Opt"));
@@ -348,7 +349,8 @@ TEST(CheckOptionsValidation, ValidIntOptions) {
ClangTidyGlobalOptions(), Options));
ClangTidyDiagnosticConsumer DiagConsumer(Context);
auto DiagOpts = std::make_unique<DiagnosticOptions>();
- DiagnosticsEngine DE(new DiagnosticIDs(), *DiagOpts, &DiagConsumer, false);
+ DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer,
+ false);
Context.setDiagnosticsEngine(std::move(DiagOpts), &DE);
TestCheck TestCheck(&Context);
@@ -410,7 +412,8 @@ TEST(ValidConfiguration, ValidEnumOptions) {
ClangTidyGlobalOptions(), Options));
ClangTidyDiagnosticConsumer DiagConsumer(Context);
auto DiagOpts = std::make_unique<DiagnosticOptions>();
- DiagnosticsEngine DE(new DiagnosticIDs(), *DiagOpts, &DiagConsumer, false);
+ DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer,
+ false);
Context.setDiagnosticsEngine(std::move(DiagOpts), &DE);
TestCheck TestCheck(&Context);
diff --git a/clang-tools-extra/unittests/clang-tidy/ClangTidyTest.h b/clang-tools-extra/unittests/clang-tidy/ClangTidyTest.h
index 789cc2a..89f0f9f 100644
--- a/clang-tools-extra/unittests/clang-tidy/ClangTidyTest.h
+++ b/clang-tools-extra/unittests/clang-tidy/ClangTidyTest.h
@@ -97,7 +97,8 @@ runCheckOnCode(StringRef Code, std::vector<ClangTidyError> *Errors = nullptr,
ClangTidyGlobalOptions(), Options));
ClangTidyDiagnosticConsumer DiagConsumer(Context);
auto DiagOpts = std::make_unique<DiagnosticOptions>();
- DiagnosticsEngine DE(new DiagnosticIDs(), *DiagOpts, &DiagConsumer, false);
+ DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer,
+ false);
Context.setDiagnosticsEngine(std::move(DiagOpts), &DE);
std::vector<std::string> Args(1, "clang-tidy");
diff --git a/clang-tools-extra/unittests/include/common/VirtualFileHelper.h b/clang-tools-extra/unittests/include/common/VirtualFileHelper.h
index 86991bb3..cb075f8 100644
--- a/clang-tools-extra/unittests/include/common/VirtualFileHelper.h
+++ b/clang-tools-extra/unittests/include/common/VirtualFileHelper.h
@@ -32,8 +32,7 @@ class VirtualFileHelper {
public:
VirtualFileHelper()
- : Diagnostics(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
- DiagOpts),
+ : Diagnostics(DiagnosticIDs::create(), DiagOpts),
DiagnosticPrinter(llvm::outs(), DiagOpts),
Files((FileSystemOptions())) {}