summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJordan Rupprecht <rupprecht@google.com>2019-05-14 21:58:59 +0000
committerJordan Rupprecht <rupprecht@google.com>2019-05-14 21:58:59 +0000
commit46054fed6aeeabea27b9ba4a3ef81ab5ff9b9645 (patch)
treed12279f80b5729d0324f066002c838baa736fbd2
parent5026a9a16d10a2edf09be54c7225f49b5789c69e (diff)
parent0eb1ac6d1df856f065717226ef34d00679a211fe (diff)
Creating branches/google/stable and tags/google/stable/2019-05-14 from r360103upstream/stable
git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/branches/google/stable@360714 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--CMakeLists.txt11
-rw-r--r--LICENSE.TXT257
-rw-r--r--clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h7
-rw-r--r--clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp16
-rw-r--r--clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp7
-rw-r--r--clang-change-namespace/CMakeLists.txt (renamed from change-namespace/CMakeLists.txt)0
-rw-r--r--clang-change-namespace/ChangeNamespace.cpp (renamed from change-namespace/ChangeNamespace.cpp)7
-rw-r--r--clang-change-namespace/ChangeNamespace.h (renamed from change-namespace/ChangeNamespace.h)7
-rw-r--r--clang-change-namespace/tool/CMakeLists.txt (renamed from change-namespace/tool/CMakeLists.txt)0
-rw-r--r--clang-change-namespace/tool/ClangChangeNamespace.cpp (renamed from change-namespace/tool/ClangChangeNamespace.cpp)9
-rw-r--r--clang-doc/BitcodeReader.cpp7
-rw-r--r--clang-doc/BitcodeReader.h7
-rw-r--r--clang-doc/BitcodeWriter.cpp7
-rw-r--r--clang-doc/BitcodeWriter.h7
-rw-r--r--clang-doc/ClangDoc.cpp7
-rw-r--r--clang-doc/ClangDoc.h7
-rw-r--r--clang-doc/Generators.cpp9
-rw-r--r--clang-doc/Generators.h7
-rw-r--r--clang-doc/MDGenerator.cpp7
-rw-r--r--clang-doc/Mapper.cpp7
-rw-r--r--clang-doc/Mapper.h7
-rw-r--r--clang-doc/Representation.cpp7
-rw-r--r--clang-doc/Representation.h7
-rw-r--r--clang-doc/Serialize.cpp9
-rw-r--r--clang-doc/Serialize.h7
-rw-r--r--clang-doc/YAMLGenerator.cpp9
-rw-r--r--clang-doc/tool/CMakeLists.txt2
-rw-r--r--clang-doc/tool/ClangDocMain.cpp7
-rw-r--r--clang-include-fixer/CMakeLists.txt (renamed from include-fixer/CMakeLists.txt)0
-rw-r--r--clang-include-fixer/FuzzySymbolIndex.cpp (renamed from include-fixer/FuzzySymbolIndex.cpp)7
-rw-r--r--clang-include-fixer/FuzzySymbolIndex.h (renamed from include-fixer/FuzzySymbolIndex.h)9
-rw-r--r--clang-include-fixer/InMemorySymbolIndex.cpp (renamed from include-fixer/InMemorySymbolIndex.cpp)7
-rw-r--r--clang-include-fixer/InMemorySymbolIndex.h (renamed from include-fixer/InMemorySymbolIndex.h)7
-rw-r--r--clang-include-fixer/IncludeFixer.cpp (renamed from include-fixer/IncludeFixer.cpp)13
-rw-r--r--clang-include-fixer/IncludeFixer.h (renamed from include-fixer/IncludeFixer.h)9
-rw-r--r--clang-include-fixer/IncludeFixerContext.cpp (renamed from include-fixer/IncludeFixerContext.cpp)7
-rw-r--r--clang-include-fixer/IncludeFixerContext.h (renamed from include-fixer/IncludeFixerContext.h)7
-rw-r--r--clang-include-fixer/SymbolIndex.h (renamed from include-fixer/SymbolIndex.h)7
-rw-r--r--clang-include-fixer/SymbolIndexManager.cpp (renamed from include-fixer/SymbolIndexManager.cpp)9
-rw-r--r--clang-include-fixer/SymbolIndexManager.h (renamed from include-fixer/SymbolIndexManager.h)7
-rw-r--r--clang-include-fixer/YamlSymbolIndex.cpp (renamed from include-fixer/YamlSymbolIndex.cpp)7
-rw-r--r--clang-include-fixer/YamlSymbolIndex.h (renamed from include-fixer/YamlSymbolIndex.h)7
-rw-r--r--clang-include-fixer/find-all-symbols/CMakeLists.txt (renamed from include-fixer/find-all-symbols/CMakeLists.txt)0
-rw-r--r--clang-include-fixer/find-all-symbols/FindAllMacros.cpp (renamed from include-fixer/find-all-symbols/FindAllMacros.cpp)7
-rw-r--r--clang-include-fixer/find-all-symbols/FindAllMacros.h (renamed from include-fixer/find-all-symbols/FindAllMacros.h)7
-rw-r--r--clang-include-fixer/find-all-symbols/FindAllSymbols.cpp (renamed from include-fixer/find-all-symbols/FindAllSymbols.cpp)7
-rw-r--r--clang-include-fixer/find-all-symbols/FindAllSymbols.h (renamed from include-fixer/find-all-symbols/FindAllSymbols.h)7
-rw-r--r--clang-include-fixer/find-all-symbols/FindAllSymbolsAction.cpp (renamed from include-fixer/find-all-symbols/FindAllSymbolsAction.cpp)7
-rw-r--r--clang-include-fixer/find-all-symbols/FindAllSymbolsAction.h (renamed from include-fixer/find-all-symbols/FindAllSymbolsAction.h)7
-rw-r--r--clang-include-fixer/find-all-symbols/HeaderMapCollector.cpp (renamed from include-fixer/find-all-symbols/HeaderMapCollector.cpp)7
-rw-r--r--clang-include-fixer/find-all-symbols/HeaderMapCollector.h (renamed from include-fixer/find-all-symbols/HeaderMapCollector.h)7
-rw-r--r--clang-include-fixer/find-all-symbols/PathConfig.cpp (renamed from include-fixer/find-all-symbols/PathConfig.cpp)7
-rw-r--r--clang-include-fixer/find-all-symbols/PathConfig.h (renamed from include-fixer/find-all-symbols/PathConfig.h)7
-rw-r--r--clang-include-fixer/find-all-symbols/PragmaCommentHandler.cpp (renamed from include-fixer/find-all-symbols/PragmaCommentHandler.cpp)7
-rw-r--r--clang-include-fixer/find-all-symbols/PragmaCommentHandler.h (renamed from include-fixer/find-all-symbols/PragmaCommentHandler.h)7
-rw-r--r--clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp (renamed from include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp)7
-rw-r--r--clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.h (renamed from include-fixer/find-all-symbols/STLPostfixHeaderMap.h)7
-rw-r--r--clang-include-fixer/find-all-symbols/SymbolInfo.cpp (renamed from include-fixer/find-all-symbols/SymbolInfo.cpp)7
-rw-r--r--clang-include-fixer/find-all-symbols/SymbolInfo.h (renamed from include-fixer/find-all-symbols/SymbolInfo.h)7
-rw-r--r--clang-include-fixer/find-all-symbols/SymbolReporter.h (renamed from include-fixer/find-all-symbols/SymbolReporter.h)7
-rw-r--r--clang-include-fixer/find-all-symbols/tool/CMakeLists.txt (renamed from include-fixer/find-all-symbols/tool/CMakeLists.txt)0
-rw-r--r--clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp (renamed from include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp)7
-rwxr-xr-xclang-include-fixer/find-all-symbols/tool/run-find-all-symbols.py (renamed from include-fixer/find-all-symbols/tool/run-find-all-symbols.py)7
-rw-r--r--clang-include-fixer/plugin/CMakeLists.txt (renamed from include-fixer/plugin/CMakeLists.txt)0
-rw-r--r--clang-include-fixer/plugin/IncludeFixerPlugin.cpp (renamed from include-fixer/plugin/IncludeFixerPlugin.cpp)7
-rw-r--r--clang-include-fixer/tool/CMakeLists.txt (renamed from include-fixer/tool/CMakeLists.txt)0
-rw-r--r--clang-include-fixer/tool/ClangIncludeFixer.cpp (renamed from include-fixer/tool/ClangIncludeFixer.cpp)18
-rw-r--r--clang-include-fixer/tool/clang-include-fixer-test.el (renamed from include-fixer/tool/clang-include-fixer-test.el)0
-rw-r--r--clang-include-fixer/tool/clang-include-fixer.el (renamed from include-fixer/tool/clang-include-fixer.el)6
-rw-r--r--clang-include-fixer/tool/clang-include-fixer.py (renamed from include-fixer/tool/clang-include-fixer.py)14
-rw-r--r--clang-move/CMakeLists.txt2
-rw-r--r--clang-move/HelperDeclRefGraph.cpp11
-rw-r--r--clang-move/HelperDeclRefGraph.h7
-rw-r--r--clang-move/Move.cpp (renamed from clang-move/ClangMove.cpp)16
-rw-r--r--clang-move/Move.h (renamed from clang-move/ClangMove.h)9
-rw-r--r--clang-move/tool/CMakeLists.txt2
-rw-r--r--clang-move/tool/ClangMove.cpp (renamed from clang-move/tool/ClangMoveMain.cpp)11
-rw-r--r--clang-query/Query.cpp7
-rw-r--r--clang-query/Query.h7
-rw-r--r--clang-query/QueryParser.cpp7
-rw-r--r--clang-query/QueryParser.h7
-rw-r--r--clang-query/QuerySession.h7
-rw-r--r--clang-query/tool/CMakeLists.txt4
-rw-r--r--clang-query/tool/ClangQuery.cpp7
-rw-r--r--clang-reorder-fields/ReorderFieldsAction.cpp7
-rw-r--r--clang-reorder-fields/ReorderFieldsAction.h7
-rw-r--r--clang-reorder-fields/tool/CMakeLists.txt4
-rw-r--r--clang-reorder-fields/tool/ClangReorderFields.cpp7
-rw-r--r--clang-tidy-vs/ClangTidy/ClangTidyPackage.cs111
-rw-r--r--clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.cs415
-rw-r--r--clang-tidy-vs/ClangTidy/PkgCmdID.cs2
-rw-r--r--clang-tidy-vs/ClangTidy/license.txt257
-rw-r--r--clang-tidy/CMakeLists.txt3
-rw-r--r--clang-tidy/ClangTidy.cpp210
-rw-r--r--clang-tidy/ClangTidy.h177
-rw-r--r--clang-tidy/ClangTidyCheck.cpp71
-rw-r--r--clang-tidy/ClangTidyCheck.h194
-rw-r--r--clang-tidy/ClangTidyDiagnosticConsumer.cpp55
-rw-r--r--clang-tidy/ClangTidyDiagnosticConsumer.h9
-rw-r--r--clang-tidy/ClangTidyForceLinker.h12
-rw-r--r--clang-tidy/ClangTidyModule.cpp7
-rw-r--r--clang-tidy/ClangTidyModule.h7
-rw-r--r--clang-tidy/ClangTidyModuleRegistry.h7
-rw-r--r--clang-tidy/ClangTidyOptions.cpp7
-rw-r--r--clang-tidy/ClangTidyOptions.h7
-rw-r--r--clang-tidy/ClangTidyProfiling.cpp7
-rw-r--r--clang-tidy/ClangTidyProfiling.h7
-rw-r--r--clang-tidy/ExpandModularHeadersPPCallbacks.cpp294
-rw-r--r--clang-tidy/ExpandModularHeadersPPCallbacks.h137
-rw-r--r--clang-tidy/abseil/AbseilMatcher.h7
-rw-r--r--clang-tidy/abseil/AbseilTidyModule.cpp22
-rw-r--r--clang-tidy/abseil/CMakeLists.txt5
-rw-r--r--clang-tidy/abseil/DurationAdditionCheck.cpp73
-rw-r--r--clang-tidy/abseil/DurationAdditionCheck.h35
-rw-r--r--clang-tidy/abseil/DurationComparisonCheck.cpp44
-rw-r--r--clang-tidy/abseil/DurationComparisonCheck.h7
-rw-r--r--clang-tidy/abseil/DurationConversionCastCheck.cpp85
-rw-r--r--clang-tidy/abseil/DurationConversionCastCheck.h35
-rw-r--r--clang-tidy/abseil/DurationDivisionCheck.cpp7
-rw-r--r--clang-tidy/abseil/DurationDivisionCheck.h7
-rw-r--r--clang-tidy/abseil/DurationFactoryFloatCheck.cpp7
-rw-r--r--clang-tidy/abseil/DurationFactoryFloatCheck.h7
-rw-r--r--clang-tidy/abseil/DurationFactoryScaleCheck.cpp11
-rw-r--r--clang-tidy/abseil/DurationFactoryScaleCheck.h7
-rw-r--r--clang-tidy/abseil/DurationRewriter.cpp121
-rw-r--r--clang-tidy/abseil/DurationRewriter.h53
-rw-r--r--clang-tidy/abseil/DurationSubtractionCheck.cpp10
-rw-r--r--clang-tidy/abseil/DurationSubtractionCheck.h7
-rw-r--r--clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp82
-rw-r--r--clang-tidy/abseil/DurationUnnecessaryConversionCheck.h35
-rw-r--r--clang-tidy/abseil/FasterStrsplitDelimiterCheck.cpp7
-rw-r--r--clang-tidy/abseil/FasterStrsplitDelimiterCheck.h7
-rw-r--r--clang-tidy/abseil/NoInternalDependenciesCheck.cpp7
-rw-r--r--clang-tidy/abseil/NoInternalDependenciesCheck.h7
-rw-r--r--clang-tidy/abseil/NoNamespaceCheck.cpp7
-rw-r--r--clang-tidy/abseil/NoNamespaceCheck.h7
-rw-r--r--clang-tidy/abseil/RedundantStrcatCallsCheck.cpp7
-rw-r--r--clang-tidy/abseil/RedundantStrcatCallsCheck.h7
-rw-r--r--clang-tidy/abseil/StrCatAppendCheck.cpp7
-rw-r--r--clang-tidy/abseil/StrCatAppendCheck.h7
-rw-r--r--clang-tidy/abseil/StringFindStartswithCheck.cpp16
-rw-r--r--clang-tidy/abseil/StringFindStartswithCheck.h10
-rw-r--r--clang-tidy/abseil/TimeComparisonCheck.cpp61
-rw-r--r--clang-tidy/abseil/TimeComparisonCheck.h35
-rw-r--r--clang-tidy/abseil/TimeSubtractionCheck.cpp181
-rw-r--r--clang-tidy/abseil/TimeSubtractionCheck.h38
-rw-r--r--clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp7
-rw-r--r--clang-tidy/abseil/UpgradeDurationConversionsCheck.h7
-rwxr-xr-xclang-tidy/add_new_check.py28
-rw-r--r--clang-tidy/android/AndroidTidyModule.cpp7
-rw-r--r--clang-tidy/android/CloexecAccept4Check.cpp7
-rw-r--r--clang-tidy/android/CloexecAccept4Check.h7
-rw-r--r--clang-tidy/android/CloexecAcceptCheck.cpp7
-rw-r--r--clang-tidy/android/CloexecAcceptCheck.h7
-rw-r--r--clang-tidy/android/CloexecCheck.cpp7
-rw-r--r--clang-tidy/android/CloexecCheck.h9
-rw-r--r--clang-tidy/android/CloexecCreatCheck.cpp7
-rw-r--r--clang-tidy/android/CloexecCreatCheck.h7
-rw-r--r--clang-tidy/android/CloexecDupCheck.cpp7
-rw-r--r--clang-tidy/android/CloexecDupCheck.h7
-rw-r--r--clang-tidy/android/CloexecEpollCreate1Check.cpp7
-rw-r--r--clang-tidy/android/CloexecEpollCreate1Check.h7
-rw-r--r--clang-tidy/android/CloexecEpollCreateCheck.cpp7
-rw-r--r--clang-tidy/android/CloexecEpollCreateCheck.h7
-rw-r--r--clang-tidy/android/CloexecFopenCheck.cpp6
-rw-r--r--clang-tidy/android/CloexecFopenCheck.h7
-rw-r--r--clang-tidy/android/CloexecInotifyInit1Check.cpp7
-rw-r--r--clang-tidy/android/CloexecInotifyInit1Check.h7
-rw-r--r--clang-tidy/android/CloexecInotifyInitCheck.cpp7
-rw-r--r--clang-tidy/android/CloexecInotifyInitCheck.h7
-rw-r--r--clang-tidy/android/CloexecMemfdCreateCheck.cpp7
-rw-r--r--clang-tidy/android/CloexecMemfdCreateCheck.h7
-rw-r--r--clang-tidy/android/CloexecOpenCheck.cpp7
-rw-r--r--clang-tidy/android/CloexecOpenCheck.h7
-rw-r--r--clang-tidy/android/CloexecSocketCheck.cpp7
-rw-r--r--clang-tidy/android/CloexecSocketCheck.h7
-rw-r--r--clang-tidy/android/ComparisonInTempFailureRetryCheck.cpp7
-rw-r--r--clang-tidy/android/ComparisonInTempFailureRetryCheck.h9
-rw-r--r--clang-tidy/boost/BoostTidyModule.cpp7
-rw-r--r--clang-tidy/boost/UseToStringCheck.cpp7
-rw-r--r--clang-tidy/boost/UseToStringCheck.h9
-rw-r--r--clang-tidy/bugprone/ArgumentCommentCheck.cpp74
-rw-r--r--clang-tidy/bugprone/ArgumentCommentCheck.h23
-rw-r--r--clang-tidy/bugprone/AssertSideEffectCheck.cpp7
-rw-r--r--clang-tidy/bugprone/AssertSideEffectCheck.h9
-rw-r--r--clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp7
-rw-r--r--clang-tidy/bugprone/BoolPointerImplicitConversionCheck.h9
-rw-r--r--clang-tidy/bugprone/BugproneTidyModule.cpp7
-rw-r--r--clang-tidy/bugprone/CopyConstructorInitCheck.cpp7
-rw-r--r--clang-tidy/bugprone/CopyConstructorInitCheck.h9
-rw-r--r--clang-tidy/bugprone/DanglingHandleCheck.cpp12
-rw-r--r--clang-tidy/bugprone/DanglingHandleCheck.h9
-rw-r--r--clang-tidy/bugprone/ExceptionEscapeCheck.cpp174
-rw-r--r--clang-tidy/bugprone/ExceptionEscapeCheck.h15
-rw-r--r--clang-tidy/bugprone/FoldInitTypeCheck.cpp7
-rw-r--r--clang-tidy/bugprone/FoldInitTypeCheck.h9
-rw-r--r--clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp7
-rw-r--r--clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.h9
-rw-r--r--clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp7
-rw-r--r--clang-tidy/bugprone/ForwardingReferenceOverloadCheck.h9
-rw-r--r--clang-tidy/bugprone/InaccurateEraseCheck.cpp11
-rw-r--r--clang-tidy/bugprone/InaccurateEraseCheck.h9
-rw-r--r--clang-tidy/bugprone/IncorrectRoundingsCheck.cpp7
-rw-r--r--clang-tidy/bugprone/IncorrectRoundingsCheck.h9
-rw-r--r--clang-tidy/bugprone/IntegerDivisionCheck.cpp7
-rw-r--r--clang-tidy/bugprone/IntegerDivisionCheck.h9
-rw-r--r--clang-tidy/bugprone/LambdaFunctionNameCheck.cpp15
-rw-r--r--clang-tidy/bugprone/LambdaFunctionNameCheck.h12
-rw-r--r--clang-tidy/bugprone/MacroParenthesesCheck.cpp14
-rw-r--r--clang-tidy/bugprone/MacroParenthesesCheck.h12
-rw-r--r--clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.cpp13
-rw-r--r--clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.h12
-rw-r--r--clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp7
-rw-r--r--clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h9
-rw-r--r--clang-tidy/bugprone/MisplacedWideningCastCheck.cpp7
-rw-r--r--clang-tidy/bugprone/MisplacedWideningCastCheck.h9
-rw-r--r--clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp7
-rw-r--r--clang-tidy/bugprone/MoveForwardingReferenceCheck.h9
-rw-r--r--clang-tidy/bugprone/MultipleStatementMacroCheck.cpp7
-rw-r--r--clang-tidy/bugprone/MultipleStatementMacroCheck.h9
-rwxr-xr-xclang-tidy/bugprone/ParentVirtualCallCheck.cpp7
-rwxr-xr-xclang-tidy/bugprone/ParentVirtualCallCheck.h9
-rw-r--r--clang-tidy/bugprone/SizeofContainerCheck.cpp7
-rw-r--r--clang-tidy/bugprone/SizeofContainerCheck.h9
-rw-r--r--clang-tidy/bugprone/SizeofExpressionCheck.cpp64
-rw-r--r--clang-tidy/bugprone/SizeofExpressionCheck.h9
-rw-r--r--clang-tidy/bugprone/StringConstructorCheck.cpp10
-rw-r--r--clang-tidy/bugprone/StringConstructorCheck.h9
-rw-r--r--clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp119
-rw-r--r--clang-tidy/bugprone/StringIntegerAssignmentCheck.h9
-rw-r--r--clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.cpp7
-rw-r--r--clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.h9
-rw-r--r--clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp7
-rw-r--r--clang-tidy/bugprone/SuspiciousEnumUsageCheck.h9
-rw-r--r--clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp7
-rw-r--r--clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h9
-rw-r--r--clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp7
-rw-r--r--clang-tidy/bugprone/SuspiciousMissingCommaCheck.h9
-rw-r--r--clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp9
-rw-r--r--clang-tidy/bugprone/SuspiciousSemicolonCheck.h9
-rw-r--r--clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp7
-rw-r--r--clang-tidy/bugprone/SuspiciousStringCompareCheck.h9
-rw-r--r--clang-tidy/bugprone/SwappedArgumentsCheck.cpp7
-rw-r--r--clang-tidy/bugprone/SwappedArgumentsCheck.h9
-rw-r--r--clang-tidy/bugprone/TerminatingContinueCheck.cpp7
-rw-r--r--clang-tidy/bugprone/TerminatingContinueCheck.h9
-rw-r--r--clang-tidy/bugprone/ThrowKeywordMissingCheck.cpp7
-rw-r--r--clang-tidy/bugprone/ThrowKeywordMissingCheck.h9
-rw-r--r--clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp57
-rw-r--r--clang-tidy/bugprone/TooSmallLoopVariableCheck.h17
-rw-r--r--clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp7
-rw-r--r--clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h9
-rw-r--r--clang-tidy/bugprone/UndelegatedConstructorCheck.cpp7
-rw-r--r--clang-tidy/bugprone/UndelegatedConstructorCheck.h9
-rw-r--r--clang-tidy/bugprone/UnusedRaiiCheck.cpp7
-rw-r--r--clang-tidy/bugprone/UnusedRaiiCheck.h9
-rw-r--r--clang-tidy/bugprone/UnusedReturnValueCheck.cpp7
-rw-r--r--clang-tidy/bugprone/UnusedReturnValueCheck.h9
-rw-r--r--clang-tidy/bugprone/UseAfterMoveCheck.cpp7
-rw-r--r--clang-tidy/bugprone/UseAfterMoveCheck.h9
-rw-r--r--clang-tidy/bugprone/VirtualNearMissCheck.cpp7
-rw-r--r--clang-tidy/bugprone/VirtualNearMissCheck.h9
-rw-r--r--clang-tidy/cert/CERTTidyModule.cpp7
-rw-r--r--clang-tidy/cert/CommandProcessorCheck.cpp9
-rw-r--r--clang-tidy/cert/CommandProcessorCheck.h9
-rw-r--r--clang-tidy/cert/DontModifyStdNamespaceCheck.cpp7
-rw-r--r--clang-tidy/cert/DontModifyStdNamespaceCheck.h9
-rw-r--r--clang-tidy/cert/FloatLoopCounter.cpp7
-rw-r--r--clang-tidy/cert/FloatLoopCounter.h9
-rw-r--r--clang-tidy/cert/LICENSE.TXT4
-rw-r--r--clang-tidy/cert/LimitedRandomnessCheck.cpp7
-rw-r--r--clang-tidy/cert/LimitedRandomnessCheck.h9
-rw-r--r--clang-tidy/cert/PostfixOperatorCheck.cpp7
-rw-r--r--clang-tidy/cert/PostfixOperatorCheck.h9
-rw-r--r--clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp7
-rw-r--r--clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h9
-rw-r--r--clang-tidy/cert/SetLongJmpCheck.cpp28
-rw-r--r--clang-tidy/cert/SetLongJmpCheck.h14
-rw-r--r--clang-tidy/cert/StaticObjectExceptionCheck.cpp7
-rw-r--r--clang-tidy/cert/StaticObjectExceptionCheck.h9
-rw-r--r--clang-tidy/cert/StrToNumCheck.cpp9
-rw-r--r--clang-tidy/cert/StrToNumCheck.h9
-rw-r--r--clang-tidy/cert/ThrownExceptionTypeCheck.cpp7
-rw-r--r--clang-tidy/cert/ThrownExceptionTypeCheck.h9
-rw-r--r--clang-tidy/cert/VariadicFunctionDefCheck.cpp9
-rw-r--r--clang-tidy/cert/VariadicFunctionDefCheck.h9
-rw-r--r--clang-tidy/cppcoreguidelines/AvoidGotoCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/AvoidGotoCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp15
-rw-r--r--clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp20
-rw-r--r--clang-tidy/cppcoreguidelines/MacroUsageCheck.h10
-rw-r--r--clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/NoMallocCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/NoMallocCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/OwningMemoryCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp15
-rw-r--r--clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h10
-rw-r--r--clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/ProTypeVarargCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/SlicingCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/SlicingCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h7
-rw-r--r--clang-tidy/fuchsia/DefaultArgumentsCheck.cpp7
-rw-r--r--clang-tidy/fuchsia/DefaultArgumentsCheck.h9
-rw-r--r--clang-tidy/fuchsia/FuchsiaTidyModule.cpp7
-rw-r--r--clang-tidy/fuchsia/MultipleInheritanceCheck.cpp7
-rw-r--r--clang-tidy/fuchsia/MultipleInheritanceCheck.h9
-rw-r--r--clang-tidy/fuchsia/OverloadedOperatorCheck.cpp7
-rw-r--r--clang-tidy/fuchsia/OverloadedOperatorCheck.h9
-rw-r--r--clang-tidy/fuchsia/RestrictSystemIncludesCheck.cpp18
-rw-r--r--clang-tidy/fuchsia/RestrictSystemIncludesCheck.h12
-rw-r--r--clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp7
-rw-r--r--clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.h9
-rw-r--r--clang-tidy/fuchsia/TrailingReturnCheck.cpp7
-rw-r--r--clang-tidy/fuchsia/TrailingReturnCheck.h9
-rw-r--r--clang-tidy/fuchsia/VirtualInheritanceCheck.cpp7
-rw-r--r--clang-tidy/fuchsia/VirtualInheritanceCheck.h9
-rw-r--r--clang-tidy/google/AvoidCStyleCastsCheck.cpp7
-rw-r--r--clang-tidy/google/AvoidCStyleCastsCheck.h9
-rw-r--r--clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp7
-rw-r--r--clang-tidy/google/AvoidThrowingObjCExceptionCheck.h9
-rw-r--r--clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp88
-rw-r--r--clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h34
-rw-r--r--clang-tidy/google/CMakeLists.txt1
-rw-r--r--clang-tidy/google/DefaultArgumentsCheck.cpp7
-rw-r--r--clang-tidy/google/DefaultArgumentsCheck.h9
-rw-r--r--clang-tidy/google/ExplicitConstructorCheck.cpp7
-rw-r--r--clang-tidy/google/ExplicitConstructorCheck.h9
-rw-r--r--clang-tidy/google/ExplicitMakePairCheck.cpp7
-rw-r--r--clang-tidy/google/ExplicitMakePairCheck.h9
-rw-r--r--clang-tidy/google/FunctionNamingCheck.cpp17
-rw-r--r--clang-tidy/google/FunctionNamingCheck.h9
-rw-r--r--clang-tidy/google/GlobalNamesInHeadersCheck.cpp7
-rw-r--r--clang-tidy/google/GlobalNamesInHeadersCheck.h9
-rw-r--r--clang-tidy/google/GlobalVariableDeclarationCheck.cpp11
-rw-r--r--clang-tidy/google/GlobalVariableDeclarationCheck.h9
-rw-r--r--clang-tidy/google/GoogleTidyModule.cpp11
-rw-r--r--clang-tidy/google/IntegerTypesCheck.cpp11
-rw-r--r--clang-tidy/google/IntegerTypesCheck.h9
-rw-r--r--clang-tidy/google/NonConstReferences.cpp7
-rw-r--r--clang-tidy/google/NonConstReferences.h9
-rw-r--r--clang-tidy/google/OverloadedUnaryAndCheck.cpp7
-rw-r--r--clang-tidy/google/OverloadedUnaryAndCheck.h9
-rw-r--r--clang-tidy/google/TodoCommentCheck.cpp13
-rw-r--r--clang-tidy/google/TodoCommentCheck.h12
-rw-r--r--clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp7
-rw-r--r--clang-tidy/google/UnnamedNamespaceInHeaderCheck.h9
-rw-r--r--clang-tidy/google/UsingNamespaceDirectiveCheck.cpp7
-rw-r--r--clang-tidy/google/UsingNamespaceDirectiveCheck.h9
-rw-r--r--clang-tidy/hicpp/ExceptionBaseclassCheck.cpp7
-rw-r--r--clang-tidy/hicpp/ExceptionBaseclassCheck.h7
-rw-r--r--clang-tidy/hicpp/HICPPTidyModule.cpp7
-rw-r--r--clang-tidy/hicpp/LICENSE.TXT4
-rw-r--r--clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp7
-rw-r--r--clang-tidy/hicpp/MultiwayPathsCoveredCheck.h7
-rw-r--r--clang-tidy/hicpp/NoAssemblerCheck.cpp7
-rw-r--r--clang-tidy/hicpp/NoAssemblerCheck.h7
-rw-r--r--clang-tidy/hicpp/SignedBitwiseCheck.cpp7
-rw-r--r--clang-tidy/hicpp/SignedBitwiseCheck.h7
-rw-r--r--clang-tidy/llvm/CMakeLists.txt1
-rw-r--r--clang-tidy/llvm/HeaderGuardCheck.cpp7
-rw-r--r--clang-tidy/llvm/HeaderGuardCheck.h7
-rw-r--r--clang-tidy/llvm/IncludeOrderCheck.cpp20
-rw-r--r--clang-tidy/llvm/IncludeOrderCheck.h12
-rw-r--r--clang-tidy/llvm/LLVMTidyModule.cpp10
-rw-r--r--clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp135
-rw-r--r--clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.h64
-rw-r--r--clang-tidy/llvm/TwineLocalCheck.cpp7
-rw-r--r--clang-tidy/llvm/TwineLocalCheck.h9
-rw-r--r--clang-tidy/misc/DefinitionsInHeadersCheck.cpp7
-rw-r--r--clang-tidy/misc/DefinitionsInHeadersCheck.h9
-rw-r--r--clang-tidy/misc/MiscTidyModule.cpp7
-rw-r--r--clang-tidy/misc/MisplacedConstCheck.cpp7
-rw-r--r--clang-tidy/misc/MisplacedConstCheck.h9
-rw-r--r--clang-tidy/misc/NewDeleteOverloadsCheck.cpp7
-rw-r--r--clang-tidy/misc/NewDeleteOverloadsCheck.h9
-rw-r--r--clang-tidy/misc/NonCopyableObjects.cpp7
-rw-r--r--clang-tidy/misc/NonCopyableObjects.h9
-rw-r--r--clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.cpp18
-rw-r--r--clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.h9
-rw-r--r--clang-tidy/misc/RedundantExpressionCheck.cpp7
-rw-r--r--clang-tidy/misc/RedundantExpressionCheck.h9
-rw-r--r--clang-tidy/misc/StaticAssertCheck.cpp9
-rw-r--r--clang-tidy/misc/StaticAssertCheck.h9
-rw-r--r--clang-tidy/misc/ThrowByValueCatchByReferenceCheck.cpp7
-rw-r--r--clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h9
-rw-r--r--clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp7
-rw-r--r--clang-tidy/misc/UnconventionalAssignOperatorCheck.h9
-rw-r--r--clang-tidy/misc/UniqueptrResetReleaseCheck.cpp7
-rw-r--r--clang-tidy/misc/UniqueptrResetReleaseCheck.h9
-rw-r--r--clang-tidy/misc/UnusedAliasDeclsCheck.cpp7
-rw-r--r--clang-tidy/misc/UnusedAliasDeclsCheck.h9
-rw-r--r--clang-tidy/misc/UnusedParametersCheck.cpp7
-rw-r--r--clang-tidy/misc/UnusedParametersCheck.h9
-rw-r--r--clang-tidy/misc/UnusedUsingDeclsCheck.cpp12
-rw-r--r--clang-tidy/misc/UnusedUsingDeclsCheck.h9
-rw-r--r--clang-tidy/modernize/AvoidBindCheck.cpp9
-rw-r--r--clang-tidy/modernize/AvoidBindCheck.h9
-rw-r--r--clang-tidy/modernize/AvoidCArraysCheck.cpp16
-rw-r--r--clang-tidy/modernize/AvoidCArraysCheck.h9
-rw-r--r--clang-tidy/modernize/ConcatNestedNamespacesCheck.cpp8
-rw-r--r--clang-tidy/modernize/ConcatNestedNamespacesCheck.h9
-rw-r--r--clang-tidy/modernize/DeprecatedHeadersCheck.cpp17
-rw-r--r--clang-tidy/modernize/DeprecatedHeadersCheck.h12
-rw-r--r--clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp7
-rw-r--r--clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.h9
-rw-r--r--clang-tidy/modernize/LoopConvertCheck.cpp7
-rw-r--r--clang-tidy/modernize/LoopConvertCheck.h9
-rw-r--r--clang-tidy/modernize/LoopConvertUtils.cpp7
-rw-r--r--clang-tidy/modernize/LoopConvertUtils.h7
-rw-r--r--clang-tidy/modernize/MakeSharedCheck.cpp7
-rw-r--r--clang-tidy/modernize/MakeSharedCheck.h7
-rw-r--r--clang-tidy/modernize/MakeSmartPtrCheck.cpp19
-rw-r--r--clang-tidy/modernize/MakeSmartPtrCheck.h12
-rw-r--r--clang-tidy/modernize/MakeUniqueCheck.cpp7
-rw-r--r--clang-tidy/modernize/MakeUniqueCheck.h7
-rw-r--r--clang-tidy/modernize/ModernizeTidyModule.cpp7
-rw-r--r--clang-tidy/modernize/PassByValueCheck.cpp17
-rw-r--r--clang-tidy/modernize/PassByValueCheck.h12
-rw-r--r--clang-tidy/modernize/RawStringLiteralCheck.cpp7
-rw-r--r--clang-tidy/modernize/RawStringLiteralCheck.h9
-rw-r--r--clang-tidy/modernize/RedundantVoidArgCheck.cpp24
-rw-r--r--clang-tidy/modernize/RedundantVoidArgCheck.h9
-rw-r--r--clang-tidy/modernize/ReplaceAutoPtrCheck.cpp17
-rw-r--r--clang-tidy/modernize/ReplaceAutoPtrCheck.h12
-rw-r--r--clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp16
-rw-r--r--clang-tidy/modernize/ReplaceRandomShuffleCheck.h12
-rw-r--r--clang-tidy/modernize/ReturnBracedInitListCheck.cpp7
-rw-r--r--clang-tidy/modernize/ReturnBracedInitListCheck.h9
-rw-r--r--clang-tidy/modernize/ShrinkToFitCheck.cpp7
-rw-r--r--clang-tidy/modernize/ShrinkToFitCheck.h9
-rw-r--r--clang-tidy/modernize/UnaryStaticAssertCheck.cpp7
-rw-r--r--clang-tidy/modernize/UnaryStaticAssertCheck.h9
-rw-r--r--clang-tidy/modernize/UseAutoCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseAutoCheck.h9
-rw-r--r--clang-tidy/modernize/UseBoolLiteralsCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseBoolLiteralsCheck.h9
-rw-r--r--clang-tidy/modernize/UseDefaultMemberInitCheck.cpp18
-rw-r--r--clang-tidy/modernize/UseDefaultMemberInitCheck.h9
-rw-r--r--clang-tidy/modernize/UseEmplaceCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseEmplaceCheck.h9
-rw-r--r--clang-tidy/modernize/UseEqualsDefaultCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseEqualsDefaultCheck.h9
-rw-r--r--clang-tidy/modernize/UseEqualsDeleteCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseEqualsDeleteCheck.h9
-rw-r--r--clang-tidy/modernize/UseNodiscardCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseNodiscardCheck.h9
-rw-r--r--clang-tidy/modernize/UseNoexceptCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseNoexceptCheck.h9
-rw-r--r--clang-tidy/modernize/UseNullptrCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseNullptrCheck.h9
-rw-r--r--clang-tidy/modernize/UseOverrideCheck.cpp70
-rw-r--r--clang-tidy/modernize/UseOverrideCheck.h19
-rw-r--r--clang-tidy/modernize/UseTransparentFunctorsCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseTransparentFunctorsCheck.h9
-rw-r--r--clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseUncaughtExceptionsCheck.h9
-rw-r--r--clang-tidy/modernize/UseUsingCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseUsingCheck.h9
-rw-r--r--clang-tidy/mpi/BufferDerefCheck.cpp7
-rw-r--r--clang-tidy/mpi/BufferDerefCheck.h9
-rw-r--r--clang-tidy/mpi/MPITidyModule.cpp7
-rw-r--r--clang-tidy/mpi/TypeMismatchCheck.cpp7
-rw-r--r--clang-tidy/mpi/TypeMismatchCheck.h9
-rw-r--r--clang-tidy/objc/AvoidNSErrorInitCheck.cpp7
-rw-r--r--clang-tidy/objc/AvoidNSErrorInitCheck.h9
-rw-r--r--clang-tidy/objc/AvoidSpinlockCheck.cpp7
-rw-r--r--clang-tidy/objc/AvoidSpinlockCheck.h9
-rw-r--r--clang-tidy/objc/CMakeLists.txt1
-rw-r--r--clang-tidy/objc/ForbiddenSubclassingCheck.cpp7
-rw-r--r--clang-tidy/objc/ForbiddenSubclassingCheck.h9
-rw-r--r--clang-tidy/objc/ObjCTidyModule.cpp10
-rw-r--r--clang-tidy/objc/PropertyDeclarationCheck.cpp40
-rw-r--r--clang-tidy/objc/PropertyDeclarationCheck.h20
-rw-r--r--clang-tidy/objc/SuperSelfCheck.cpp127
-rw-r--r--clang-tidy/objc/SuperSelfCheck.h36
-rw-r--r--clang-tidy/openmp/CMakeLists.txt14
-rw-r--r--clang-tidy/openmp/ExceptionEscapeCheck.cpp84
-rw-r--r--clang-tidy/openmp/ExceptionEscapeCheck.h41
-rw-r--r--clang-tidy/openmp/OpenMPTidyModule.cpp41
-rw-r--r--clang-tidy/openmp/UseDefaultNoneCheck.cpp65
-rw-r--r--clang-tidy/openmp/UseDefaultNoneCheck.h36
-rw-r--r--clang-tidy/performance/FasterStringFindCheck.cpp7
-rw-r--r--clang-tidy/performance/FasterStringFindCheck.h9
-rw-r--r--clang-tidy/performance/ForRangeCopyCheck.cpp7
-rw-r--r--clang-tidy/performance/ForRangeCopyCheck.h9
-rw-r--r--clang-tidy/performance/ImplicitConversionInLoopCheck.cpp7
-rw-r--r--clang-tidy/performance/ImplicitConversionInLoopCheck.h9
-rw-r--r--clang-tidy/performance/InefficientAlgorithmCheck.cpp7
-rw-r--r--clang-tidy/performance/InefficientAlgorithmCheck.h9
-rw-r--r--clang-tidy/performance/InefficientStringConcatenationCheck.cpp7
-rw-r--r--clang-tidy/performance/InefficientStringConcatenationCheck.h9
-rw-r--r--clang-tidy/performance/InefficientVectorOperationCheck.cpp7
-rw-r--r--clang-tidy/performance/InefficientVectorOperationCheck.h9
-rw-r--r--clang-tidy/performance/MoveConstArgCheck.cpp7
-rw-r--r--clang-tidy/performance/MoveConstArgCheck.h9
-rw-r--r--clang-tidy/performance/MoveConstructorInitCheck.cpp16
-rw-r--r--clang-tidy/performance/MoveConstructorInitCheck.h12
-rw-r--r--clang-tidy/performance/NoexceptMoveConstructorCheck.cpp7
-rw-r--r--clang-tidy/performance/NoexceptMoveConstructorCheck.h9
-rw-r--r--clang-tidy/performance/PerformanceTidyModule.cpp9
-rw-r--r--clang-tidy/performance/TypePromotionInMathFnCheck.cpp16
-rw-r--r--clang-tidy/performance/TypePromotionInMathFnCheck.h12
-rw-r--r--clang-tidy/performance/UnnecessaryCopyInitialization.cpp7
-rw-r--r--clang-tidy/performance/UnnecessaryCopyInitialization.h9
-rw-r--r--clang-tidy/performance/UnnecessaryValueParamCheck.cpp15
-rw-r--r--clang-tidy/performance/UnnecessaryValueParamCheck.h12
-rw-r--r--clang-tidy/plugin/CMakeLists.txt1
-rw-r--r--clang-tidy/plugin/ClangTidyPlugin.cpp7
-rw-r--r--clang-tidy/portability/PortabilityTidyModule.cpp7
-rw-r--r--clang-tidy/portability/SIMDIntrinsicsCheck.cpp7
-rw-r--r--clang-tidy/portability/SIMDIntrinsicsCheck.h9
-rw-r--r--clang-tidy/readability/AvoidConstParamsInDecls.cpp7
-rw-r--r--clang-tidy/readability/AvoidConstParamsInDecls.h9
-rw-r--r--clang-tidy/readability/BracesAroundStatementsCheck.cpp7
-rw-r--r--clang-tidy/readability/BracesAroundStatementsCheck.h9
-rw-r--r--clang-tidy/readability/ConstReturnTypeCheck.cpp11
-rw-r--r--clang-tidy/readability/ConstReturnTypeCheck.h9
-rw-r--r--clang-tidy/readability/ContainerSizeEmptyCheck.cpp7
-rw-r--r--clang-tidy/readability/ContainerSizeEmptyCheck.h9
-rw-r--r--clang-tidy/readability/DeleteNullPointerCheck.cpp7
-rw-r--r--clang-tidy/readability/DeleteNullPointerCheck.h9
-rw-r--r--clang-tidy/readability/DeletedDefaultCheck.cpp7
-rw-r--r--clang-tidy/readability/DeletedDefaultCheck.h9
-rw-r--r--clang-tidy/readability/ElseAfterReturnCheck.cpp121
-rw-r--r--clang-tidy/readability/ElseAfterReturnCheck.h9
-rw-r--r--clang-tidy/readability/FunctionSizeCheck.cpp9
-rw-r--r--clang-tidy/readability/FunctionSizeCheck.h9
-rw-r--r--clang-tidy/readability/IdentifierNamingCheck.cpp16
-rw-r--r--clang-tidy/readability/IdentifierNamingCheck.h12
-rw-r--r--clang-tidy/readability/ImplicitBoolConversionCheck.cpp7
-rw-r--r--clang-tidy/readability/ImplicitBoolConversionCheck.h9
-rw-r--r--clang-tidy/readability/InconsistentDeclarationParameterNameCheck.cpp7
-rw-r--r--clang-tidy/readability/InconsistentDeclarationParameterNameCheck.h9
-rw-r--r--clang-tidy/readability/IsolateDeclarationCheck.cpp7
-rw-r--r--clang-tidy/readability/IsolateDeclarationCheck.h9
-rw-r--r--clang-tidy/readability/MagicNumbersCheck.cpp7
-rw-r--r--clang-tidy/readability/MagicNumbersCheck.h9
-rw-r--r--clang-tidy/readability/MisleadingIndentationCheck.cpp13
-rw-r--r--clang-tidy/readability/MisleadingIndentationCheck.h9
-rw-r--r--clang-tidy/readability/MisplacedArrayIndexCheck.cpp7
-rw-r--r--clang-tidy/readability/MisplacedArrayIndexCheck.h9
-rw-r--r--clang-tidy/readability/NamedParameterCheck.cpp7
-rw-r--r--clang-tidy/readability/NamedParameterCheck.h9
-rw-r--r--clang-tidy/readability/NamespaceCommentCheck.cpp12
-rw-r--r--clang-tidy/readability/NamespaceCommentCheck.h9
-rw-r--r--clang-tidy/readability/NonConstParameterCheck.cpp7
-rw-r--r--clang-tidy/readability/NonConstParameterCheck.h9
-rw-r--r--clang-tidy/readability/ReadabilityTidyModule.cpp7
-rw-r--r--clang-tidy/readability/RedundantControlFlowCheck.cpp7
-rw-r--r--clang-tidy/readability/RedundantControlFlowCheck.h9
-rw-r--r--clang-tidy/readability/RedundantDeclarationCheck.cpp7
-rw-r--r--clang-tidy/readability/RedundantDeclarationCheck.h9
-rw-r--r--clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp7
-rw-r--r--clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.h9
-rw-r--r--clang-tidy/readability/RedundantMemberInitCheck.cpp7
-rw-r--r--clang-tidy/readability/RedundantMemberInitCheck.h9
-rw-r--r--clang-tidy/readability/RedundantPreprocessorCheck.cpp14
-rw-r--r--clang-tidy/readability/RedundantPreprocessorCheck.h12
-rw-r--r--clang-tidy/readability/RedundantSmartptrGetCheck.cpp36
-rw-r--r--clang-tidy/readability/RedundantSmartptrGetCheck.h9
-rw-r--r--clang-tidy/readability/RedundantStringCStrCheck.cpp7
-rw-r--r--clang-tidy/readability/RedundantStringCStrCheck.h9
-rw-r--r--clang-tidy/readability/RedundantStringInitCheck.cpp7
-rw-r--r--clang-tidy/readability/RedundantStringInitCheck.h9
-rw-r--r--clang-tidy/readability/SimplifyBooleanExprCheck.cpp9
-rw-r--r--clang-tidy/readability/SimplifyBooleanExprCheck.h9
-rw-r--r--clang-tidy/readability/SimplifySubscriptExprCheck.cpp7
-rw-r--r--clang-tidy/readability/SimplifySubscriptExprCheck.h9
-rw-r--r--clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp7
-rw-r--r--clang-tidy/readability/StaticAccessedThroughInstanceCheck.h9
-rw-r--r--clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.cpp7
-rw-r--r--clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h9
-rw-r--r--clang-tidy/readability/StringCompareCheck.cpp9
-rw-r--r--clang-tidy/readability/StringCompareCheck.h9
-rw-r--r--clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp7
-rw-r--r--clang-tidy/readability/UniqueptrDeleteReleaseCheck.h9
-rw-r--r--clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp7
-rw-r--r--clang-tidy/readability/UppercaseLiteralSuffixCheck.h9
-rwxr-xr-xclang-tidy/rename_check.py7
-rw-r--r--clang-tidy/tool/CMakeLists.txt3
-rw-r--r--clang-tidy/tool/ClangTidyMain.cpp32
-rwxr-xr-xclang-tidy/tool/clang-tidy-diff.py188
-rwxr-xr-xclang-tidy/tool/run-clang-tidy.py25
-rw-r--r--clang-tidy/utils/ASTUtils.cpp7
-rw-r--r--clang-tidy/utils/ASTUtils.h7
-rw-r--r--clang-tidy/utils/CMakeLists.txt1
-rw-r--r--clang-tidy/utils/DeclRefExprUtils.cpp7
-rw-r--r--clang-tidy/utils/DeclRefExprUtils.h7
-rw-r--r--clang-tidy/utils/ExceptionAnalyzer.cpp262
-rw-r--r--clang-tidy/utils/ExceptionAnalyzer.h156
-rw-r--r--clang-tidy/utils/ExprSequence.cpp7
-rw-r--r--clang-tidy/utils/ExprSequence.h7
-rw-r--r--clang-tidy/utils/FixItHintUtils.cpp7
-rw-r--r--clang-tidy/utils/FixItHintUtils.h7
-rw-r--r--clang-tidy/utils/HeaderFileExtensionsUtils.cpp7
-rw-r--r--clang-tidy/utils/HeaderFileExtensionsUtils.h7
-rw-r--r--clang-tidy/utils/HeaderGuard.cpp15
-rw-r--r--clang-tidy/utils/HeaderGuard.h10
-rw-r--r--clang-tidy/utils/IncludeInserter.cpp7
-rw-r--r--clang-tidy/utils/IncludeInserter.h17
-rw-r--r--clang-tidy/utils/IncludeSorter.cpp7
-rw-r--r--clang-tidy/utils/IncludeSorter.h7
-rw-r--r--clang-tidy/utils/LexerUtils.cpp7
-rw-r--r--clang-tidy/utils/LexerUtils.h7
-rw-r--r--clang-tidy/utils/Matchers.h7
-rw-r--r--clang-tidy/utils/NamespaceAliaser.cpp7
-rw-r--r--clang-tidy/utils/NamespaceAliaser.h7
-rw-r--r--clang-tidy/utils/OptionsUtils.cpp9
-rw-r--r--clang-tidy/utils/OptionsUtils.h7
-rw-r--r--clang-tidy/utils/TypeTraits.cpp7
-rw-r--r--clang-tidy/utils/TypeTraits.h7
-rw-r--r--clang-tidy/utils/UsingInserter.cpp7
-rw-r--r--clang-tidy/utils/UsingInserter.h7
-rw-r--r--clang-tidy/zircon/TemporaryObjectsCheck.cpp7
-rw-r--r--clang-tidy/zircon/TemporaryObjectsCheck.h9
-rw-r--r--clang-tidy/zircon/ZirconTidyModule.cpp7
-rw-r--r--clangd/AST.cpp73
-rw-r--r--clangd/AST.h16
-rw-r--r--clangd/CMakeLists.txt36
-rw-r--r--clangd/Cancellation.cpp7
-rw-r--r--clangd/Cancellation.h7
-rw-r--r--clangd/ClangdLSPServer.cpp283
-rw-r--r--clangd/ClangdLSPServer.h23
-rw-r--r--clangd/ClangdServer.cpp218
-rw-r--r--clangd/ClangdServer.h62
-rw-r--r--clangd/ClangdUnit.cpp197
-rw-r--r--clangd/ClangdUnit.h52
-rw-r--r--clangd/CodeComplete.cpp590
-rw-r--r--clangd/CodeComplete.h51
-rw-r--r--clangd/CodeCompletionStrings.cpp7
-rw-r--r--clangd/CodeCompletionStrings.h7
-rw-r--r--clangd/Compiler.cpp42
-rw-r--r--clangd/Compiler.h33
-rw-r--r--clangd/Context.cpp7
-rw-r--r--clangd/Context.h7
-rw-r--r--clangd/Diagnostics.cpp237
-rw-r--r--clangd/Diagnostics.h43
-rw-r--r--clangd/DraftStore.cpp7
-rw-r--r--clangd/DraftStore.h7
-rw-r--r--clangd/ExpectedTypes.cpp12
-rw-r--r--clangd/ExpectedTypes.h7
-rw-r--r--clangd/FS.cpp7
-rw-r--r--clangd/FS.h7
-rw-r--r--clangd/FSProvider.cpp12
-rw-r--r--clangd/FSProvider.h7
-rw-r--r--clangd/FileDistance.cpp7
-rw-r--r--clangd/FileDistance.h7
-rw-r--r--clangd/FindSymbols.cpp72
-rw-r--r--clangd/FindSymbols.h14
-rw-r--r--clangd/Function.h7
-rw-r--r--clangd/FuzzyMatch.cpp36
-rw-r--r--clangd/FuzzyMatch.h7
-rw-r--r--clangd/GlobalCompilationDatabase.cpp63
-rw-r--r--clangd/GlobalCompilationDatabase.h12
-rw-r--r--clangd/Headers.cpp61
-rw-r--r--clangd/Headers.h34
-rw-r--r--clangd/IncludeFixer.cpp454
-rw-r--r--clangd/IncludeFixer.h100
-rw-r--r--clangd/JSONTransport.cpp7
-rw-r--r--clangd/Logger.cpp7
-rw-r--r--clangd/Logger.h7
-rw-r--r--clangd/Path.h7
-rw-r--r--clangd/Protocol.cpp218
-rw-r--r--clangd/Protocol.h148
-rw-r--r--clangd/Quality.cpp48
-rw-r--r--clangd/Quality.h14
-rw-r--r--clangd/RIFF.cpp7
-rw-r--r--clangd/RIFF.h7
-rw-r--r--clangd/Selection.cpp300
-rw-r--r--clangd/Selection.h123
-rw-r--r--clangd/SourceCode.cpp463
-rw-r--r--clangd/SourceCode.h114
-rw-r--r--clangd/StdSymbolMap.inc1513
-rw-r--r--clangd/TUScheduler.cpp193
-rw-r--r--clangd/TUScheduler.h37
-rw-r--r--clangd/Threading.cpp21
-rw-r--r--clangd/Threading.h17
-rw-r--r--clangd/Trace.cpp41
-rw-r--r--clangd/Trace.h7
-rw-r--r--clangd/Transport.h9
-rw-r--r--clangd/URI.cpp7
-rw-r--r--clangd/URI.h7
-rw-r--r--clangd/XRefs.cpp512
-rw-r--r--clangd/XRefs.h38
-rw-r--r--clangd/benchmarks/IndexBenchmark.cpp7
-rw-r--r--clangd/clients/clangd-vscode/.gitignore1
-rw-r--r--clangd/clients/clangd-vscode/package-lock.json2027
-rw-r--r--clangd/clients/clangd-vscode/package.json25
-rw-r--r--clangd/clients/clangd-vscode/src/extension.ts80
-rw-r--r--clangd/fuzzer/CMakeLists.txt20
-rw-r--r--clangd/fuzzer/DummyClangdMain.cpp18
-rw-r--r--clangd/fuzzer/clangd-fuzzer.cpp (renamed from clangd/fuzzer/ClangdFuzzer.cpp)14
-rwxr-xr-xclangd/include-mapping/gen_std.py252
-rwxr-xr-xclangd/include-mapping/test.py121
-rw-r--r--clangd/index/Background.cpp70
-rw-r--r--clangd/index/Background.h31
-rw-r--r--clangd/index/BackgroundIndexStorage.cpp18
-rw-r--r--clangd/index/CanonicalIncludes.cpp73
-rw-r--r--clangd/index/CanonicalIncludes.h13
-rw-r--r--clangd/index/FileIndex.cpp39
-rw-r--r--clangd/index/FileIndex.h16
-rw-r--r--clangd/index/Index.cpp154
-rw-r--r--clangd/index/Index.h433
-rw-r--r--clangd/index/IndexAction.cpp19
-rw-r--r--clangd/index/IndexAction.h9
-rw-r--r--clangd/index/MemIndex.cpp8
-rw-r--r--clangd/index/MemIndex.h7
-rw-r--r--clangd/index/Merge.cpp40
-rw-r--r--clangd/index/Merge.h7
-rw-r--r--clangd/index/Ref.cpp59
-rw-r--r--clangd/index/Ref.h121
-rw-r--r--clangd/index/Serialization.cpp24
-rw-r--r--clangd/index/Serialization.h9
-rw-r--r--clangd/index/Symbol.cpp71
-rw-r--r--clangd/index/Symbol.h238
-rw-r--r--clangd/index/SymbolCollector.cpp271
-rw-r--r--clangd/index/SymbolCollector.h29
-rw-r--r--clangd/index/SymbolID.cpp10
-rw-r--r--clangd/index/SymbolID.h29
-rw-r--r--clangd/index/SymbolLocation.cpp40
-rw-r--r--clangd/index/SymbolLocation.h94
-rw-r--r--clangd/index/SymbolOrigin.cpp25
-rw-r--r--clangd/index/SymbolOrigin.h48
-rw-r--r--clangd/index/YAMLSerialization.cpp13
-rw-r--r--clangd/index/dex/Dex.cpp106
-rw-r--r--clangd/index/dex/Dex.h11
-rw-r--r--clangd/index/dex/Iterator.cpp7
-rw-r--r--clangd/index/dex/Iterator.h7
-rw-r--r--clangd/index/dex/PostingList.cpp18
-rw-r--r--clangd/index/dex/PostingList.h7
-rw-r--r--clangd/index/dex/Token.h14
-rw-r--r--clangd/index/dex/Trigram.cpp7
-rw-r--r--clangd/index/dex/Trigram.h7
-rw-r--r--clangd/index/dex/dexp/Dexp.cpp7
-rw-r--r--clangd/indexer/CMakeLists.txt4
-rw-r--r--clangd/indexer/IndexerMain.cpp16
-rw-r--r--clangd/refactor/Tweak.cpp82
-rw-r--r--clangd/refactor/Tweak.h94
-rw-r--r--clangd/refactor/tweaks/CMakeLists.txt21
-rw-r--r--clangd/refactor/tweaks/SwapIfBranches.cpp99
-rw-r--r--clangd/test/CMakeLists.txt36
-rw-r--r--clangd/test/Inputs/BenchmarkHeader.h (renamed from test/clangd/Inputs/BenchmarkHeader.h)0
-rw-r--r--clangd/test/Inputs/BenchmarkSource.cpp (renamed from test/clangd/Inputs/BenchmarkSource.cpp)0
-rw-r--r--clangd/test/Inputs/background-index/compile_commands.json (renamed from test/clangd/Inputs/background-index/compile_commands.json)0
-rw-r--r--clangd/test/Inputs/background-index/definition.jsonrpc (renamed from test/clangd/Inputs/background-index/definition.jsonrpc)2
-rw-r--r--clangd/test/Inputs/background-index/foo.cpp (renamed from test/clangd/Inputs/background-index/foo.cpp)0
-rw-r--r--clangd/test/Inputs/background-index/foo.h (renamed from test/clangd/Inputs/background-index/foo.h)0
-rw-r--r--clangd/test/Inputs/requests.json (renamed from test/clangd/Inputs/requests.json)0
-rw-r--r--clangd/test/Inputs/symbols.test.yaml (renamed from test/clangd/Inputs/symbols.test.yaml)0
-rw-r--r--clangd/test/background-index.test (renamed from test/clangd/background-index.test)2
-rw-r--r--clangd/test/compile-commands-path-in-initialize.test (renamed from test/clangd/compile-commands-path-in-initialize.test)1
-rw-r--r--clangd/test/completion-auto-trigger.test (renamed from test/clangd/completion-auto-trigger.test)6
-rw-r--r--clangd/test/completion-snippets.test (renamed from test/clangd/completion-snippets.test)0
-rw-r--r--clangd/test/completion.test (renamed from test/clangd/completion.test)0
-rw-r--r--clangd/test/crash-non-added-files.test (renamed from test/clangd/crash-non-added-files.test)0
-rw-r--r--clangd/test/delimited-input-comment-at-the-end.test (renamed from test/clangd/delimited-input-comment-at-the-end.test)0
-rw-r--r--clangd/test/diagnostic-category.test (renamed from test/clangd/diagnostic-category.test)6
-rw-r--r--clangd/test/diagnostics-notes.test48
-rw-r--r--clangd/test/diagnostics.test55
-rw-r--r--clangd/test/did-change-configuration-params.test (renamed from test/clangd/did-change-configuration-params.test)10
-rw-r--r--clangd/test/execute-command.test (renamed from test/clangd/execute-command.test)6
-rw-r--r--clangd/test/exit-with-shutdown.test (renamed from test/clangd/exit-with-shutdown.test)0
-rw-r--r--clangd/test/exit-without-shutdown.test (renamed from test/clangd/exit-without-shutdown.test)0
-rw-r--r--clangd/test/filestatus.test (renamed from test/clangd/filestatus.test)0
-rw-r--r--clangd/test/fixits-codeaction.test (renamed from test/clangd/fixits-codeaction.test)20
-rw-r--r--clangd/test/fixits-command.test (renamed from test/clangd/fixits-command.test)10
-rw-r--r--clangd/test/fixits-embed-in-diagnostic.test (renamed from test/clangd/fixits-embed-in-diagnostic.test)6
-rw-r--r--clangd/test/formatting.test (renamed from test/clangd/formatting.test)0
-rw-r--r--clangd/test/hover.test (renamed from test/clangd/hover.test)0
-rw-r--r--clangd/test/index-tools.test (renamed from test/clangd/index-tools.test)0
-rw-r--r--clangd/test/initialize-params-invalid.test (renamed from test/clangd/initialize-params-invalid.test)0
-rw-r--r--clangd/test/initialize-params.test (renamed from test/clangd/initialize-params.test)5
-rw-r--r--clangd/test/initialize-sequence.test (renamed from test/clangd/initialize-sequence.test)0
-rw-r--r--clangd/test/input-mirror.test (renamed from test/clangd/input-mirror.test)0
-rw-r--r--clangd/test/lit.cfg.py19
-rw-r--r--clangd/test/lit.local.cfg (renamed from test/clangd/lit.local.cfg)0
-rw-r--r--clangd/test/lit.site.cfg.py.in28
-rw-r--r--clangd/test/protocol.test (renamed from test/clangd/protocol.test)0
-rw-r--r--clangd/test/references.test (renamed from test/clangd/references.test)0
-rw-r--r--clangd/test/rename.test (renamed from test/clangd/rename.test)2
-rw-r--r--clangd/test/signature-help.test (renamed from test/clangd/signature-help.test)0
-rw-r--r--clangd/test/spaces-in-delimited-input.test (renamed from test/clangd/spaces-in-delimited-input.test)0
-rw-r--r--clangd/test/symbol-info.test (renamed from test/clangd/symbol-info.test)0
-rw-r--r--clangd/test/symbols.test (renamed from test/clangd/symbols.test)0
-rw-r--r--clangd/test/test-uri-posix.test (renamed from test/clangd/test-uri-posix.test)0
-rw-r--r--clangd/test/test-uri-windows.test (renamed from test/clangd/test-uri-windows.test)0
-rw-r--r--clangd/test/textdocument-didchange-fail.test (renamed from test/clangd/textdocument-didchange-fail.test)0
-rw-r--r--clangd/test/too_large.test (renamed from test/clangd/too_large.test)0
-rw-r--r--clangd/test/trace.test (renamed from test/clangd/trace.test)31
-rw-r--r--clangd/test/tweaks-format.test50
-rw-r--r--clangd/test/type-hierarchy.test92
-rw-r--r--clangd/test/unsupported-method.test (renamed from test/clangd/unsupported-method.test)0
-rw-r--r--clangd/test/utf8.test32
-rw-r--r--clangd/test/xpc/initialize.test (renamed from test/clangd/xpc/initialize.test)0
-rw-r--r--clangd/test/xrefs.test (renamed from test/clangd/xrefs.test)49
-rw-r--r--clangd/tool/CMakeLists.txt3
-rw-r--r--clangd/tool/ClangdMain.cpp105
-rw-r--r--clangd/unittests/Annotations.cpp53
-rw-r--r--clangd/unittests/Annotations.h39
-rw-r--r--clangd/unittests/BackgroundIndexTests.cpp (renamed from unittests/clangd/BackgroundIndexTests.cpp)77
-rw-r--r--clangd/unittests/CMakeLists.txt (renamed from unittests/clangd/CMakeLists.txt)28
-rw-r--r--clangd/unittests/CancellationTests.cpp (renamed from unittests/clangd/CancellationTests.cpp)0
-rw-r--r--clangd/unittests/CanonicalIncludesTests.cpp62
-rw-r--r--clangd/unittests/ClangdTests.cpp (renamed from unittests/clangd/ClangdTests.cpp)160
-rw-r--r--clangd/unittests/ClangdUnitTests.cpp86
-rw-r--r--clangd/unittests/CodeCompleteTests.cpp (renamed from unittests/clangd/CodeCompleteTests.cpp)392
-rw-r--r--clangd/unittests/CodeCompletionStringsTests.cpp (renamed from unittests/clangd/CodeCompletionStringsTests.cpp)7
-rw-r--r--clangd/unittests/ContextTests.cpp (renamed from unittests/clangd/ContextTests.cpp)7
-rw-r--r--clangd/unittests/DexTests.cpp (renamed from unittests/clangd/DexTests.cpp)72
-rw-r--r--clangd/unittests/DiagnosticsTests.cpp773
-rw-r--r--clangd/unittests/DraftStoreTests.cpp (renamed from unittests/clangd/DraftStoreTests.cpp)13
-rw-r--r--clangd/unittests/ExpectedTypeTest.cpp (renamed from unittests/clangd/ExpectedTypeTest.cpp)8
-rw-r--r--clangd/unittests/FSTests.cpp (renamed from unittests/clangd/FSTests.cpp)7
-rw-r--r--clangd/unittests/FileDistanceTests.cpp (renamed from unittests/clangd/FileDistanceTests.cpp)7
-rw-r--r--clangd/unittests/FileIndexTests.cpp (renamed from unittests/clangd/FileIndexTests.cpp)100
-rw-r--r--clangd/unittests/FindSymbolsTests.cpp (renamed from unittests/clangd/FindSymbolsTests.cpp)74
-rw-r--r--clangd/unittests/FunctionTests.cpp (renamed from unittests/clangd/FunctionTests.cpp)9
-rw-r--r--clangd/unittests/FuzzyMatchTests.cpp (renamed from unittests/clangd/FuzzyMatchTests.cpp)39
-rw-r--r--clangd/unittests/GlobalCompilationDatabaseTests.cpp (renamed from unittests/clangd/GlobalCompilationDatabaseTests.cpp)60
-rw-r--r--clangd/unittests/HeadersTests.cpp (renamed from unittests/clangd/HeadersTests.cpp)45
-rw-r--r--clangd/unittests/IndexActionTests.cpp (renamed from unittests/clangd/IndexActionTests.cpp)37
-rw-r--r--clangd/unittests/IndexTests.cpp (renamed from unittests/clangd/IndexTests.cpp)75
-rw-r--r--clangd/unittests/JSONTransportTests.cpp (renamed from unittests/clangd/JSONTransportTests.cpp)11
-rw-r--r--clangd/unittests/Matchers.h (renamed from unittests/clangd/Matchers.h)74
-rw-r--r--clangd/unittests/PrintASTTests.cpp102
-rw-r--r--clangd/unittests/QualityTests.cpp (renamed from unittests/clangd/QualityTests.cpp)34
-rw-r--r--clangd/unittests/RIFFTests.cpp (renamed from unittests/clangd/RIFFTests.cpp)7
-rw-r--r--clangd/unittests/SelectionTests.cpp259
-rw-r--r--clangd/unittests/SerializationTests.cpp (renamed from unittests/clangd/SerializationTests.cpp)26
-rw-r--r--clangd/unittests/SourceCodeTests.cpp409
-rw-r--r--clangd/unittests/SymbolCollectorTests.cpp (renamed from unittests/clangd/SymbolCollectorTests.cpp)396
-rw-r--r--clangd/unittests/SymbolInfoTests.cpp (renamed from unittests/clangd/SymbolInfoTests.cpp)38
-rw-r--r--clangd/unittests/SyncAPI.cpp (renamed from unittests/clangd/SyncAPI.cpp)23
-rw-r--r--clangd/unittests/SyncAPI.h (renamed from unittests/clangd/SyncAPI.h)13
-rw-r--r--clangd/unittests/TUSchedulerTests.cpp (renamed from unittests/clangd/TUSchedulerTests.cpp)89
-rw-r--r--clangd/unittests/TestFS.cpp (renamed from unittests/clangd/TestFS.cpp)7
-rw-r--r--clangd/unittests/TestFS.h (renamed from unittests/clangd/TestFS.h)7
-rw-r--r--clangd/unittests/TestIndex.cpp118
-rw-r--r--clangd/unittests/TestIndex.h (renamed from unittests/clangd/TestIndex.h)20
-rw-r--r--clangd/unittests/TestScheme.h (renamed from unittests/clangd/TestScheme.h)0
-rw-r--r--clangd/unittests/TestTU.cpp (renamed from unittests/clangd/TestTU.cpp)42
-rw-r--r--clangd/unittests/TestTU.h (renamed from unittests/clangd/TestTU.h)22
-rw-r--r--clangd/unittests/ThreadingTests.cpp (renamed from unittests/clangd/ThreadingTests.cpp)7
-rw-r--r--clangd/unittests/TraceTests.cpp (renamed from unittests/clangd/TraceTests.cpp)7
-rw-r--r--clangd/unittests/TweakTests.cpp190
-rw-r--r--clangd/unittests/TypeHierarchyTests.cpp455
-rw-r--r--clangd/unittests/URITests.cpp (renamed from unittests/clangd/URITests.cpp)7
-rw-r--r--clangd/unittests/XRefsTests.cpp (renamed from unittests/clangd/XRefsTests.cpp)398
-rw-r--r--clangd/unittests/lit.cfg.py21
-rw-r--r--clangd/unittests/lit.site.cfg.py.in11
-rw-r--r--clangd/unittests/xpc/CMakeLists.txt (renamed from unittests/clangd/xpc/CMakeLists.txt)3
-rw-r--r--clangd/unittests/xpc/ConversionTests.cpp (renamed from unittests/clangd/xpc/ConversionTests.cpp)7
-rw-r--r--clangd/xpc/CMakeLists.txt4
-rw-r--r--clangd/xpc/Conversion.cpp7
-rw-r--r--clangd/xpc/Conversion.h7
-rw-r--r--clangd/xpc/XPCTransport.cpp7
-rw-r--r--clangd/xpc/framework/CMakeLists.txt3
-rw-r--r--clangd/xpc/framework/ClangdXPC.cpp7
-rw-r--r--clangd/xpc/test-client/ClangdXPCTestClient.cpp12
-rw-r--r--docs/README.txt15
-rw-r--r--docs/ReleaseNotes.rst297
-rw-r--r--docs/_static/clang-tools-extra-styles.css23
-rw-r--r--docs/_templates/layout.html3
-rw-r--r--docs/clang-doc.rst4
-rw-r--r--docs/clang-include-fixer.rst (renamed from docs/include-fixer.rst)8
-rw-r--r--docs/clang-rename.rst10
-rw-r--r--docs/clang-tidy.rst2
-rw-r--r--docs/clang-tidy/Contributing.rst513
-rw-r--r--docs/clang-tidy/Integrations.rst117
-rw-r--r--docs/clang-tidy/checks/abseil-duration-addition.rst21
-rw-r--r--docs/clang-tidy/checks/abseil-duration-conversion-cast.rst31
-rw-r--r--docs/clang-tidy/checks/abseil-duration-subtraction.rst2
-rw-r--r--docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst46
-rw-r--r--docs/clang-tidy/checks/abseil-time-comparison.rst23
-rw-r--r--docs/clang-tidy/checks/abseil-time-subtraction.rst39
-rw-r--r--docs/clang-tidy/checks/bugprone-argument-comment.rst155
-rw-r--r--[-rwxr-xr-x]docs/clang-tidy/checks/bugprone-parent-virtual-call.rst6
-rw-r--r--docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst17
-rw-r--r--docs/clang-tidy/checks/cppcoreguidelines-explicit-virtual-functions.rst10
-rw-r--r--docs/clang-tidy/checks/cppcoreguidelines-owning-memory.rst2
-rw-r--r--docs/clang-tidy/checks/google-objc-avoid-throwing-exception.rst2
-rw-r--r--docs/clang-tidy/checks/google-objc-global-variable-declaration.rst2
-rw-r--r--docs/clang-tidy/checks/google-readability-avoid-underscore-in-googletest-name.rst34
-rw-r--r--docs/clang-tidy/checks/list.rst11
-rw-r--r--docs/clang-tidy/checks/llvm-include-order.rst2
-rw-r--r--docs/clang-tidy/checks/llvm-namespace-comment.rst2
-rw-r--r--docs/clang-tidy/checks/llvm-prefer-isa-or-dyn-cast-in-conditionals.rst34
-rw-r--r--docs/clang-tidy/checks/misc-non-private-member-variables-in-classes.rst10
-rw-r--r--docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst4
-rw-r--r--docs/clang-tidy/checks/modernize-avoid-c-arrays.rst4
-rw-r--r--docs/clang-tidy/checks/modernize-pass-by-value.rst2
-rw-r--r--docs/clang-tidy/checks/modernize-use-emplace.rst2
-rw-r--r--docs/clang-tidy/checks/modernize-use-override.rst39
-rw-r--r--docs/clang-tidy/checks/objc-property-declaration.rst12
-rw-r--r--docs/clang-tidy/checks/objc-super-self.rst13
-rw-r--r--docs/clang-tidy/checks/openmp-exception-escape.rst25
-rw-r--r--docs/clang-tidy/checks/openmp-use-default-none.rst53
-rw-r--r--docs/clang-tidy/checks/portability-simd-intrinsics.rst2
-rw-r--r--docs/clang-tidy/checks/readability-else-after-return.rst4
-rw-r--r--docs/clang-tidy/checks/readability-magic-numbers.rst2
-rw-r--r--docs/clang-tidy/index.rst574
-rw-r--r--docs/clangd.rst163
-rw-r--r--docs/clangd/ApplyClangTidyFixInVSCode.gifbin0 -> 95232 bytes
-rw-r--r--docs/clangd/ApplyFixInVSCode.gifbin0 -> 73814 bytes
-rw-r--r--docs/clangd/CodeCompletionInEmacsCompanyMode.pngbin0 -> 10480 bytes
-rw-r--r--docs/clangd/CodeCompletionInSublimeText.pngbin0 -> 19894 bytes
-rw-r--r--docs/clangd/CodeCompletionInVSCode.pngbin0 -> 15094 bytes
-rw-r--r--docs/clangd/CodeCompletionInYCM.pngbin0 -> 17028 bytes
-rw-r--r--docs/clangd/CodeCompletionInsertsNamespaceQualifiersInVSCode.gifbin0 -> 110759 bytes
-rw-r--r--docs/clangd/DeveloperDocumentation.rst29
-rw-r--r--docs/clangd/DiagnosticsInEmacsEglot.pngbin0 -> 16634 bytes
-rw-r--r--docs/clangd/ErrorsInVSCode.pngbin0 -> 76993 bytes
-rw-r--r--docs/clangd/Extensions.rst175
-rw-r--r--docs/clangd/Features.rst267
-rw-r--r--docs/clangd/FindAllReferencesInVSCode.gifbin0 -> 76027 bytes
-rw-r--r--docs/clangd/FormatSelectionInVSCode.gifbin0 -> 167887 bytes
-rw-r--r--docs/clangd/GoToDefinitionInVSCode.gifbin0 -> 123395 bytes
-rw-r--r--docs/clangd/Installation.rst371
-rw-r--r--docs/clangd/NavigationWithBreadcrumbsInVSCode.gifbin0 -> 123365 bytes
-rw-r--r--docs/clangd/OutlineInVSCode.pngbin0 -> 15443 bytes
-rw-r--r--docs/clangd/SignatureHelpInVSCode.gifbin0 -> 36923 bytes
-rw-r--r--docs/clangd/index.rst27
-rw-r--r--docs/conf.py6
-rw-r--r--docs/doxygen.cfg.in2
-rw-r--r--docs/index.rst12
-rw-r--r--docs/modularize.rst8
-rw-r--r--docs/pp-trace.rst142
-rw-r--r--modularize/CoverageChecker.cpp7
-rw-r--r--modularize/CoverageChecker.h7
-rw-r--r--modularize/Modularize.cpp7
-rw-r--r--modularize/Modularize.h7
-rw-r--r--modularize/ModularizeUtilities.cpp7
-rw-r--r--modularize/ModularizeUtilities.h7
-rw-r--r--modularize/ModuleAssistant.cpp7
-rw-r--r--modularize/PreprocessorTracker.cpp7
-rw-r--r--modularize/PreprocessorTracker.h7
-rw-r--r--pp-trace/PPCallbacksTracker.cpp221
-rw-r--r--pp-trace/PPCallbacksTracker.h178
-rw-r--r--pp-trace/PPTrace.cpp243
-rw-r--r--test/CMakeLists.txt52
-rw-r--r--test/Unit/lit.cfg.py (renamed from test/Unit/lit.cfg)0
-rw-r--r--test/Unit/lit.site.cfg.py.in (renamed from test/Unit/lit.site.cfg.in)2
-rw-r--r--test/clang-apply-replacements/Inputs/basic/file1.yaml41
-rw-r--r--test/clang-apply-replacements/Inputs/basic/file2.yaml17
-rw-r--r--test/clang-apply-replacements/Inputs/conflict/file1.yaml33
-rw-r--r--test/clang-apply-replacements/Inputs/conflict/file2.yaml33
-rw-r--r--test/clang-apply-replacements/Inputs/conflict/file3.yaml17
-rw-r--r--test/clang-apply-replacements/Inputs/crlf/file1.yaml17
-rw-r--r--test/clang-apply-replacements/Inputs/format/no.yaml17
-rw-r--r--test/clang-apply-replacements/Inputs/format/yes.yaml41
-rw-r--r--test/clang-apply-replacements/Inputs/identical/file1.yaml17
-rw-r--r--test/clang-apply-replacements/Inputs/identical/file2.yaml17
-rw-r--r--test/clang-apply-replacements/Inputs/order-dependent/file1.yaml17
-rw-r--r--test/clang-apply-replacements/Inputs/order-dependent/file2.yaml17
-rw-r--r--test/clang-change-namespace/Inputs/fake-std.h (renamed from test/change-namespace/Inputs/fake-std.h)0
-rw-r--r--test/clang-change-namespace/lambda-function.cpp (renamed from test/change-namespace/lambda-function.cpp)0
-rw-r--r--test/clang-change-namespace/macro.cpp (renamed from test/change-namespace/macro.cpp)0
-rw-r--r--test/clang-change-namespace/simple-move.cpp (renamed from test/change-namespace/simple-move.cpp)0
-rw-r--r--test/clang-change-namespace/white-list.cpp (renamed from test/change-namespace/white-list.cpp)0
-rw-r--r--test/clang-include-fixer/Inputs/database_template.json (renamed from test/include-fixer/Inputs/database_template.json)0
-rw-r--r--test/clang-include-fixer/Inputs/fake_yaml_db.yaml (renamed from test/include-fixer/Inputs/fake_yaml_db.yaml)2
-rw-r--r--test/clang-include-fixer/Inputs/merge/a.yaml (renamed from test/include-fixer/Inputs/merge/a.yaml)0
-rw-r--r--test/clang-include-fixer/Inputs/merge/b.yaml (renamed from test/include-fixer/Inputs/merge/b.yaml)0
-rw-r--r--test/clang-include-fixer/commandline_options.cpp (renamed from test/include-fixer/commandline_options.cpp)0
-rw-r--r--test/clang-include-fixer/exit_on_fatal.cpp (renamed from test/include-fixer/exit_on_fatal.cpp)0
-rw-r--r--test/clang-include-fixer/fixeddb.cpp (renamed from test/include-fixer/fixeddb.cpp)0
-rw-r--r--test/clang-include-fixer/include_path.cpp19
-rw-r--r--test/clang-include-fixer/merge.test (renamed from test/include-fixer/merge.test)0
-rw-r--r--test/clang-include-fixer/multiple_fixes.cpp13
-rw-r--r--test/clang-include-fixer/prefix_variable.cpp (renamed from test/include-fixer/prefix_variable.cpp)0
-rw-r--r--test/clang-include-fixer/query_symbol.cpp (renamed from test/include-fixer/query_symbol.cpp)0
-rw-r--r--test/clang-include-fixer/ranking.cpp (renamed from test/include-fixer/ranking.cpp)2
-rw-r--r--test/clang-include-fixer/yaml_fuzzy.cpp (renamed from test/include-fixer/yaml_fuzzy.cpp)2
-rw-r--r--test/clang-include-fixer/yamldb.cpp (renamed from test/include-fixer/yamldb.cpp)0
-rw-r--r--test/clang-include-fixer/yamldb_autodetect.cpp (renamed from test/include-fixer/yamldb_autodetect.cpp)0
-rw-r--r--test/clang-tidy/Inputs/Headers/stdio.h18
-rw-r--r--test/clang-tidy/Inputs/absl/time/time.h20
-rw-r--r--test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/a.h1
-rw-r--r--test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/b.h2
-rw-r--r--test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/c.h2
-rw-r--r--test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/module.modulemap3
-rw-r--r--test/clang-tidy/abseil-duration-addition.cpp98
-rw-r--r--test/clang-tidy/abseil-duration-conversion-cast.cpp95
-rw-r--r--test/clang-tidy/abseil-duration-unnecessary-conversion.cpp111
-rw-r--r--test/clang-tidy/abseil-time-comparison.cpp129
-rw-r--r--test/clang-tidy/abseil-time-subtraction.cpp117
-rw-r--r--test/clang-tidy/abseil-upgrade-duration-conversions.cpp33
-rw-r--r--test/clang-tidy/alternative-fixes.cpp9
-rw-r--r--test/clang-tidy/bugprone-argument-comment-literals.cpp124
-rw-r--r--test/clang-tidy/bugprone-exception-escape-openmp.cpp29
-rw-r--r--[-rwxr-xr-x]test/clang-tidy/bugprone-parent-virtual-call.cpp0
-rw-r--r--test/clang-tidy/bugprone-sizeof-expression.cpp29
-rw-r--r--test/clang-tidy/bugprone-string-constructor.cpp8
-rw-r--r--test/clang-tidy/bugprone-string-integer-assignment.cpp60
-rw-r--r--test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp23
-rw-r--r--test/clang-tidy/bugprone-too-small-loop-variable.cpp6
-rwxr-xr-xtest/clang-tidy/check_clang_tidy.py7
-rw-r--r--test/clang-tidy/clang-tidy-diff.cpp1
-rw-r--r--test/clang-tidy/clang-tidy-mac-libcxx.cpp2
-rw-r--r--test/clang-tidy/cppcoreguidelines-macro-usage.cpp2
-rw-r--r--test/clang-tidy/expand-modular-headers-ppcallbacks.cpp35
-rw-r--r--test/clang-tidy/export-diagnostics.cpp13
-rw-r--r--test/clang-tidy/google-objc-function-naming.m10
-rw-r--r--test/clang-tidy/google-objc-global-variable-declaration.mm10
-rw-r--r--test/clang-tidy/google-runtime-int.m32
-rw-r--r--test/clang-tidy/llvm-prefer-isa-or-dyn-cast-in-conditionals.cpp132
-rw-r--r--test/clang-tidy/misc-non-private-member-variables-in-classes.cpp17
-rw-r--r--test/clang-tidy/modernize-avoid-bind.cpp44
-rw-r--r--test/clang-tidy/modernize-avoid-c-arrays-ignores-main.cpp18
-rw-r--r--test/clang-tidy/modernize-avoid-c-arrays-ignores-three-arg-main.cpp20
-rw-r--r--test/clang-tidy/modernize-redundant-void-arg.cpp7
-rw-r--r--test/clang-tidy/modernize-use-default-member-init-assignment.cpp8
-rw-r--r--test/clang-tidy/modernize-use-default-member-init.cpp18
-rw-r--r--test/clang-tidy/modernize-use-override-no-destructors.cpp16
-rw-r--r--test/clang-tidy/modernize-use-override-with-macro.cpp70
-rw-r--r--test/clang-tidy/modernize-use-override-with-no-macro-inscope.cpp28
-rw-r--r--test/clang-tidy/nolint.cpp3
-rw-r--r--test/clang-tidy/objc-property-declaration.m1
-rw-r--r--test/clang-tidy/objc-super-self.m86
-rw-r--r--test/clang-tidy/openmp-exception-escape.cpp132
-rw-r--r--test/clang-tidy/openmp-use-default-none.cpp160
-rw-r--r--test/clang-tidy/readability-avoid-underscore-in-googletest-name.cpp108
-rw-r--r--test/clang-tidy/readability-else-after-return.cpp12
-rw-r--r--test/clang-tidy/readability-misleading-indentation.cpp13
-rw-r--r--test/clang-tidy/readability-redundant-smartptr-get-msvc.cpp94
-rw-r--r--test/clang-tidy/readability-uppercase-literal-suffix-float16.cpp51
-rw-r--r--test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp28
-rw-r--r--test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp15
-rw-r--r--test/clang-tidy/run-clang-tidy.cpp1
-rw-r--r--test/clang-tidy/static-analyzer-config.cpp2
-rw-r--r--test/clangd/diagnostics.test28
-rw-r--r--test/include-fixer/include_path.cpp19
-rw-r--r--test/include-fixer/multiple_fixes.cpp13
-rw-r--r--test/lit.cfg.py (renamed from test/lit.cfg)8
-rw-r--r--test/lit.site.cfg.py.in (renamed from test/lit.site.cfg.in)3
-rw-r--r--test/modularize/ProblemsInconsistent.modularize10
-rw-r--r--test/pp-trace/pp-trace-conditional.cpp50
-rw-r--r--test/pp-trace/pp-trace-filter.cpp17
-rw-r--r--test/pp-trace/pp-trace-ident.cpp2
-rw-r--r--test/pp-trace/pp-trace-include.cpp2
-rw-r--r--test/pp-trace/pp-trace-macro.cpp6
-rw-r--r--test/pp-trace/pp-trace-modules.cpp2
-rw-r--r--test/pp-trace/pp-trace-pragma-general.cpp2
-rw-r--r--test/pp-trace/pp-trace-pragma-ms.cpp2
-rw-r--r--test/pp-trace/pp-trace-pragma-opencl.cpp2
-rw-r--r--tool-template/ToolTemplate.cpp7
-rw-r--r--unittests/CMakeLists.txt14
-rw-r--r--unittests/clang-apply-replacements/ApplyReplacementsTest.cpp8
-rw-r--r--unittests/clang-change-namespace/CMakeLists.txt (renamed from unittests/change-namespace/CMakeLists.txt)6
-rw-r--r--unittests/clang-change-namespace/ChangeNamespaceTests.cpp (renamed from unittests/change-namespace/ChangeNamespaceTests.cpp)7
-rw-r--r--unittests/clang-doc/BitcodeTest.cpp7
-rw-r--r--unittests/clang-doc/ClangDocTest.cpp7
-rw-r--r--unittests/clang-doc/ClangDocTest.h7
-rw-r--r--unittests/clang-doc/MDGeneratorTest.cpp7
-rw-r--r--unittests/clang-doc/MergeTest.cpp7
-rw-r--r--unittests/clang-doc/SerializeTest.cpp7
-rw-r--r--unittests/clang-doc/YAMLGeneratorTest.cpp7
-rw-r--r--unittests/clang-include-fixer/CMakeLists.txt (renamed from unittests/include-fixer/CMakeLists.txt)6
-rw-r--r--unittests/clang-include-fixer/FuzzySymbolIndexTests.cpp (renamed from unittests/include-fixer/FuzzySymbolIndexTests.cpp)7
-rw-r--r--unittests/clang-include-fixer/IncludeFixerTest.cpp (renamed from unittests/include-fixer/IncludeFixerTest.cpp)11
-rw-r--r--unittests/clang-include-fixer/find-all-symbols/CMakeLists.txt (renamed from unittests/include-fixer/find-all-symbols/CMakeLists.txt)2
-rw-r--r--unittests/clang-include-fixer/find-all-symbols/FindAllSymbolsTests.cpp (renamed from unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp)7
-rw-r--r--unittests/clang-move/ClangMoveTests.cpp11
-rw-r--r--unittests/clang-query/QueryEngineTest.cpp9
-rw-r--r--unittests/clang-query/QueryParserTest.cpp7
-rw-r--r--unittests/clang-tidy/CMakeLists.txt3
-rw-r--r--unittests/clang-tidy/ClangTidyTest.h29
-rw-r--r--unittests/clang-tidy/IncludeInserterTest.cpp18
-rw-r--r--unittests/clang-tidy/NamespaceAliaserTest.cpp7
-rw-r--r--unittests/clang-tidy/ObjCModuleTest.cpp7
-rw-r--r--unittests/clang-tidy/OverlappingReplacementsTest.cpp7
-rw-r--r--unittests/clang-tidy/UsingInserterTest.cpp7
-rw-r--r--unittests/clangd/Annotations.cpp87
-rw-r--r--unittests/clangd/Annotations.h72
-rw-r--r--unittests/clangd/ClangdUnitTests.cpp341
-rw-r--r--unittests/clangd/SourceCodeTests.cpp146
-rw-r--r--unittests/clangd/TestIndex.cpp71
-rw-r--r--unittests/include/common/VirtualFileHelper.h7
1100 files changed, 26084 insertions, 9365 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 37e3e87e..d32b4b9f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,20 +1,15 @@
-option(CLANGD_BUILD_XPC "Build XPC Support For Clangd." OFF)
-if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
- set(CLANGD_BUILD_XPC ON CACHE BOOL "" FORCE)
-endif ()
-
add_subdirectory(clang-apply-replacements)
add_subdirectory(clang-reorder-fields)
add_subdirectory(modularize)
add_subdirectory(clang-tidy)
add_subdirectory(clang-tidy-vs)
-add_subdirectory(change-namespace)
+add_subdirectory(clang-change-namespace)
add_subdirectory(clang-doc)
-add_subdirectory(clang-query)
+add_subdirectory(clang-include-fixer)
add_subdirectory(clang-move)
+add_subdirectory(clang-query)
add_subdirectory(clangd)
-add_subdirectory(include-fixer)
add_subdirectory(pp-trace)
add_subdirectory(tool-template)
diff --git a/LICENSE.TXT b/LICENSE.TXT
index 44864d4d..24806ab4 100644
--- a/LICENSE.TXT
+++ b/LICENSE.TXT
@@ -1,5 +1,240 @@
==============================================================================
-LLVM Release License
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+==============================================================================
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+==============================================================================
+Software from third parties included in the LLVM Project:
+==============================================================================
+The LLVM Project contains third party software which is under different license
+terms. All such code will be identified clearly using at least one of two
+mechanisms:
+1) It will be in a separate directory tree with its own `LICENSE.txt` or
+ `LICENSE` file at the top containing the specific license and restrictions
+ which apply to that software, or
+2) It will contain specific license and restriction terms at the top of every
+ file.
+
+==============================================================================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
==============================================================================
University of Illinois/NCSA
Open Source License
@@ -41,23 +276,3 @@ CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.
-
-==============================================================================
-The LLVM software contains code written by third parties. Such software will
-have its own individual LICENSE.TXT file in the directory in which it appears.
-This file will describe the copyrights, license, and restrictions which apply
-to that code.
-
-The disclaimer of warranty in the University of Illinois Open Source License
-applies to all code in the LLVM Distribution, and nothing in any of the
-other licenses gives permission to use the names of the LLVM Team or the
-University of Illinois to endorse or promote products derived from this
-Software.
-
-The following pieces of software have additional or alternate copyrights,
-licenses, and/or restrictions:
-
-Program Directory
-------- ---------
-clang-tidy clang-tidy/cert
-clang-tidy clang-tidy/hicpp
diff --git a/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h b/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h
index da9ae0c9..34f5c75d 100644
--- a/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h
+++ b/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h
@@ -1,9 +1,8 @@
//===-- ApplyReplacements.h - Deduplicate and apply replacements -- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
diff --git a/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp b/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
index b4799225..4a6707ba 100644
--- a/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
+++ b/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
@@ -1,9 +1,8 @@
//===-- ApplyReplacements.cpp - Apply and deduplicate replacements --------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
@@ -20,6 +19,7 @@
#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/Core/Diagnostic.h"
#include "clang/Tooling/DiagnosticsYaml.h"
#include "clang/Tooling/ReplacementsYaml.h"
#include "llvm/ADT/ArrayRef.h"
@@ -170,9 +170,11 @@ groupReplacements(const TUReplacements &TUs, const TUDiagnostics &TUDs,
for (const auto &TU : TUDs)
for (const auto &D : TU.Diagnostics)
- for (const auto &Fix : D.Fix)
- for (const tooling::Replacement &R : Fix.second)
- AddToGroup(R, true);
+ if (const auto *ChoosenFix = tooling::selectFirstFix(D)) {
+ for (const auto &Fix : *ChoosenFix)
+ for (const tooling::Replacement &R : Fix.second)
+ AddToGroup(R, true);
+ }
// Sort replacements per file to keep consistent behavior when
// clang-apply-replacements run on differents machine.
diff --git a/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp b/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp
index 8977b131..ffd1e65c 100644
--- a/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp
+++ b/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp
@@ -1,9 +1,8 @@
//===-- ClangApplyReplacementsMain.cpp - Main file for the tool -----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
diff --git a/change-namespace/CMakeLists.txt b/clang-change-namespace/CMakeLists.txt
index 17830642..17830642 100644
--- a/change-namespace/CMakeLists.txt
+++ b/clang-change-namespace/CMakeLists.txt
diff --git a/change-namespace/ChangeNamespace.cpp b/clang-change-namespace/ChangeNamespace.cpp
index 7a710318..eb732639 100644
--- a/change-namespace/ChangeNamespace.cpp
+++ b/clang-change-namespace/ChangeNamespace.cpp
@@ -1,9 +1,8 @@
//===-- ChangeNamespace.cpp - Change namespace implementation -------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "ChangeNamespace.h"
diff --git a/change-namespace/ChangeNamespace.h b/clang-change-namespace/ChangeNamespace.h
index cfe3cbc7..293d5ce8 100644
--- a/change-namespace/ChangeNamespace.h
+++ b/clang-change-namespace/ChangeNamespace.h
@@ -1,9 +1,8 @@
//===-- ChangeNamespace.h -- Change namespace ------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/change-namespace/tool/CMakeLists.txt b/clang-change-namespace/tool/CMakeLists.txt
index be4b830e..be4b830e 100644
--- a/change-namespace/tool/CMakeLists.txt
+++ b/clang-change-namespace/tool/CMakeLists.txt
diff --git a/change-namespace/tool/ClangChangeNamespace.cpp b/clang-change-namespace/tool/ClangChangeNamespace.cpp
index 180e8c38..d5f06552 100644
--- a/change-namespace/tool/ClangChangeNamespace.cpp
+++ b/clang-change-namespace/tool/ClangChangeNamespace.cpp
@@ -1,9 +1,8 @@
-//===-- ClangIncludeFixer.cpp - Standalone change namespace ---------------===//
+//===-- ClangChangeNamespace.cpp - Standalone change namespace ------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
// This tool can be used to change the surrounding namespaces of class/function
diff --git a/clang-doc/BitcodeReader.cpp b/clang-doc/BitcodeReader.cpp
index 20cdc508..04e5d7d2 100644
--- a/clang-doc/BitcodeReader.cpp
+++ b/clang-doc/BitcodeReader.cpp
@@ -1,9 +1,8 @@
//===-- BitcodeReader.cpp - ClangDoc Bitcode Reader ------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-doc/BitcodeReader.h b/clang-doc/BitcodeReader.h
index ec3f6b0f..2642a2c7 100644
--- a/clang-doc/BitcodeReader.h
+++ b/clang-doc/BitcodeReader.h
@@ -1,9 +1,8 @@
//===-- BitcodeReader.h - ClangDoc Bitcode Reader --------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clang-doc/BitcodeWriter.cpp b/clang-doc/BitcodeWriter.cpp
index bc990fa7..232c3f13 100644
--- a/clang-doc/BitcodeWriter.cpp
+++ b/clang-doc/BitcodeWriter.cpp
@@ -1,9 +1,8 @@
//===-- BitcodeWriter.cpp - ClangDoc Bitcode Writer ------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-doc/BitcodeWriter.h b/clang-doc/BitcodeWriter.h
index 12a31ea5..9deba830 100644
--- a/clang-doc/BitcodeWriter.h
+++ b/clang-doc/BitcodeWriter.h
@@ -1,9 +1,8 @@
//===-- BitcodeWriter.h - ClangDoc Bitcode Writer --------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clang-doc/ClangDoc.cpp b/clang-doc/ClangDoc.cpp
index a11c5840..ec32f012 100644
--- a/clang-doc/ClangDoc.cpp
+++ b/clang-doc/ClangDoc.cpp
@@ -1,9 +1,8 @@
//===-- ClangDoc.cpp - ClangDoc ---------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clang-doc/ClangDoc.h b/clang-doc/ClangDoc.h
index 59e9a92b..f3820d2c 100644
--- a/clang-doc/ClangDoc.h
+++ b/clang-doc/ClangDoc.h
@@ -1,9 +1,8 @@
//===-- ClangDoc.h - ClangDoc -----------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clang-doc/Generators.cpp b/clang-doc/Generators.cpp
index 5a0d0c5c..e3b672ad 100644
--- a/clang-doc/Generators.cpp
+++ b/clang-doc/Generators.cpp
@@ -1,9 +1,8 @@
-//===---- Generator.cpp - Generator Registry ---------------------*- C++-*-===//
+//===-- Generators.cpp - Generator Registry ----------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-doc/Generators.h b/clang-doc/Generators.h
index 90a81e82..25e5e0b4 100644
--- a/clang-doc/Generators.h
+++ b/clang-doc/Generators.h
@@ -1,9 +1,8 @@
//===-- Generators.h - ClangDoc Generator ----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
// Generator classes for converting declaration information into documentation
diff --git a/clang-doc/MDGenerator.cpp b/clang-doc/MDGenerator.cpp
index 5deb510e..d7784200 100644
--- a/clang-doc/MDGenerator.cpp
+++ b/clang-doc/MDGenerator.cpp
@@ -1,9 +1,8 @@
//===-- MDGenerator.cpp - Markdown Generator --------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-doc/Mapper.cpp b/clang-doc/Mapper.cpp
index 0b00bd1f..654096d8 100644
--- a/clang-doc/Mapper.cpp
+++ b/clang-doc/Mapper.cpp
@@ -1,9 +1,8 @@
//===-- Mapper.cpp - ClangDoc Mapper ----------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-doc/Mapper.h b/clang-doc/Mapper.h
index a0b1ac22..fe2a8e2b 100644
--- a/clang-doc/Mapper.h
+++ b/clang-doc/Mapper.h
@@ -1,9 +1,8 @@
//===-- Mapper.h - ClangDoc Mapper ------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clang-doc/Representation.cpp b/clang-doc/Representation.cpp
index eacf11a8..398d1025 100644
--- a/clang-doc/Representation.cpp
+++ b/clang-doc/Representation.cpp
@@ -1,9 +1,8 @@
///===-- Representation.cpp - ClangDoc Representation -----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clang-doc/Representation.h b/clang-doc/Representation.h
index 48f8f3d8..ad12ec4d 100644
--- a/clang-doc/Representation.h
+++ b/clang-doc/Representation.h
@@ -1,9 +1,8 @@
///===-- Representation.h - ClangDoc Representation -------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clang-doc/Serialize.cpp b/clang-doc/Serialize.cpp
index eb72c19c..2bd54cf2 100644
--- a/clang-doc/Serialize.cpp
+++ b/clang-doc/Serialize.cpp
@@ -1,9 +1,8 @@
-//===-- Serializer.cpp - ClangDoc Serializer --------------------*- C++ -*-===//
+//===-- Serialize.cpp - ClangDoc Serializer ---------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-doc/Serialize.h b/clang-doc/Serialize.h
index d89dac80..3a2c93df 100644
--- a/clang-doc/Serialize.h
+++ b/clang-doc/Serialize.h
@@ -1,9 +1,8 @@
//===-- Serializer.h - ClangDoc Serializer ----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clang-doc/YAMLGenerator.cpp b/clang-doc/YAMLGenerator.cpp
index e0939019..94fb9f98 100644
--- a/clang-doc/YAMLGenerator.cpp
+++ b/clang-doc/YAMLGenerator.cpp
@@ -1,9 +1,8 @@
-//===-- ClangDocYAML.cpp - ClangDoc YAML -----------------------*- C++ -*-===//
+//===-- YAMLGenerator.cpp - ClangDoc YAML -----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
// Implementation of the YAML generator, converting decl info into YAML output.
diff --git a/clang-doc/tool/CMakeLists.txt b/clang-doc/tool/CMakeLists.txt
index d7f28cf6..35f99ea0 100644
--- a/clang-doc/tool/CMakeLists.txt
+++ b/clang-doc/tool/CMakeLists.txt
@@ -1,6 +1,6 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
-add_clang_executable(clang-doc
+add_clang_tool(clang-doc
ClangDocMain.cpp
)
diff --git a/clang-doc/tool/ClangDocMain.cpp b/clang-doc/tool/ClangDocMain.cpp
index 71ca2d91..2b44869d 100644
--- a/clang-doc/tool/ClangDocMain.cpp
+++ b/clang-doc/tool/ClangDocMain.cpp
@@ -1,9 +1,8 @@
//===-- ClangDocMain.cpp - ClangDoc -----------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/include-fixer/CMakeLists.txt b/clang-include-fixer/CMakeLists.txt
index f27f7403..f27f7403 100644
--- a/include-fixer/CMakeLists.txt
+++ b/clang-include-fixer/CMakeLists.txt
diff --git a/include-fixer/FuzzySymbolIndex.cpp b/clang-include-fixer/FuzzySymbolIndex.cpp
index d91f4552..099d7389 100644
--- a/include-fixer/FuzzySymbolIndex.cpp
+++ b/clang-include-fixer/FuzzySymbolIndex.cpp
@@ -1,9 +1,8 @@
//===--- FuzzySymbolIndex.cpp - Lookup symbols for autocomplete -*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "FuzzySymbolIndex.h"
diff --git a/include-fixer/FuzzySymbolIndex.h b/clang-include-fixer/FuzzySymbolIndex.h
index 245191eb..27bfadf1 100644
--- a/include-fixer/FuzzySymbolIndex.h
+++ b/clang-include-fixer/FuzzySymbolIndex.h
@@ -1,9 +1,8 @@
//===--- FuzzySymbolIndex.h - Lookup symbols for autocomplete ---*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -32,7 +31,7 @@ namespace include_fixer {
// Implementations may choose to truncate results, refuse short queries, etc.
class FuzzySymbolIndex : public SymbolIndex {
public:
- // Loads the specified include-fixer database and returns an index serving it.
+ // Loads the specified clang-include-fixer database and returns an index serving it.
static llvm::Expected<std::unique_ptr<FuzzySymbolIndex>>
createFromYAML(llvm::StringRef File);
diff --git a/include-fixer/InMemorySymbolIndex.cpp b/clang-include-fixer/InMemorySymbolIndex.cpp
index 14753bd9..e7858939 100644
--- a/include-fixer/InMemorySymbolIndex.cpp
+++ b/clang-include-fixer/InMemorySymbolIndex.cpp
@@ -1,9 +1,8 @@
//===-- InMemorySymbolIndex.cpp--------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/InMemorySymbolIndex.h b/clang-include-fixer/InMemorySymbolIndex.h
index 0e1310e3..bea8be91 100644
--- a/include-fixer/InMemorySymbolIndex.h
+++ b/clang-include-fixer/InMemorySymbolIndex.h
@@ -1,9 +1,8 @@
//===-- InMemorySymbolIndex.h -----------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/include-fixer/IncludeFixer.cpp b/clang-include-fixer/IncludeFixer.cpp
index c6dfd7fc..d364021f 100644
--- a/include-fixer/IncludeFixer.cpp
+++ b/clang-include-fixer/IncludeFixer.cpp
@@ -1,9 +1,8 @@
//===-- IncludeFixer.cpp - Include inserter based on sema callbacks -------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -17,7 +16,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
-#define DEBUG_TYPE "include-fixer"
+#define DEBUG_TYPE "clang-include-fixer"
using namespace clang;
@@ -349,8 +348,8 @@ IncludeFixerSemaSource::query(StringRef Query, StringRef ScopedQualifiers,
//
// We use conservative behavior for detecting the same unidentified symbol
// here. The symbols which have the same ScopedQualifier and RawIdentifier
- // are considered equal. So that include-fixer avoids false positives, and
- // always adds missing qualifiers to correct symbols.
+ // are considered equal. So that clang-include-fixer avoids false positives,
+ // and always adds missing qualifiers to correct symbols.
if (!GenerateDiagnostics && !QuerySymbolInfos.empty()) {
if (ScopedQualifiers == QuerySymbolInfos.front().ScopedQualifiers &&
Query == QuerySymbolInfos.front().RawIdentifier) {
diff --git a/include-fixer/IncludeFixer.h b/clang-include-fixer/IncludeFixer.h
index 13092a34..ccab65d2 100644
--- a/include-fixer/IncludeFixer.h
+++ b/clang-include-fixer/IncludeFixer.h
@@ -1,9 +1,8 @@
//===-- IncludeFixer.h - Include inserter -----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -68,7 +67,7 @@ private:
///
/// \param Code The source code.
/// \param Context The context which contains all information for creating
-/// include-fixer replacements.
+/// clang-include-fixer replacements.
/// \param Style clang-format style being used.
/// \param AddQualifiers Whether we should add qualifiers to all instances of
/// an unidentified symbol.
diff --git a/include-fixer/IncludeFixerContext.cpp b/clang-include-fixer/IncludeFixerContext.cpp
index 8106e20e..a9fef45c 100644
--- a/include-fixer/IncludeFixerContext.cpp
+++ b/clang-include-fixer/IncludeFixerContext.cpp
@@ -1,9 +1,8 @@
//===-- IncludeFixerContext.cpp - Include fixer context ---------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/IncludeFixerContext.h b/clang-include-fixer/IncludeFixerContext.h
index 3c44574b..bbb87e2b 100644
--- a/include-fixer/IncludeFixerContext.h
+++ b/clang-include-fixer/IncludeFixerContext.h
@@ -1,9 +1,8 @@
//===-- IncludeFixerContext.h - Include fixer context -----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/SymbolIndex.h b/clang-include-fixer/SymbolIndex.h
index f3e6ecd9..ca04d50a 100644
--- a/include-fixer/SymbolIndex.h
+++ b/clang-include-fixer/SymbolIndex.h
@@ -1,9 +1,8 @@
//===-- SymbolIndex.h - Interface for symbol-header matching ----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/SymbolIndexManager.cpp b/clang-include-fixer/SymbolIndexManager.cpp
index e4312bf1..7b827536 100644
--- a/include-fixer/SymbolIndexManager.cpp
+++ b/clang-include-fixer/SymbolIndexManager.cpp
@@ -1,9 +1,8 @@
//===-- SymbolIndexManager.cpp - Managing multiple SymbolIndices-*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -14,7 +13,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/Path.h"
-#define DEBUG_TYPE "include-fixer"
+#define DEBUG_TYPE "clang-include-fixer"
namespace clang {
namespace include_fixer {
diff --git a/include-fixer/SymbolIndexManager.h b/clang-include-fixer/SymbolIndexManager.h
index 12963ddb..ca2d7399 100644
--- a/include-fixer/SymbolIndexManager.h
+++ b/clang-include-fixer/SymbolIndexManager.h
@@ -1,9 +1,8 @@
//===-- SymbolIndexManager.h - Managing multiple SymbolIndices --*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/YamlSymbolIndex.cpp b/clang-include-fixer/YamlSymbolIndex.cpp
index f3f2d5a8..de72e9a9 100644
--- a/include-fixer/YamlSymbolIndex.cpp
+++ b/clang-include-fixer/YamlSymbolIndex.cpp
@@ -1,9 +1,8 @@
//===-- YamlSymbolIndex.cpp -----------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/YamlSymbolIndex.h b/clang-include-fixer/YamlSymbolIndex.h
index d5d699a2..3c4f5144 100644
--- a/include-fixer/YamlSymbolIndex.h
+++ b/clang-include-fixer/YamlSymbolIndex.h
@@ -1,9 +1,8 @@
//===-- YamlSymbolIndex.h ---------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/CMakeLists.txt b/clang-include-fixer/find-all-symbols/CMakeLists.txt
index c5fe19bf..c5fe19bf 100644
--- a/include-fixer/find-all-symbols/CMakeLists.txt
+++ b/clang-include-fixer/find-all-symbols/CMakeLists.txt
diff --git a/include-fixer/find-all-symbols/FindAllMacros.cpp b/clang-include-fixer/find-all-symbols/FindAllMacros.cpp
index 3dc2b96f..ed1bc2f4 100644
--- a/include-fixer/find-all-symbols/FindAllMacros.cpp
+++ b/clang-include-fixer/find-all-symbols/FindAllMacros.cpp
@@ -1,9 +1,8 @@
//===-- FindAllMacros.cpp - find all macros ---------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/FindAllMacros.h b/clang-include-fixer/find-all-symbols/FindAllMacros.h
index 10b4a696..5aaf3884 100644
--- a/include-fixer/find-all-symbols/FindAllMacros.h
+++ b/clang-include-fixer/find-all-symbols/FindAllMacros.h
@@ -1,10 +1,9 @@
//===-- FindAllMacros.h - find all macros -----------------------*- C++ -*-===//
//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/FindAllSymbols.cpp b/clang-include-fixer/find-all-symbols/FindAllSymbols.cpp
index bd5032d0..bb6a3fa9 100644
--- a/include-fixer/find-all-symbols/FindAllSymbols.cpp
+++ b/clang-include-fixer/find-all-symbols/FindAllSymbols.cpp
@@ -1,9 +1,8 @@
//===-- FindAllSymbols.cpp - find all symbols--------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/FindAllSymbols.h b/clang-include-fixer/find-all-symbols/FindAllSymbols.h
index fca849f5..d78da668 100644
--- a/include-fixer/find-all-symbols/FindAllSymbols.h
+++ b/clang-include-fixer/find-all-symbols/FindAllSymbols.h
@@ -1,9 +1,8 @@
//===-- FindAllSymbols.h - find all symbols----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/FindAllSymbolsAction.cpp b/clang-include-fixer/find-all-symbols/FindAllSymbolsAction.cpp
index bc00547a..9f1d31dc 100644
--- a/include-fixer/find-all-symbols/FindAllSymbolsAction.cpp
+++ b/clang-include-fixer/find-all-symbols/FindAllSymbolsAction.cpp
@@ -1,9 +1,8 @@
//===-- FindAllSymbolsAction.cpp - find all symbols action --------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/FindAllSymbolsAction.h b/clang-include-fixer/find-all-symbols/FindAllSymbolsAction.h
index 7be9fe2b..ccffa4b3 100644
--- a/include-fixer/find-all-symbols/FindAllSymbolsAction.h
+++ b/clang-include-fixer/find-all-symbols/FindAllSymbolsAction.h
@@ -1,9 +1,8 @@
//===-- FindAllSymbolsAction.h - find all symbols action --------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/HeaderMapCollector.cpp b/clang-include-fixer/find-all-symbols/HeaderMapCollector.cpp
index 379df81a..6ec49cae 100644
--- a/include-fixer/find-all-symbols/HeaderMapCollector.cpp
+++ b/clang-include-fixer/find-all-symbols/HeaderMapCollector.cpp
@@ -1,9 +1,8 @@
//===-- HeaderMapCoolector.h - find all symbols------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/HeaderMapCollector.h b/clang-include-fixer/find-all-symbols/HeaderMapCollector.h
index 65edd754..21358275 100644
--- a/include-fixer/find-all-symbols/HeaderMapCollector.h
+++ b/clang-include-fixer/find-all-symbols/HeaderMapCollector.h
@@ -1,9 +1,8 @@
//===-- HeaderMapCoolector.h - find all symbols------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/PathConfig.cpp b/clang-include-fixer/find-all-symbols/PathConfig.cpp
index de799b99..4f1ebc77 100644
--- a/include-fixer/find-all-symbols/PathConfig.cpp
+++ b/clang-include-fixer/find-all-symbols/PathConfig.cpp
@@ -1,10 +1,9 @@
//===-- PathConfig.cpp - Process paths of symbols ---------------*- C++ -*-===//
//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/PathConfig.h b/clang-include-fixer/find-all-symbols/PathConfig.h
index 50de5480..9c430f25 100644
--- a/include-fixer/find-all-symbols/PathConfig.h
+++ b/clang-include-fixer/find-all-symbols/PathConfig.h
@@ -1,10 +1,9 @@
//===-- PathConfig.h - Process paths of symbols -----------------*- C++ -*-===//
//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/PragmaCommentHandler.cpp b/clang-include-fixer/find-all-symbols/PragmaCommentHandler.cpp
index 0242d385..49489752 100644
--- a/include-fixer/find-all-symbols/PragmaCommentHandler.cpp
+++ b/clang-include-fixer/find-all-symbols/PragmaCommentHandler.cpp
@@ -1,9 +1,8 @@
//===-- PragmaCommentHandler.cpp - find all symbols -----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/PragmaCommentHandler.h b/clang-include-fixer/find-all-symbols/PragmaCommentHandler.h
index 9eb4972c..752c82f5 100644
--- a/include-fixer/find-all-symbols/PragmaCommentHandler.h
+++ b/clang-include-fixer/find-all-symbols/PragmaCommentHandler.h
@@ -1,9 +1,8 @@
//===-- PragmaCommentHandler.h - find all symbols----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp b/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
index 4a49479b..0d0bbd9f 100644
--- a/include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
+++ b/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
@@ -1,9 +1,8 @@
//===-- STLPostfixHeaderMap.h - hardcoded STL header map --------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/STLPostfixHeaderMap.h b/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.h
index 162580d8..49bc5f30 100644
--- a/include-fixer/find-all-symbols/STLPostfixHeaderMap.h
+++ b/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.h
@@ -1,9 +1,8 @@
//===-- STLPostfixHeaderMap.h - hardcoded header map for STL ----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/SymbolInfo.cpp b/clang-include-fixer/find-all-symbols/SymbolInfo.cpp
index 00bfbe5f..e5b4dba4 100644
--- a/include-fixer/find-all-symbols/SymbolInfo.cpp
+++ b/clang-include-fixer/find-all-symbols/SymbolInfo.cpp
@@ -1,9 +1,8 @@
//===-- SymbolInfo.cpp - Symbol Info ----------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/SymbolInfo.h b/clang-include-fixer/find-all-symbols/SymbolInfo.h
index 92d360d3..6def1c70 100644
--- a/include-fixer/find-all-symbols/SymbolInfo.h
+++ b/clang-include-fixer/find-all-symbols/SymbolInfo.h
@@ -1,9 +1,8 @@
//===-- SymbolInfo.h - Symbol Info ------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/SymbolReporter.h b/clang-include-fixer/find-all-symbols/SymbolReporter.h
index 2398234c..25e86219 100644
--- a/include-fixer/find-all-symbols/SymbolReporter.h
+++ b/clang-include-fixer/find-all-symbols/SymbolReporter.h
@@ -1,9 +1,8 @@
//===--- SymbolReporter.h - Symbol Reporter ---------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/tool/CMakeLists.txt b/clang-include-fixer/find-all-symbols/tool/CMakeLists.txt
index 64278ad1..64278ad1 100644
--- a/include-fixer/find-all-symbols/tool/CMakeLists.txt
+++ b/clang-include-fixer/find-all-symbols/tool/CMakeLists.txt
diff --git a/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp b/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
index e09a5aaf..dbbe0738 100644
--- a/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
+++ b/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
@@ -1,9 +1,8 @@
//===-- FindAllSymbolsMain.cpp - find all symbols tool ----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/find-all-symbols/tool/run-find-all-symbols.py b/clang-include-fixer/find-all-symbols/tool/run-find-all-symbols.py
index 461d959b..5e9dde72 100755
--- a/include-fixer/find-all-symbols/tool/run-find-all-symbols.py
+++ b/clang-include-fixer/find-all-symbols/tool/run-find-all-symbols.py
@@ -2,10 +2,9 @@
#
#=- run-find-all-symbols.py - Parallel find-all-symbols runner -*- python -*-=#
#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
+# 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
#
#===------------------------------------------------------------------------===#
diff --git a/include-fixer/plugin/CMakeLists.txt b/clang-include-fixer/plugin/CMakeLists.txt
index df792ea1..df792ea1 100644
--- a/include-fixer/plugin/CMakeLists.txt
+++ b/clang-include-fixer/plugin/CMakeLists.txt
diff --git a/include-fixer/plugin/IncludeFixerPlugin.cpp b/clang-include-fixer/plugin/IncludeFixerPlugin.cpp
index 0d6bdb75..bc9c4973 100644
--- a/include-fixer/plugin/IncludeFixerPlugin.cpp
+++ b/clang-include-fixer/plugin/IncludeFixerPlugin.cpp
@@ -1,9 +1,8 @@
//===- IncludeFixerPlugin.cpp - clang-include-fixer as a clang plugin -----===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/tool/CMakeLists.txt b/clang-include-fixer/tool/CMakeLists.txt
index 207995aa..207995aa 100644
--- a/include-fixer/tool/CMakeLists.txt
+++ b/clang-include-fixer/tool/CMakeLists.txt
diff --git a/include-fixer/tool/ClangIncludeFixer.cpp b/clang-include-fixer/tool/ClangIncludeFixer.cpp
index d9d97d23..15f6ed29 100644
--- a/include-fixer/tool/ClangIncludeFixer.cpp
+++ b/clang-include-fixer/tool/ClangIncludeFixer.cpp
@@ -1,9 +1,8 @@
//===-- ClangIncludeFixer.cpp - Standalone include fixer ------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -367,8 +366,8 @@ int includeFixerMain(int argc, const char **argv) {
}
// We leave an empty symbol range as we don't know the range of the symbol
- // being queried in this mode. include-fixer won't add namespace qualifiers
- // if the symbol range is empty, which also fits this case.
+ // being queried in this mode. clang-include-fixer won't add namespace
+ // qualifiers if the symbol range is empty, which also fits this case.
IncludeFixerContext::QuerySymbolInfo Symbol;
Symbol.RawIdentifier = QuerySymbol;
auto Context =
@@ -384,9 +383,10 @@ int includeFixerMain(int argc, const char **argv) {
if (tool.run(&Factory) != 0) {
// We suppress all Clang diagnostics (because they would be wrong,
- // include-fixer does custom recovery) but still want to give some feedback
- // in case there was a compiler error we couldn't recover from. The most
- // common case for this is a #include in the file that couldn't be found.
+ // clang-include-fixer does custom recovery) but still want to give some
+ // feedback in case there was a compiler error we couldn't recover from.
+ // The most common case for this is a #include in the file that couldn't be
+ // found.
llvm::errs() << "Fatal compiler error occurred while parsing file!"
" (incorrect include paths?)\n";
return 1;
diff --git a/include-fixer/tool/clang-include-fixer-test.el b/clang-include-fixer/tool/clang-include-fixer-test.el
index d66d5300..d66d5300 100644
--- a/include-fixer/tool/clang-include-fixer-test.el
+++ b/clang-include-fixer/tool/clang-include-fixer-test.el
diff --git a/include-fixer/tool/clang-include-fixer.el b/clang-include-fixer/tool/clang-include-fixer.el
index 1512402d..84fff624 100644
--- a/include-fixer/tool/clang-include-fixer.el
+++ b/clang-include-fixer/tool/clang-include-fixer.el
@@ -8,7 +8,7 @@
;; This package allows Emacs users to invoke the 'clang-include-fixer' within
;; Emacs. 'clang-include-fixer' provides an automated way of adding #include
;; directives for missing symbols in one translation unit, see
-;; <http://clang.llvm.org/extra/include-fixer.html>.
+;; <http://clang.llvm.org/extra/clang-include-fixer.html>.
;;; Code:
@@ -243,7 +243,7 @@ return nil. Buffer restrictions are ignored."
t))))))))))))
(defun clang-include-fixer--add-header (stdout)
- "Analyse the result of include-fixer stored in STDOUT.
+ "Analyse the result of clang-include-fixer stored in STDOUT.
Add a missing header if there is any. If there are multiple
possible headers the user can select one of them to be included.
Temporarily highlight the affected symbols. Asynchronously call
@@ -317,7 +317,7 @@ They are replaced by the single element selected by the user."
(when overlays
(goto-char (clang-include-fixer--closest-overlay overlays)))
(cl-flet ((header (info) (let-alist info .Header)))
- ;; The header-infos is already sorted by include-fixer.
+ ;; The header-infos is already sorted by clang-include-fixer.
(let* ((headers (mapcar #'header .HeaderInfos))
(header (completing-read
(clang-include-fixer--format-message
diff --git a/include-fixer/tool/clang-include-fixer.py b/clang-include-fixer/tool/clang-include-fixer.py
index 0e9306d1..4c38f71e 100644
--- a/include-fixer/tool/clang-include-fixer.py
+++ b/clang-include-fixer/tool/clang-include-fixer.py
@@ -2,12 +2,14 @@
# - Change 'binary' if clang-include-fixer is not on the path (see below).
# - Add to your .vimrc:
#
-# noremap <leader>cf :pyf path/to/llvm/source/tools/clang/tools/extra/include-fixer/tool/clang-include-fixer.py<cr>
+# noremap <leader>cf :pyf path/to/llvm/source/tools/clang/tools/extra/clang-include-fixer/tool/clang-include-fixer.py<cr>
#
-# This enables clang-include-fixer for NORMAL and VISUAL mode. Change "<leader>cf"
-# to another binding if you need clang-include-fixer on a different key.
+# This enables clang-include-fixer for NORMAL and VISUAL mode. Change
+# "<leader>cf" to another binding if you need clang-include-fixer on a
+# different key.
#
-# To set up clang-include-fixer, see http://clang.llvm.org/extra/include-fixer.html
+# To set up clang-include-fixer, see
+# http://clang.llvm.org/extra/clang-include-fixer.html
#
# With this integration you can press the bound key and clang-include-fixer will
# be run on the current buffer.
@@ -76,7 +78,7 @@ def GetUserSelection(message, headers, maximum_suggested_headers):
raise Exception()
except Exception:
# Show a new prompt on invalid option instead of aborting so that users
- # don't need to wait for another include-fixer run.
+ # don't need to wait for another clang-include-fixer run.
print >> sys.stderr, "Invalid option:", res
return GetUserSelection(message, headers, maximum_suggested_headers)
return headers[idx - 1]
@@ -170,7 +172,7 @@ def main():
print "The file is fine, no need to add a header."
return
symbol = query_symbol_infos[0]["RawIdentifier"]
- # The header_infos is already sorted by include-fixer.
+ # The header_infos is already sorted by clang-include-fixer.
header_infos = include_fixer_context["HeaderInfos"]
# Deduplicate headers while keeping the order, so that the same header would
# not be suggested twice.
diff --git a/clang-move/CMakeLists.txt b/clang-move/CMakeLists.txt
index 37a305d3..c63127ea 100644
--- a/clang-move/CMakeLists.txt
+++ b/clang-move/CMakeLists.txt
@@ -3,7 +3,7 @@ set(LLVM_LINK_COMPONENTS
)
add_clang_library(clangMove
- ClangMove.cpp
+ Move.cpp
HelperDeclRefGraph.cpp
LINK_LIBS
diff --git a/clang-move/HelperDeclRefGraph.cpp b/clang-move/HelperDeclRefGraph.cpp
index 28200e0b..b47e7f4e 100644
--- a/clang-move/HelperDeclRefGraph.cpp
+++ b/clang-move/HelperDeclRefGraph.cpp
@@ -1,14 +1,13 @@
-//===-- UsedHelperDeclFinder.cpp - AST-based call graph for helper decls --===//
+//===-- HelperDeclRefGraph.cpp - AST-based call graph for helper decls ----===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "HelperDeclRefGraph.h"
-#include "ClangMove.h"
+#include "Move.h"
#include "clang/AST/Decl.h"
#include "llvm/Support/Debug.h"
#include <vector>
diff --git a/clang-move/HelperDeclRefGraph.h b/clang-move/HelperDeclRefGraph.h
index 11b3c9c1..a9cc22df 100644
--- a/clang-move/HelperDeclRefGraph.h
+++ b/clang-move/HelperDeclRefGraph.h
@@ -1,9 +1,8 @@
//===-- UsedHelperDeclFinder.h - AST-based call graph for helper decls ----===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-move/ClangMove.cpp b/clang-move/Move.cpp
index 3ab3d4eb..efb67c68 100644
--- a/clang-move/ClangMove.cpp
+++ b/clang-move/Move.cpp
@@ -1,13 +1,12 @@
-//===-- ClangMove.cpp - Implement ClangMove functationalities ---*- C++ -*-===//
+//===-- Move.cpp - Implement ClangMove functationalities --------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "ClangMove.h"
+#include "Move.h"
#include "HelperDeclRefGraph.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Basic/SourceManager.h"
@@ -88,8 +87,7 @@ std::string MakeAbsolutePath(StringRef CurrentDir, StringRef Path) {
std::string MakeAbsolutePath(const SourceManager &SM, StringRef Path) {
llvm::SmallString<128> AbsolutePath(Path);
if (std::error_code EC =
- SM.getFileManager().getVirtualFileSystem()->makeAbsolute(
- AbsolutePath))
+ SM.getFileManager().getVirtualFileSystem().makeAbsolute(AbsolutePath))
llvm::errs() << "Warning: could not make absolute file: '" << EC.message()
<< '\n';
// Handle symbolic link path cases.
@@ -766,7 +764,7 @@ void ClangMoveTool::removeDeclsInOldFiles() {
if (Context->Spec.OldDependOnNew &&
MakeAbsolutePath(SM, FilePath) ==
makeAbsolutePath(Context->Spec.OldHeader)) {
- // FIXME: Minimize the include path like include-fixer.
+ // FIXME: Minimize the include path like clang-include-fixer.
std::string IncludeNewH =
"#include \"" + Context->Spec.NewHeader + "\"\n";
// This replacment for inserting header will be cleaned up at the end.
diff --git a/clang-move/ClangMove.h b/clang-move/Move.h
index 94172181..da4bc444 100644
--- a/clang-move/ClangMove.h
+++ b/clang-move/Move.h
@@ -1,9 +1,8 @@
-//===-- ClangMove.h - Clang move -----------------------------------------===//
+//===-- Move.h - Clang move ----------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-move/tool/CMakeLists.txt b/clang-move/tool/CMakeLists.txt
index 6202e150..7bc4f30d 100644
--- a/clang-move/tool/CMakeLists.txt
+++ b/clang-move/tool/CMakeLists.txt
@@ -1,7 +1,7 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
add_clang_executable(clang-move
- ClangMoveMain.cpp
+ ClangMove.cpp
)
target_link_libraries(clang-move
diff --git a/clang-move/tool/ClangMoveMain.cpp b/clang-move/tool/ClangMove.cpp
index f50e973a..807425bb 100644
--- a/clang-move/tool/ClangMoveMain.cpp
+++ b/clang-move/tool/ClangMove.cpp
@@ -1,13 +1,12 @@
-//===-- ClangMoveMain.cpp - move defintion to new file ----------*- C++ -*-===//
+//===-- ClangMove.cpp - move defintion to new file --------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "ClangMove.h"
+#include "Move.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Tooling/ArgumentsAdjusters.h"
diff --git a/clang-query/Query.cpp b/clang-query/Query.cpp
index ffa3b456..eea0e776 100644
--- a/clang-query/Query.cpp
+++ b/clang-query/Query.cpp
@@ -1,9 +1,8 @@
//===---- Query.cpp - clang-query query -----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-query/Query.h b/clang-query/Query.h
index b4ff1d0f..56af4869 100644
--- a/clang-query/Query.h
+++ b/clang-query/Query.h
@@ -1,9 +1,8 @@
//===--- Query.h - clang-query ----------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-query/QueryParser.cpp b/clang-query/QueryParser.cpp
index 54eb5a03..4da2f5da 100644
--- a/clang-query/QueryParser.cpp
+++ b/clang-query/QueryParser.cpp
@@ -1,9 +1,8 @@
//===---- QueryParser.cpp - clang-query command parser --------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-query/QueryParser.h b/clang-query/QueryParser.h
index 56eb5a9a..f5d4393d 100644
--- a/clang-query/QueryParser.h
+++ b/clang-query/QueryParser.h
@@ -1,9 +1,8 @@
//===--- QueryParser.h - clang-query ----------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-query/QuerySession.h b/clang-query/QuerySession.h
index 70a4ede8..0f3bc1aa 100644
--- a/clang-query/QuerySession.h
+++ b/clang-query/QuerySession.h
@@ -1,9 +1,8 @@
//===--- QuerySession.h - clang-query ---------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-query/tool/CMakeLists.txt b/clang-query/tool/CMakeLists.txt
index e5c8a774..d6ac0ae7 100644
--- a/clang-query/tool/CMakeLists.txt
+++ b/clang-query/tool/CMakeLists.txt
@@ -1,6 +1,8 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
-add_clang_executable(clang-query ClangQuery.cpp)
+add_clang_executable(clang-query
+ ClangQuery.cpp
+ )
target_link_libraries(clang-query
PRIVATE
clangAST
diff --git a/clang-query/tool/ClangQuery.cpp b/clang-query/tool/ClangQuery.cpp
index 59c49baa..80e1c602 100644
--- a/clang-query/tool/ClangQuery.cpp
+++ b/clang-query/tool/ClangQuery.cpp
@@ -1,9 +1,8 @@
//===---- ClangQuery.cpp - clang-query tool -------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clang-reorder-fields/ReorderFieldsAction.cpp b/clang-reorder-fields/ReorderFieldsAction.cpp
index 7cb8abe5..c11234a0 100644
--- a/clang-reorder-fields/ReorderFieldsAction.cpp
+++ b/clang-reorder-fields/ReorderFieldsAction.cpp
@@ -1,9 +1,8 @@
//===-- tools/extra/clang-reorder-fields/ReorderFieldsAction.cpp -*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
diff --git a/clang-reorder-fields/ReorderFieldsAction.h b/clang-reorder-fields/ReorderFieldsAction.h
index f08c632a..cc450ed7 100644
--- a/clang-reorder-fields/ReorderFieldsAction.h
+++ b/clang-reorder-fields/ReorderFieldsAction.h
@@ -1,9 +1,8 @@
//===-- tools/extra/clang-reorder-fields/ReorderFieldsAction.h -*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
diff --git a/clang-reorder-fields/tool/CMakeLists.txt b/clang-reorder-fields/tool/CMakeLists.txt
index 97b41db5..718ee960 100644
--- a/clang-reorder-fields/tool/CMakeLists.txt
+++ b/clang-reorder-fields/tool/CMakeLists.txt
@@ -1,4 +1,6 @@
-add_clang_tool(clang-reorder-fields ClangReorderFields.cpp)
+add_clang_tool(clang-reorder-fields
+ ClangReorderFields.cpp
+ )
target_link_libraries(clang-reorder-fields
PRIVATE
diff --git a/clang-reorder-fields/tool/ClangReorderFields.cpp b/clang-reorder-fields/tool/ClangReorderFields.cpp
index 077e55e8..bae3f4c6 100644
--- a/clang-reorder-fields/tool/ClangReorderFields.cpp
+++ b/clang-reorder-fields/tool/ClangReorderFields.cpp
@@ -1,9 +1,8 @@
//===-- tools/extra/clang-reorder-fields/tool/ClangReorderFields.cpp -*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
diff --git a/clang-tidy-vs/ClangTidy/ClangTidyPackage.cs b/clang-tidy-vs/ClangTidy/ClangTidyPackage.cs
index 9a0c9b67..fb8a1511 100644
--- a/clang-tidy-vs/ClangTidy/ClangTidyPackage.cs
+++ b/clang-tidy-vs/ClangTidy/ClangTidyPackage.cs
@@ -1,56 +1,55 @@
-//===-- ClangTidyPackages.cs - VSPackage for clang-tidy ----------*- C# -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class contains a VS extension package that runs clang-tidy over a
-// file in a VS text editor.
-//
-//===----------------------------------------------------------------------===//
-
-using Microsoft.VisualStudio.Editor;
-using Microsoft.VisualStudio.Shell;
-using Microsoft.VisualStudio.Shell.Interop;
-using Microsoft.VisualStudio.TextManager.Interop;
-using System;
-using System.Collections;
-using System.ComponentModel;
-using System.ComponentModel.Design;
-using System.IO;
-using System.Runtime.InteropServices;
-using System.Windows.Forms;
-using System.Xml.Linq;
-
-namespace LLVM.ClangTidy
-{
- [PackageRegistration(UseManagedResourcesOnly = true)]
- [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
- [ProvideMenuResource("Menus.ctmenu", 1)]
- [Guid(GuidList.guidClangTidyPkgString)]
- [ProvideOptionPage(typeof(ClangTidyConfigurationPage), "LLVM/Clang", "ClangTidy", 0, 0, true)]
- public sealed class ClangTidyPackage : Package
- {
- #region Package Members
- protected override void Initialize()
- {
- base.Initialize();
-
- var commandService = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
- if (commandService != null)
- {
- var menuCommandID = new CommandID(GuidList.guidClangTidyCmdSet, (int)PkgCmdIDList.cmdidClangTidy);
- var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
- commandService.AddCommand(menuItem);
- }
- }
- #endregion
-
- private void MenuItemCallback(object sender, EventArgs args)
- {
- }
- }
-}
+//===-- ClangTidyPackages.cs - VSPackage for 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This class contains a VS extension package that runs clang-tidy over a
+// file in a VS text editor.
+//
+//===----------------------------------------------------------------------===//
+
+using Microsoft.VisualStudio.Editor;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.TextManager.Interop;
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.ComponentModel.Design;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using System.Xml.Linq;
+
+namespace LLVM.ClangTidy
+{
+ [PackageRegistration(UseManagedResourcesOnly = true)]
+ [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
+ [ProvideMenuResource("Menus.ctmenu", 1)]
+ [Guid(GuidList.guidClangTidyPkgString)]
+ [ProvideOptionPage(typeof(ClangTidyConfigurationPage), "LLVM/Clang", "ClangTidy", 0, 0, true)]
+ public sealed class ClangTidyPackage : Package
+ {
+ #region Package Members
+ protected override void Initialize()
+ {
+ base.Initialize();
+
+ var commandService = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
+ if (commandService != null)
+ {
+ var menuCommandID = new CommandID(GuidList.guidClangTidyCmdSet, (int)PkgCmdIDList.cmdidClangTidy);
+ var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
+ commandService.AddCommand(menuItem);
+ }
+ }
+ #endregion
+
+ private void MenuItemCallback(object sender, EventArgs args)
+ {
+ }
+ }
+}
diff --git a/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.cs b/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.cs
index 20c8a8ff..c9945b27 100644
--- a/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.cs
+++ b/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.cs
@@ -1,208 +1,207 @@
-//===-- ClangTidyPropertyGrid.cs - UI for configuring clang-tidy -*- C# -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class contains a UserControl consisting of a .NET PropertyGrid control
-// allowing configuration of checks and check options for ClangTidy.
-//
-//===----------------------------------------------------------------------===//
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Drawing;
-using System.Data;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.IO;
-using Microsoft.VisualStudio.Shell;
-
-namespace LLVM.ClangTidy
-{
- /// <summary>
- /// A UserControl displaying a PropertyGrid allowing configuration of clang-tidy
- /// checks and check options, as well as serialization and deserialization of
- /// clang-tidy configuration files. When a configuration file is loaded, the
- /// entire chain of configuration files is analyzed based on the file path,
- /// and quick access is provided to edit or view any of the files in the
- /// configuration chain, allowing easy visualization of where values come from
- /// (similar in spirit to the -explain-config option of clang-tidy).
- /// </summary>
- public partial class ClangTidyPropertyGrid : UserControl
- {
- /// <summary>
- /// The sequence of .clang-tidy configuration files, starting from the root
- /// of the filesystem, down to the selected file.
- /// </summary>
- List<KeyValuePair<string, ClangTidyProperties>> PropertyChain_ = null;
-
- public ClangTidyPropertyGrid()
- {
- InitializeComponent();
- InitializeSettings();
- }
-
- private enum ShouldCancel
- {
- Yes,
- No,
- }
-
- public void SaveSettingsToStorage()
- {
- PersistUnsavedChanges(false);
- }
-
- private ShouldCancel PersistUnsavedChanges(bool PromptFirst)
- {
- var UnsavedResults = PropertyChain_.Where(x => x.Key != null && x.Value.GetHasUnsavedChanges());
- if (UnsavedResults.Count() == 0)
- return ShouldCancel.No;
-
- bool ShouldSave = false;
- if (PromptFirst)
- {
- var Response = MessageBox.Show(
- "You have unsaved changes! Do you want to save before loading a new file?",
- "clang-tidy",
- MessageBoxButtons.YesNoCancel);
-
- ShouldSave = (Response == DialogResult.Yes);
- if (Response == DialogResult.Cancel)
- return ShouldCancel.Yes;
- }
- else
- ShouldSave = true;
-
- if (ShouldSave)
- {
- foreach (var Result in UnsavedResults)
- {
- ClangTidyConfigParser.SerializeClangTidyFile(Result.Value, Result.Key);
- Result.Value.SetHasUnsavedChanges(false);
- }
- }
- return ShouldCancel.No;
- }
-
- public void InitializeSettings()
- {
- PropertyChain_ = new List<KeyValuePair<string, ClangTidyProperties>>();
- PropertyChain_.Add(new KeyValuePair<string, ClangTidyProperties>(null, ClangTidyProperties.RootProperties));
- reloadPropertyChain();
- }
-
- private void button1_Click(object sender, EventArgs e)
- {
- ShouldCancel Cancel = PersistUnsavedChanges(true);
- if (Cancel == ShouldCancel.Yes)
- return;
-
- using (OpenFileDialog D = new OpenFileDialog())
- {
- D.Filter = "Clang Tidy files|.clang-tidy";
- D.CheckPathExists = true;
- D.CheckFileExists = true;
-
- if (D.ShowDialog() == DialogResult.OK)
- {
- PropertyChain_.Clear();
- PropertyChain_ = ClangTidyConfigParser.ParseConfigurationChain(D.FileName);
- textBox1.Text = D.FileName;
- reloadPropertyChain();
- }
- }
- }
-
- private static readonly string DefaultText = "(Default)";
- private static readonly string BrowseText = "Browse for a file to edit its properties";
-
- /// <summary>
- /// After a new configuration file is chosen, analyzes the directory hierarchy
- /// and finds all .clang-tidy files in the path, parses them and updates the
- /// PropertyGrid and quick-access LinkLabel control to reflect the new property
- /// chain.
- /// </summary>
- private void reloadPropertyChain()
- {
- StringBuilder LinkBuilder = new StringBuilder();
- LinkBuilder.Append(DefaultText);
- LinkBuilder.Append(" > ");
- int PrefixLength = LinkBuilder.Length;
-
- if (PropertyChain_.Count == 1)
- LinkBuilder.Append(BrowseText);
- else
- LinkBuilder.Append(PropertyChain_[PropertyChain_.Count - 1].Key);
-
- linkLabelPath.Text = LinkBuilder.ToString();
-
- // Given a path like D:\Foo\Bar\Baz, construct a LinkLabel where individual
- // components of the path are clickable iff they contain a .clang-tidy file.
- // Clicking one of the links then updates the PropertyGrid to display the
- // selected .clang-tidy file.
- ClangTidyProperties LastProps = ClangTidyProperties.RootProperties;
- linkLabelPath.Links.Clear();
- linkLabelPath.Links.Add(0, DefaultText.Length, LastProps);
- foreach (var Prop in PropertyChain_.Skip(1))
- {
- LastProps = Prop.Value;
- string ClangTidyFolder = Path.GetFileName(Prop.Key);
- int ClangTidyFolderOffset = Prop.Key.Length - ClangTidyFolder.Length;
- linkLabelPath.Links.Add(PrefixLength + ClangTidyFolderOffset, ClangTidyFolder.Length, LastProps);
- }
- propertyGrid1.SelectedObject = LastProps;
- }
-
- private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
- {
- ClangTidyProperties Props = (ClangTidyProperties)propertyGrid1.SelectedObject;
- Props.SetHasUnsavedChanges(true);
-
- // When a CategoryVerb is selected, perform the corresponding action.
- PropertyDescriptor Property = e.ChangedItem.PropertyDescriptor;
- if (!(e.ChangedItem.Value is CategoryVerb))
- return;
-
- CategoryVerb Action = (CategoryVerb)e.ChangedItem.Value;
- if (Action == CategoryVerb.None)
- return;
-
- var Category = Property.Attributes.OfType<CategoryAttribute>().FirstOrDefault();
- if (Category == null)
- return;
- var SameCategoryProps = Props.GetProperties(new Attribute[] { Category });
- foreach (PropertyDescriptor P in SameCategoryProps)
- {
- if (P == Property)
- continue;
- switch (Action)
- {
- case CategoryVerb.Disable:
- P.SetValue(propertyGrid1.SelectedObject, false);
- break;
- case CategoryVerb.Enable:
- P.SetValue(propertyGrid1.SelectedObject, true);
- break;
- case CategoryVerb.Inherit:
- P.ResetValue(propertyGrid1.SelectedObject);
- break;
- }
- }
- Property.ResetValue(propertyGrid1.SelectedObject);
- propertyGrid1.Invalidate();
- }
-
- private void linkLabelPath_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
- {
- ClangTidyProperties Props = (ClangTidyProperties)e.Link.LinkData;
- propertyGrid1.SelectedObject = Props;
- }
- }
-}
+//===-- ClangTidyPropertyGrid.cs - UI for configuring 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This class contains a UserControl consisting of a .NET PropertyGrid control
+// allowing configuration of checks and check options for ClangTidy.
+//
+//===----------------------------------------------------------------------===//
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.IO;
+using Microsoft.VisualStudio.Shell;
+
+namespace LLVM.ClangTidy
+{
+ /// <summary>
+ /// A UserControl displaying a PropertyGrid allowing configuration of clang-tidy
+ /// checks and check options, as well as serialization and deserialization of
+ /// clang-tidy configuration files. When a configuration file is loaded, the
+ /// entire chain of configuration files is analyzed based on the file path,
+ /// and quick access is provided to edit or view any of the files in the
+ /// configuration chain, allowing easy visualization of where values come from
+ /// (similar in spirit to the -explain-config option of clang-tidy).
+ /// </summary>
+ public partial class ClangTidyPropertyGrid : UserControl
+ {
+ /// <summary>
+ /// The sequence of .clang-tidy configuration files, starting from the root
+ /// of the filesystem, down to the selected file.
+ /// </summary>
+ List<KeyValuePair<string, ClangTidyProperties>> PropertyChain_ = null;
+
+ public ClangTidyPropertyGrid()
+ {
+ InitializeComponent();
+ InitializeSettings();
+ }
+
+ private enum ShouldCancel
+ {
+ Yes,
+ No,
+ }
+
+ public void SaveSettingsToStorage()
+ {
+ PersistUnsavedChanges(false);
+ }
+
+ private ShouldCancel PersistUnsavedChanges(bool PromptFirst)
+ {
+ var UnsavedResults = PropertyChain_.Where(x => x.Key != null && x.Value.GetHasUnsavedChanges());
+ if (UnsavedResults.Count() == 0)
+ return ShouldCancel.No;
+
+ bool ShouldSave = false;
+ if (PromptFirst)
+ {
+ var Response = MessageBox.Show(
+ "You have unsaved changes! Do you want to save before loading a new file?",
+ "clang-tidy",
+ MessageBoxButtons.YesNoCancel);
+
+ ShouldSave = (Response == DialogResult.Yes);
+ if (Response == DialogResult.Cancel)
+ return ShouldCancel.Yes;
+ }
+ else
+ ShouldSave = true;
+
+ if (ShouldSave)
+ {
+ foreach (var Result in UnsavedResults)
+ {
+ ClangTidyConfigParser.SerializeClangTidyFile(Result.Value, Result.Key);
+ Result.Value.SetHasUnsavedChanges(false);
+ }
+ }
+ return ShouldCancel.No;
+ }
+
+ public void InitializeSettings()
+ {
+ PropertyChain_ = new List<KeyValuePair<string, ClangTidyProperties>>();
+ PropertyChain_.Add(new KeyValuePair<string, ClangTidyProperties>(null, ClangTidyProperties.RootProperties));
+ reloadPropertyChain();
+ }
+
+ private void button1_Click(object sender, EventArgs e)
+ {
+ ShouldCancel Cancel = PersistUnsavedChanges(true);
+ if (Cancel == ShouldCancel.Yes)
+ return;
+
+ using (OpenFileDialog D = new OpenFileDialog())
+ {
+ D.Filter = "Clang Tidy files|.clang-tidy";
+ D.CheckPathExists = true;
+ D.CheckFileExists = true;
+
+ if (D.ShowDialog() == DialogResult.OK)
+ {
+ PropertyChain_.Clear();
+ PropertyChain_ = ClangTidyConfigParser.ParseConfigurationChain(D.FileName);
+ textBox1.Text = D.FileName;
+ reloadPropertyChain();
+ }
+ }
+ }
+
+ private static readonly string DefaultText = "(Default)";
+ private static readonly string BrowseText = "Browse for a file to edit its properties";
+
+ /// <summary>
+ /// After a new configuration file is chosen, analyzes the directory hierarchy
+ /// and finds all .clang-tidy files in the path, parses them and updates the
+ /// PropertyGrid and quick-access LinkLabel control to reflect the new property
+ /// chain.
+ /// </summary>
+ private void reloadPropertyChain()
+ {
+ StringBuilder LinkBuilder = new StringBuilder();
+ LinkBuilder.Append(DefaultText);
+ LinkBuilder.Append(" > ");
+ int PrefixLength = LinkBuilder.Length;
+
+ if (PropertyChain_.Count == 1)
+ LinkBuilder.Append(BrowseText);
+ else
+ LinkBuilder.Append(PropertyChain_[PropertyChain_.Count - 1].Key);
+
+ linkLabelPath.Text = LinkBuilder.ToString();
+
+ // Given a path like D:\Foo\Bar\Baz, construct a LinkLabel where individual
+ // components of the path are clickable iff they contain a .clang-tidy file.
+ // Clicking one of the links then updates the PropertyGrid to display the
+ // selected .clang-tidy file.
+ ClangTidyProperties LastProps = ClangTidyProperties.RootProperties;
+ linkLabelPath.Links.Clear();
+ linkLabelPath.Links.Add(0, DefaultText.Length, LastProps);
+ foreach (var Prop in PropertyChain_.Skip(1))
+ {
+ LastProps = Prop.Value;
+ string ClangTidyFolder = Path.GetFileName(Prop.Key);
+ int ClangTidyFolderOffset = Prop.Key.Length - ClangTidyFolder.Length;
+ linkLabelPath.Links.Add(PrefixLength + ClangTidyFolderOffset, ClangTidyFolder.Length, LastProps);
+ }
+ propertyGrid1.SelectedObject = LastProps;
+ }
+
+ private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
+ {
+ ClangTidyProperties Props = (ClangTidyProperties)propertyGrid1.SelectedObject;
+ Props.SetHasUnsavedChanges(true);
+
+ // When a CategoryVerb is selected, perform the corresponding action.
+ PropertyDescriptor Property = e.ChangedItem.PropertyDescriptor;
+ if (!(e.ChangedItem.Value is CategoryVerb))
+ return;
+
+ CategoryVerb Action = (CategoryVerb)e.ChangedItem.Value;
+ if (Action == CategoryVerb.None)
+ return;
+
+ var Category = Property.Attributes.OfType<CategoryAttribute>().FirstOrDefault();
+ if (Category == null)
+ return;
+ var SameCategoryProps = Props.GetProperties(new Attribute[] { Category });
+ foreach (PropertyDescriptor P in SameCategoryProps)
+ {
+ if (P == Property)
+ continue;
+ switch (Action)
+ {
+ case CategoryVerb.Disable:
+ P.SetValue(propertyGrid1.SelectedObject, false);
+ break;
+ case CategoryVerb.Enable:
+ P.SetValue(propertyGrid1.SelectedObject, true);
+ break;
+ case CategoryVerb.Inherit:
+ P.ResetValue(propertyGrid1.SelectedObject);
+ break;
+ }
+ }
+ Property.ResetValue(propertyGrid1.SelectedObject);
+ propertyGrid1.Invalidate();
+ }
+
+ private void linkLabelPath_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+ {
+ ClangTidyProperties Props = (ClangTidyProperties)e.Link.LinkData;
+ propertyGrid1.SelectedObject = Props;
+ }
+ }
+}
diff --git a/clang-tidy-vs/ClangTidy/PkgCmdID.cs b/clang-tidy-vs/ClangTidy/PkgCmdID.cs
index 3faf403a..beabbce5 100644
--- a/clang-tidy-vs/ClangTidy/PkgCmdID.cs
+++ b/clang-tidy-vs/ClangTidy/PkgCmdID.cs
@@ -4,4 +4,4 @@
{
public const uint cmdidClangTidy = 0x100;
};
-} \ No newline at end of file
+}
diff --git a/clang-tidy-vs/ClangTidy/license.txt b/clang-tidy-vs/ClangTidy/license.txt
index 547f6a48..d3d7ed3c 100644
--- a/clang-tidy-vs/ClangTidy/license.txt
+++ b/clang-tidy-vs/ClangTidy/license.txt
@@ -1,5 +1,240 @@
==============================================================================
-LLVM Release License
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+==============================================================================
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+==============================================================================
+Software from third parties included in the LLVM Project:
+==============================================================================
+The LLVM Project contains third party software which is under different license
+terms. All such code will be identified clearly using at least one of two
+mechanisms:
+1) It will be in a separate directory tree with its own `LICENSE.txt` or
+ `LICENSE` file at the top containing the specific license and restrictions
+ which apply to that software, or
+2) It will contain specific license and restriction terms at the top of every
+ file.
+
+==============================================================================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
==============================================================================
University of Illinois/NCSA
Open Source License
@@ -41,23 +276,3 @@ CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.
-
-==============================================================================
-The LLVM software contains code written by third parties. Such software will
-have its own individual LICENSE.TXT file in the directory in which it appears.
-This file will describe the copyrights, license, and restrictions which apply
-to that code.
-
-The disclaimer of warranty in the University of Illinois Open Source License
-applies to all code in the LLVM Distribution, and nothing in any of the
-other licenses gives permission to use the names of the LLVM Team or the
-University of Illinois to endorse or promote products derived from this
-Software.
-
-The following pieces of software have additional or alternate copyrights,
-licenses, and/or restrictions:
-
-Program Directory
-------- ---------
-<none yet>
-
diff --git a/clang-tidy/CMakeLists.txt b/clang-tidy/CMakeLists.txt
index 196548f4..84328ba0 100644
--- a/clang-tidy/CMakeLists.txt
+++ b/clang-tidy/CMakeLists.txt
@@ -4,10 +4,12 @@ set(LLVM_LINK_COMPONENTS
add_clang_library(clangTidy
ClangTidy.cpp
+ ClangTidyCheck.cpp
ClangTidyModule.cpp
ClangTidyDiagnosticConsumer.cpp
ClangTidyOptions.cpp
ClangTidyProfiling.cpp
+ ExpandModularHeadersPPCallbacks.cpp
DEPENDS
ClangSACheckers
@@ -49,6 +51,7 @@ if(CLANG_ENABLE_STATIC_ANALYZER)
add_subdirectory(mpi)
endif()
add_subdirectory(objc)
+add_subdirectory(openmp)
add_subdirectory(performance)
add_subdirectory(plugin)
add_subdirectory(portability)
diff --git a/clang-tidy/ClangTidy.cpp b/clang-tidy/ClangTidy.cpp
index 0feda605..1d813d65 100644
--- a/clang-tidy/ClangTidy.cpp
+++ b/clang-tidy/ClangTidy.cpp
@@ -1,9 +1,8 @@
//===--- tools/extra/clang-tidy/ClangTidy.cpp - Clang tidy tool -----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
@@ -19,6 +18,7 @@
#include "ClangTidyDiagnosticConsumer.h"
#include "ClangTidyModuleRegistry.h"
#include "ClangTidyProfiling.h"
+#include "ExpandModularHeadersPPCallbacks.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
@@ -35,6 +35,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Rewrite/Frontend/FixItRewriter.h"
#include "clang/Rewrite/Frontend/FrontendActions.h"
+#include "clang/Tooling/Core/Diagnostic.h"
#if CLANG_ENABLE_STATIC_ANALYZER
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
@@ -125,61 +126,51 @@ public:
}
auto Diag = Diags.Report(Loc, Diags.getCustomDiagID(Level, "%0 [%1]"))
<< Message.Message << Name;
- for (const auto &FileAndReplacements : Error.Fix) {
- for (const auto &Repl : FileAndReplacements.second) {
- SourceLocation FixLoc;
- ++TotalFixes;
- bool CanBeApplied = false;
- if (Repl.isApplicable()) {
+ // FIXME: explore options to support interactive fix selection.
+ const llvm::StringMap<Replacements> *ChosenFix = selectFirstFix(Error);
+ if (ApplyFixes && ChosenFix) {
+ for (const auto &FileAndReplacements : *ChosenFix) {
+ for (const auto &Repl : FileAndReplacements.second) {
+ ++TotalFixes;
+ bool CanBeApplied = false;
+ if (!Repl.isApplicable())
+ continue;
+ SourceLocation FixLoc;
SmallString<128> FixAbsoluteFilePath = Repl.getFilePath();
Files.makeAbsolutePath(FixAbsoluteFilePath);
- if (ApplyFixes) {
- tooling::Replacement R(FixAbsoluteFilePath, Repl.getOffset(),
- Repl.getLength(),
- Repl.getReplacementText());
- Replacements &Replacements = FileReplacements[R.getFilePath()];
- llvm::Error Err = Replacements.add(R);
- if (Err) {
- // FIXME: Implement better conflict handling.
- llvm::errs() << "Trying to resolve conflict: "
- << llvm::toString(std::move(Err)) << "\n";
- unsigned NewOffset =
- Replacements.getShiftedCodePosition(R.getOffset());
- unsigned NewLength = Replacements.getShiftedCodePosition(
- R.getOffset() + R.getLength()) -
- NewOffset;
- if (NewLength == R.getLength()) {
- R = Replacement(R.getFilePath(), NewOffset, NewLength,
- R.getReplacementText());
- Replacements = Replacements.merge(tooling::Replacements(R));
- CanBeApplied = true;
- ++AppliedFixes;
- } else {
- llvm::errs()
- << "Can't resolve conflict, skipping the replacement.\n";
- }
-
- } else {
+ tooling::Replacement R(FixAbsoluteFilePath, Repl.getOffset(),
+ Repl.getLength(), Repl.getReplacementText());
+ Replacements &Replacements = FileReplacements[R.getFilePath()];
+ llvm::Error Err = Replacements.add(R);
+ if (Err) {
+ // FIXME: Implement better conflict handling.
+ llvm::errs() << "Trying to resolve conflict: "
+ << llvm::toString(std::move(Err)) << "\n";
+ unsigned NewOffset =
+ Replacements.getShiftedCodePosition(R.getOffset());
+ unsigned NewLength = Replacements.getShiftedCodePosition(
+ R.getOffset() + R.getLength()) -
+ NewOffset;
+ if (NewLength == R.getLength()) {
+ R = Replacement(R.getFilePath(), NewOffset, NewLength,
+ R.getReplacementText());
+ Replacements = Replacements.merge(tooling::Replacements(R));
CanBeApplied = true;
++AppliedFixes;
+ } else {
+ llvm::errs()
+ << "Can't resolve conflict, skipping the replacement.\n";
}
+ } else {
+ CanBeApplied = true;
+ ++AppliedFixes;
}
FixLoc = getLocation(FixAbsoluteFilePath, Repl.getOffset());
- SourceLocation FixEndLoc =
- FixLoc.getLocWithOffset(Repl.getLength());
- // Retrieve the source range for applicable fixes. Macro definitions
- // on the command line have locations in a virtual buffer and don't
- // have valid file paths and are therefore not applicable.
- CharSourceRange Range =
- CharSourceRange::getCharRange(SourceRange(FixLoc, FixEndLoc));
- Diag << FixItHint::CreateReplacement(Range,
- Repl.getReplacementText());
- }
-
- if (ApplyFixes)
FixLocations.push_back(std::make_pair(FixLoc, CanBeApplied));
+ }
}
}
+ reportFix(Diag, Error.Message.Fix);
}
for (auto Fix : FixLocations) {
Diags.Report(Fix.first, Fix.second ? diag::note_fixit_applied
@@ -250,10 +241,33 @@ private:
return SourceMgr.getLocForStartOfFile(ID).getLocWithOffset(Offset);
}
+ void reportFix(const DiagnosticBuilder &Diag,
+ const llvm::StringMap<Replacements> &Fix) {
+ for (const auto &FileAndReplacements : Fix) {
+ for (const auto &Repl : FileAndReplacements.second) {
+ if (!Repl.isApplicable())
+ continue;
+ SmallString<128> FixAbsoluteFilePath = Repl.getFilePath();
+ Files.makeAbsolutePath(FixAbsoluteFilePath);
+ SourceLocation FixLoc =
+ getLocation(FixAbsoluteFilePath, Repl.getOffset());
+ SourceLocation FixEndLoc = FixLoc.getLocWithOffset(Repl.getLength());
+ // Retrieve the source range for applicable fixes. Macro definitions
+ // on the command line have locations in a virtual buffer and don't
+ // have valid file paths and are therefore not applicable.
+ CharSourceRange Range =
+ CharSourceRange::getCharRange(SourceRange(FixLoc, FixEndLoc));
+ Diag << FixItHint::CreateReplacement(Range, Repl.getReplacementText());
+ }
+ }
+ }
+
void reportNote(const tooling::DiagnosticMessage &Message) {
SourceLocation Loc = getLocation(Message.FilePath, Message.FileOffset);
- Diags.Report(Loc, Diags.getCustomDiagID(DiagnosticsEngine::Note, "%0"))
+ auto Diag =
+ Diags.Report(Loc, Diags.getCustomDiagID(DiagnosticsEngine::Note, "%0"))
<< Message.Message;
+ reportFix(Diag, Message.Fix);
}
FileManager Files;
@@ -291,8 +305,10 @@ private:
} // namespace
ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory(
- ClangTidyContext &Context)
- : Context(Context), CheckFactories(new ClangTidyCheckFactories) {
+ ClangTidyContext &Context,
+ IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS)
+ : Context(Context), OverlayFS(OverlayFS),
+ CheckFactories(new ClangTidyCheckFactories) {
for (ClangTidyModuleRegistry::iterator I = ClangTidyModuleRegistry::begin(),
E = ClangTidyModuleRegistry::end();
I != E; ++I) {
@@ -352,14 +368,15 @@ ClangTidyASTConsumerFactory::CreateASTConsumer(
clang::CompilerInstance &Compiler, StringRef File) {
// FIXME: Move this to a separate method, so that CreateASTConsumer doesn't
// modify Compiler.
- Context.setSourceManager(&Compiler.getSourceManager());
+ SourceManager *SM = &Compiler.getSourceManager();
+ Context.setSourceManager(SM);
Context.setCurrentFile(File);
Context.setASTContext(&Compiler.getASTContext());
auto WorkingDir = Compiler.getSourceManager()
.getFileManager()
.getVirtualFileSystem()
- ->getCurrentWorkingDirectory();
+ .getCurrentWorkingDirectory();
if (WorkingDir)
Context.setCurrentBuildDirectory(WorkingDir.get());
@@ -378,9 +395,19 @@ ClangTidyASTConsumerFactory::CreateASTConsumer(
std::unique_ptr<ast_matchers::MatchFinder> Finder(
new ast_matchers::MatchFinder(std::move(FinderOptions)));
+ Preprocessor *PP = &Compiler.getPreprocessor();
+ Preprocessor *ModuleExpanderPP = PP;
+
+ if (Context.getLangOpts().Modules && OverlayFS != nullptr) {
+ auto ModuleExpander = llvm::make_unique<ExpandModularHeadersPPCallbacks>(
+ &Compiler, OverlayFS);
+ ModuleExpanderPP = ModuleExpander->getPreprocessor();
+ PP->addPPCallbacks(std::move(ModuleExpander));
+ }
+
for (auto &Check : Checks) {
Check->registerMatchers(&*Finder);
- Check->registerPPCallbacks(Compiler);
+ Check->registerPPCallbacks(*SM, PP, ModuleExpanderPP);
}
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
@@ -435,51 +462,6 @@ ClangTidyOptions::OptionMap ClangTidyASTConsumerFactory::getCheckOptions() {
return Options;
}
-DiagnosticBuilder ClangTidyCheck::diag(SourceLocation Loc, StringRef Message,
- DiagnosticIDs::Level Level) {
- return Context->diag(CheckName, Loc, Message, Level);
-}
-
-void ClangTidyCheck::run(const ast_matchers::MatchFinder::MatchResult &Result) {
- // For historical reasons, checks don't implement the MatchFinder run()
- // callback directly. We keep the run()/check() distinction to avoid interface
- // churn, and to allow us to add cross-cutting logic in the future.
- check(Result);
-}
-
-OptionsView::OptionsView(StringRef CheckName,
- const ClangTidyOptions::OptionMap &CheckOptions)
- : NamePrefix(CheckName.str() + "."), CheckOptions(CheckOptions) {}
-
-std::string OptionsView::get(StringRef LocalName, StringRef Default) const {
- const auto &Iter = CheckOptions.find(NamePrefix + LocalName.str());
- if (Iter != CheckOptions.end())
- return Iter->second;
- return Default;
-}
-
-std::string OptionsView::getLocalOrGlobal(StringRef LocalName,
- StringRef Default) const {
- auto Iter = CheckOptions.find(NamePrefix + LocalName.str());
- if (Iter != CheckOptions.end())
- return Iter->second;
- // Fallback to global setting, if present.
- Iter = CheckOptions.find(LocalName.str());
- if (Iter != CheckOptions.end())
- return Iter->second;
- return Default;
-}
-
-void OptionsView::store(ClangTidyOptions::OptionMap &Options,
- StringRef LocalName, StringRef Value) const {
- Options[NamePrefix + LocalName.str()] = Value;
-}
-
-void OptionsView::store(ClangTidyOptions::OptionMap &Options,
- StringRef LocalName, int64_t Value) const {
- store(Options, LocalName, llvm::itostr(Value));
-}
-
std::vector<std::string>
getCheckNames(const ClangTidyOptions &Options,
bool AllowEnablingAnalyzerAlphaCheckers) {
@@ -506,7 +488,7 @@ std::vector<ClangTidyError>
runClangTidy(clang::tidy::ClangTidyContext &Context,
const CompilationDatabase &Compilations,
ArrayRef<std::string> InputFiles,
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS,
bool EnableCheckProfile, llvm::StringRef StoreCheckProfile) {
ClangTool Tool(Compilations, InputFiles,
std::make_shared<PCHContainerOperations>(), BaseFS);
@@ -529,24 +511,8 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
return AdjustedArgs;
};
- // Remove plugins arguments.
- ArgumentsAdjuster PluginArgumentsRemover =
- [](const CommandLineArguments &Args, StringRef Filename) {
- CommandLineArguments AdjustedArgs;
- for (size_t I = 0, E = Args.size(); I < E; ++I) {
- if (I + 4 < Args.size() && Args[I] == "-Xclang" &&
- (Args[I + 1] == "-load" || Args[I + 1] == "-add-plugin" ||
- StringRef(Args[I + 1]).startswith("-plugin-arg-")) &&
- Args[I + 2] == "-Xclang") {
- I += 3;
- } else
- AdjustedArgs.push_back(Args[I]);
- }
- return AdjustedArgs;
- };
-
Tool.appendArgumentsAdjuster(PerFileExtraArgumentsInserter);
- Tool.appendArgumentsAdjuster(PluginArgumentsRemover);
+ Tool.appendArgumentsAdjuster(getStripPluginsAdjuster());
Context.setEnableProfiling(EnableCheckProfile);
Context.setProfileStoragePrefix(StoreCheckProfile);
@@ -558,7 +524,9 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
class ActionFactory : public FrontendActionFactory {
public:
- ActionFactory(ClangTidyContext &Context) : ConsumerFactory(Context) {}
+ ActionFactory(ClangTidyContext &Context,
+ IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS)
+ : ConsumerFactory(Context, BaseFS) {}
FrontendAction *create() override { return new Action(&ConsumerFactory); }
bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
@@ -589,7 +557,7 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
ClangTidyASTConsumerFactory ConsumerFactory;
};
- ActionFactory Factory(Context);
+ ActionFactory Factory(Context, BaseFS);
Tool.run(&Factory);
return DiagConsumer.take();
}
@@ -600,7 +568,7 @@ void handleErrors(llvm::ArrayRef<ClangTidyError> Errors,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {
ErrorReporter Reporter(Context, Fix, BaseFS);
llvm::vfs::FileSystem &FileSystem =
- *Reporter.getSourceManager().getFileManager().getVirtualFileSystem();
+ Reporter.getSourceManager().getFileManager().getVirtualFileSystem();
auto InitialWorkingDir = FileSystem.getCurrentWorkingDirectory();
if (!InitialWorkingDir)
llvm::report_fatal_error("Cannot get current working path.");
diff --git a/clang-tidy/ClangTidy.h b/clang-tidy/ClangTidy.h
index dc11200d..a9433f63 100644
--- a/clang-tidy/ClangTidy.h
+++ b/clang-tidy/ClangTidy.h
@@ -1,25 +1,19 @@
//===--- ClangTidy.h - clang-tidy -------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CLANGTIDY_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDY_H
+#include "ClangTidyCheck.h"
#include "ClangTidyDiagnosticConsumer.h"
#include "ClangTidyOptions.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Tooling/Refactoring.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
-#include <type_traits>
#include <vector>
namespace clang {
@@ -31,167 +25,13 @@ class CompilationDatabase;
namespace tidy {
-/// \brief Provides access to the ``ClangTidyCheck`` options via check-local
-/// names.
-///
-/// Methods of this class prepend ``CheckName + "."`` to translate check-local
-/// option names to global option names.
-class OptionsView {
-public:
- /// \brief Initializes the instance using \p CheckName + "." as a prefix.
- OptionsView(StringRef CheckName,
- const ClangTidyOptions::OptionMap &CheckOptions);
-
- /// \brief Read a named option from the ``Context``.
- ///
- /// Reads the option with the check-local name \p LocalName from the
- /// ``CheckOptions``. If the corresponding key is not present, returns
- /// \p Default.
- std::string get(StringRef LocalName, StringRef Default) const;
-
- /// \brief Read a named option from the ``Context``.
- ///
- /// Reads the option with the check-local name \p LocalName from local or
- /// global ``CheckOptions``. Gets local option first. If local is not present,
- /// falls back to get global option. If global option is not present either,
- /// returns Default.
- std::string getLocalOrGlobal(StringRef LocalName, StringRef Default) const;
-
- /// \brief Read a named option from the ``Context`` and parse it as an
- /// integral type ``T``.
- ///
- /// Reads the option with the check-local name \p LocalName from the
- /// ``CheckOptions``. If the corresponding key is not present, returns
- /// \p Default.
- template <typename T>
- typename std::enable_if<std::is_integral<T>::value, T>::type
- get(StringRef LocalName, T Default) const {
- std::string Value = get(LocalName, "");
- T Result = Default;
- if (!Value.empty())
- StringRef(Value).getAsInteger(10, Result);
- return Result;
- }
-
- /// \brief Read a named option from the ``Context`` and parse it as an
- /// integral type ``T``.
- ///
- /// Reads the option with the check-local name \p LocalName from local or
- /// global ``CheckOptions``. Gets local option first. If local is not present,
- /// falls back to get global option. If global option is not present either,
- /// returns Default.
- template <typename T>
- typename std::enable_if<std::is_integral<T>::value, T>::type
- getLocalOrGlobal(StringRef LocalName, T Default) const {
- std::string Value = getLocalOrGlobal(LocalName, "");
- T Result = Default;
- if (!Value.empty())
- StringRef(Value).getAsInteger(10, Result);
- return Result;
- }
-
- /// \brief Stores an option with the check-local name \p LocalName with string
- /// value \p Value to \p Options.
- void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName,
- StringRef Value) const;
-
- /// \brief Stores an option with the check-local name \p LocalName with
- /// ``int64_t`` value \p Value to \p Options.
- void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName,
- int64_t Value) const;
-
-private:
- std::string NamePrefix;
- const ClangTidyOptions::OptionMap &CheckOptions;
-};
-
-/// \brief Base class for all clang-tidy checks.
-///
-/// To implement a ``ClangTidyCheck``, write a subclass and override some of the
-/// base class's methods. E.g. to implement a check that validates namespace
-/// declarations, override ``registerMatchers``:
-///
-/// ~~~{.cpp}
-/// void registerMatchers(ast_matchers::MatchFinder *Finder) override {
-/// Finder->addMatcher(namespaceDecl().bind("namespace"), this);
-/// }
-/// ~~~
-///
-/// and then override ``check(const MatchResult &Result)`` to do the actual
-/// check for each match.
-///
-/// A new ``ClangTidyCheck`` instance is created per translation unit.
-///
-/// FIXME: Figure out whether carrying information from one TU to another is
-/// useful/necessary.
-class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
-public:
- /// \brief Initializes the check with \p CheckName and \p Context.
- ///
- /// Derived classes must implement the constructor with this signature or
- /// delegate it. If a check needs to read options, it can do this in the
- /// constructor using the Options.get() methods below.
- ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context)
- : CheckName(CheckName), Context(Context),
- Options(CheckName, Context->getOptions().CheckOptions) {
- assert(Context != nullptr);
- assert(!CheckName.empty());
- }
-
- /// \brief Override this to register ``PPCallbacks`` with ``Compiler``.
- ///
- /// This should be used for clang-tidy checks that analyze preprocessor-
- /// dependent properties, e.g. the order of include directives.
- virtual void registerPPCallbacks(CompilerInstance &Compiler) {}
-
- /// \brief Override this to register AST matchers with \p Finder.
- ///
- /// This should be used by clang-tidy checks that analyze code properties that
- /// dependent on AST knowledge.
- ///
- /// You can register as many matchers as necessary with \p Finder. Usually,
- /// "this" will be used as callback, but you can also specify other callback
- /// classes. Thereby, different matchers can trigger different callbacks.
- ///
- /// If you need to merge information between the different matchers, you can
- /// store these as members of the derived class. However, note that all
- /// matches occur in the order of the AST traversal.
- virtual void registerMatchers(ast_matchers::MatchFinder *Finder) {}
-
- /// \brief ``ClangTidyChecks`` that register ASTMatchers should do the actual
- /// work in here.
- virtual void check(const ast_matchers::MatchFinder::MatchResult &Result) {}
-
- /// \brief Add a diagnostic with the check's name.
- DiagnosticBuilder diag(SourceLocation Loc, StringRef Description,
- DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
-
- /// \brief Should store all options supported by this check with their
- /// current values or default values for options that haven't been overridden.
- ///
- /// The check should use ``Options.store()`` to store each option it supports
- /// whether it has the default value or it has been overridden.
- virtual void storeOptions(ClangTidyOptions::OptionMap &Options) {}
-
-private:
- void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
- StringRef getID() const override { return CheckName; }
- std::string CheckName;
- ClangTidyContext *Context;
-
-protected:
- OptionsView Options;
- /// \brief Returns the main file name of the current translation unit.
- StringRef getCurrentMainFile() const { return Context->getCurrentFile(); }
- /// \brief Returns the language options from the context.
- LangOptions getLangOpts() const { return Context->getLangOpts(); }
-};
-
class ClangTidyCheckFactories;
class ClangTidyASTConsumerFactory {
public:
- ClangTidyASTConsumerFactory(ClangTidyContext &Context);
+ ClangTidyASTConsumerFactory(
+ ClangTidyContext &Context,
+ IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS = nullptr);
/// \brief Returns an ASTConsumer that runs the specified clang-tidy checks.
std::unique_ptr<clang::ASTConsumer>
@@ -205,6 +45,7 @@ public:
private:
ClangTidyContext &Context;
+ IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS;
std::unique_ptr<ClangTidyCheckFactories> CheckFactories;
};
@@ -234,7 +75,7 @@ std::vector<ClangTidyError>
runClangTidy(clang::tidy::ClangTidyContext &Context,
const tooling::CompilationDatabase &Compilations,
ArrayRef<std::string> InputFiles,
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS,
bool EnableCheckProfile = false,
llvm::StringRef StoreCheckProfile = StringRef());
diff --git a/clang-tidy/ClangTidyCheck.cpp b/clang-tidy/ClangTidyCheck.cpp
new file mode 100644
index 00000000..fbf11768
--- /dev/null
+++ b/clang-tidy/ClangTidyCheck.cpp
@@ -0,0 +1,71 @@
+//===--- ClangTidyCheck.cpp - 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+
+ClangTidyCheck::ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context)
+ : CheckName(CheckName), Context(Context),
+ Options(CheckName, Context->getOptions().CheckOptions) {
+ assert(Context != nullptr);
+ assert(!CheckName.empty());
+}
+
+DiagnosticBuilder ClangTidyCheck::diag(SourceLocation Loc, StringRef Message,
+ DiagnosticIDs::Level Level) {
+ return Context->diag(CheckName, Loc, Message, Level);
+}
+
+void ClangTidyCheck::run(const ast_matchers::MatchFinder::MatchResult &Result) {
+ // For historical reasons, checks don't implement the MatchFinder run()
+ // callback directly. We keep the run()/check() distinction to avoid interface
+ // churn, and to allow us to add cross-cutting logic in the future.
+ check(Result);
+}
+
+ClangTidyCheck::OptionsView::OptionsView(StringRef CheckName,
+ const ClangTidyOptions::OptionMap &CheckOptions)
+ : NamePrefix(CheckName.str() + "."), CheckOptions(CheckOptions) {}
+
+std::string ClangTidyCheck::OptionsView::get(StringRef LocalName,
+ StringRef Default) const {
+ const auto &Iter = CheckOptions.find(NamePrefix + LocalName.str());
+ if (Iter != CheckOptions.end())
+ return Iter->second;
+ return Default;
+}
+
+std::string
+ClangTidyCheck::OptionsView::getLocalOrGlobal(StringRef LocalName,
+ StringRef Default) const {
+ auto Iter = CheckOptions.find(NamePrefix + LocalName.str());
+ if (Iter != CheckOptions.end())
+ return Iter->second;
+ // Fallback to global setting, if present.
+ Iter = CheckOptions.find(LocalName.str());
+ if (Iter != CheckOptions.end())
+ return Iter->second;
+ return Default;
+}
+
+void ClangTidyCheck::OptionsView::store(ClangTidyOptions::OptionMap &Options,
+ StringRef LocalName,
+ StringRef Value) const {
+ Options[NamePrefix + LocalName.str()] = Value;
+}
+
+void ClangTidyCheck::OptionsView::store(ClangTidyOptions::OptionMap &Options,
+ StringRef LocalName,
+ int64_t Value) const {
+ store(Options, LocalName, llvm::itostr(Value));
+}
+
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/ClangTidyCheck.h b/clang-tidy/ClangTidyCheck.h
new file mode 100644
index 00000000..fcfea90a
--- /dev/null
+++ b/clang-tidy/ClangTidyCheck.h
@@ -0,0 +1,194 @@
+//===--- ClangTidyCheck.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_CLANGTIDYCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYCHECK_H
+
+#include "ClangTidyDiagnosticConsumer.h"
+#include "ClangTidyOptions.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/StringExtras.h"
+#include <memory>
+#include <type_traits>
+#include <vector>
+
+namespace clang {
+
+class CompilerInstance;
+
+namespace tidy {
+
+/// \brief Base class for all clang-tidy checks.
+///
+/// To implement a ``ClangTidyCheck``, write a subclass and override some of the
+/// base class's methods. E.g. to implement a check that validates namespace
+/// declarations, override ``registerMatchers``:
+///
+/// ~~~{.cpp}
+/// void registerMatchers(ast_matchers::MatchFinder *Finder) override {
+/// Finder->addMatcher(namespaceDecl().bind("namespace"), this);
+/// }
+/// ~~~
+///
+/// and then override ``check(const MatchResult &Result)`` to do the actual
+/// check for each match.
+///
+/// A new ``ClangTidyCheck`` instance is created per translation unit.
+///
+/// FIXME: Figure out whether carrying information from one TU to another is
+/// useful/necessary.
+class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
+public:
+ /// \brief Initializes the check with \p CheckName and \p Context.
+ ///
+ /// Derived classes must implement the constructor with this signature or
+ /// delegate it. If a check needs to read options, it can do this in the
+ /// constructor using the Options.get() methods below.
+ ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context);
+
+ /// \brief Override this to register ``PPCallbacks`` in the preprocessor.
+ ///
+ /// This should be used for clang-tidy checks that analyze preprocessor-
+ /// dependent properties, e.g. include directives and macro definitions.
+ ///
+ /// There are two Preprocessors to choose from that differ in how they handle
+ /// modular #includes:
+ /// - PP is the real Preprocessor. It doesn't walk into modular #includes and
+ /// thus doesn't generate PPCallbacks for their contents.
+ /// - ModuleExpanderPP preprocesses the whole translation unit in the
+ /// non-modular mode, which allows it to generate PPCallbacks not only for
+ /// the main file and textual headers, but also for all transitively
+ /// included modular headers when the analysis runs with modules enabled.
+ /// When modules are not enabled ModuleExpanderPP just points to the real
+ /// preprocessor.
+ virtual void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) {}
+
+ /// \brief Override this to register AST matchers with \p Finder.
+ ///
+ /// This should be used by clang-tidy checks that analyze code properties that
+ /// dependent on AST knowledge.
+ ///
+ /// You can register as many matchers as necessary with \p Finder. Usually,
+ /// "this" will be used as callback, but you can also specify other callback
+ /// classes. Thereby, different matchers can trigger different callbacks.
+ ///
+ /// If you need to merge information between the different matchers, you can
+ /// store these as members of the derived class. However, note that all
+ /// matches occur in the order of the AST traversal.
+ virtual void registerMatchers(ast_matchers::MatchFinder *Finder) {}
+
+ /// \brief ``ClangTidyChecks`` that register ASTMatchers should do the actual
+ /// work in here.
+ virtual void check(const ast_matchers::MatchFinder::MatchResult &Result) {}
+
+ /// \brief Add a diagnostic with the check's name.
+ DiagnosticBuilder diag(SourceLocation Loc, StringRef Description,
+ DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
+
+ /// \brief Should store all options supported by this check with their
+ /// current values or default values for options that haven't been overridden.
+ ///
+ /// The check should use ``Options.store()`` to store each option it supports
+ /// whether it has the default value or it has been overridden.
+ virtual void storeOptions(ClangTidyOptions::OptionMap &Options) {}
+
+private:
+ void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ StringRef getID() const override { return CheckName; }
+ std::string CheckName;
+ ClangTidyContext *Context;
+
+protected:
+ /// \brief Provides access to the ``ClangTidyCheck`` options via check-local
+ /// names.
+ ///
+ /// Methods of this class prepend ``CheckName + "."`` to translate check-local
+ /// option names to global option names.
+ class OptionsView {
+ public:
+ /// \brief Initializes the instance using \p CheckName + "." as a prefix.
+ OptionsView(StringRef CheckName,
+ const ClangTidyOptions::OptionMap &CheckOptions);
+
+ /// \brief Read a named option from the ``Context``.
+ ///
+ /// Reads the option with the check-local name \p LocalName from the
+ /// ``CheckOptions``. If the corresponding key is not present, returns
+ /// \p Default.
+ std::string get(StringRef LocalName, StringRef Default) const;
+
+ /// \brief Read a named option from the ``Context``.
+ ///
+ /// Reads the option with the check-local name \p LocalName from local or
+ /// global ``CheckOptions``. Gets local option first. If local is not
+ /// present, falls back to get global option. If global option is not
+ /// present either, returns Default.
+ std::string getLocalOrGlobal(StringRef LocalName, StringRef Default) const;
+
+ /// \brief Read a named option from the ``Context`` and parse it as an
+ /// integral type ``T``.
+ ///
+ /// Reads the option with the check-local name \p LocalName from the
+ /// ``CheckOptions``. If the corresponding key is not present, returns
+ /// \p Default.
+ template <typename T>
+ typename std::enable_if<std::is_integral<T>::value, T>::type
+ get(StringRef LocalName, T Default) const {
+ std::string Value = get(LocalName, "");
+ T Result = Default;
+ if (!Value.empty())
+ StringRef(Value).getAsInteger(10, Result);
+ return Result;
+ }
+
+ /// \brief Read a named option from the ``Context`` and parse it as an
+ /// integral type ``T``.
+ ///
+ /// Reads the option with the check-local name \p LocalName from local or
+ /// global ``CheckOptions``. Gets local option first. If local is not
+ /// present, falls back to get global option. If global option is not
+ /// present either, returns Default.
+ template <typename T>
+ typename std::enable_if<std::is_integral<T>::value, T>::type
+ getLocalOrGlobal(StringRef LocalName, T Default) const {
+ std::string Value = getLocalOrGlobal(LocalName, "");
+ T Result = Default;
+ if (!Value.empty())
+ StringRef(Value).getAsInteger(10, Result);
+ return Result;
+ }
+
+ /// \brief Stores an option with the check-local name \p LocalName with
+ /// string value \p Value to \p Options.
+ void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName,
+ StringRef Value) const;
+
+ /// \brief Stores an option with the check-local name \p LocalName with
+ /// ``int64_t`` value \p Value to \p Options.
+ void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName,
+ int64_t Value) const;
+
+ private:
+ std::string NamePrefix;
+ const ClangTidyOptions::OptionMap &CheckOptions;
+ };
+
+ OptionsView Options;
+ /// \brief Returns the main file name of the current translation unit.
+ StringRef getCurrentMainFile() const { return Context->getCurrentFile(); }
+ /// \brief Returns the language options from the context.
+ const LangOptions &getLangOpts() const { return Context->getLangOpts(); }
+};
+
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYCHECK_H
diff --git a/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index 7e04d71f..0abd63ee 100644
--- a/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -1,9 +1,8 @@
//===--- tools/extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp ----------=== //
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
@@ -19,8 +18,10 @@
#include "ClangTidyDiagnosticConsumer.h"
#include "ClangTidyOptions.h"
#include "clang/AST/ASTDiagnostic.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Frontend/DiagnosticRenderer.h"
+#include "clang/Tooling/Core/Diagnostic.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include <tuple>
@@ -69,6 +70,9 @@ protected:
SmallVectorImpl<CharSourceRange> &Ranges,
ArrayRef<FixItHint> Hints) override {
assert(Loc.isValid());
+ tooling::DiagnosticMessage *DiagWithFix =
+ Level == DiagnosticsEngine::Note ? &Error.Notes.back() : &Error.Message;
+
for (const auto &FixIt : Hints) {
CharSourceRange Range = FixIt.RemoveRange;
assert(Range.getBegin().isValid() && Range.getEnd().isValid() &&
@@ -78,7 +82,8 @@ protected:
tooling::Replacement Replacement(Loc.getManager(), Range,
FixIt.CodeToInsert);
- llvm::Error Err = Error.Fix[Replacement.getFilePath()].add(Replacement);
+ llvm::Error Err =
+ DiagWithFix->Fix[Replacement.getFilePath()].add(Replacement);
// FIXME: better error handling (at least, don't let other replacements be
// applied).
if (Err) {
@@ -255,7 +260,11 @@ bool ClangTidyContext::treatAsError(StringRef CheckName) const {
return WarningAsErrorFilter->contains(CheckName);
}
-StringRef ClangTidyContext::getCheckName(unsigned DiagnosticID) const {
+std::string ClangTidyContext::getCheckName(unsigned DiagnosticID) const {
+ std::string ClangWarningOption =
+ DiagEngine->getDiagnosticIDs()->getWarningOptionForDiag(DiagnosticID);
+ if (!ClangWarningOption.empty())
+ return "clang-diagnostic-" + ClangWarningOption;
llvm::DenseMap<unsigned, std::string>::const_iterator I =
CheckNamesByDiagnosticID.find(DiagnosticID);
if (I != CheckNamesByDiagnosticID.end())
@@ -306,7 +315,7 @@ static bool IsNOLINTFound(StringRef NolintDirectiveText, StringRef Line,
Line.substr(BracketIndex, BracketEndIndex - BracketIndex);
// Allow disabling all the checks with "*".
if (ChecksStr != "*") {
- StringRef CheckName = Context.getCheckName(DiagID);
+ std::string CheckName = Context.getCheckName(DiagID);
// Allow specifying a few check names, delimited with comma.
SmallVector<StringRef, 1> Checks;
ChecksStr.split(Checks, ',', -1, false);
@@ -403,13 +412,7 @@ void ClangTidyDiagnosticConsumer::HandleDiagnostic(
"A diagnostic note can only be appended to a message.");
} else {
finalizeLastError();
- StringRef WarningOption =
- Context.DiagEngine->getDiagnosticIDs()->getWarningOptionForDiag(
- Info.getID());
- std::string CheckName = !WarningOption.empty()
- ? ("clang-diagnostic-" + WarningOption).str()
- : Context.getCheckName(Info.getID()).str();
-
+ std::string CheckName = Context.getCheckName(Info.getID());
if (CheckName.empty()) {
// This is a compiler diagnostic without a warning option. Assign check
// name based on its level.
@@ -584,9 +587,17 @@ void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
// Compute error sizes.
std::vector<int> Sizes;
- for (const auto &Error : Errors) {
+ std::vector<
+ std::pair<ClangTidyError *, llvm::StringMap<tooling::Replacements> *>>
+ ErrorFixes;
+ for (auto &Error : Errors) {
+ if (const auto *Fix = tooling::selectFirstFix(Error))
+ ErrorFixes.emplace_back(
+ &Error, const_cast<llvm::StringMap<tooling::Replacements> *>(Fix));
+ }
+ for (const auto &ErrorAndFix : ErrorFixes) {
int Size = 0;
- for (const auto &FileAndReplaces : Error.Fix) {
+ for (const auto &FileAndReplaces : *ErrorAndFix.second) {
for (const auto &Replace : FileAndReplaces.second)
Size += Replace.getLength();
}
@@ -595,8 +606,8 @@ void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
// Build events from error intervals.
std::map<std::string, std::vector<Event>> FileEvents;
- for (unsigned I = 0; I < Errors.size(); ++I) {
- for (const auto &FileAndReplace : Errors[I].Fix) {
+ for (unsigned I = 0; I < ErrorFixes.size(); ++I) {
+ for (const auto &FileAndReplace : *ErrorFixes[I].second) {
for (const auto &Replace : FileAndReplace.second) {
unsigned Begin = Replace.getOffset();
unsigned End = Begin + Replace.getLength();
@@ -611,7 +622,7 @@ void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
}
}
- std::vector<bool> Apply(Errors.size(), true);
+ std::vector<bool> Apply(ErrorFixes.size(), true);
for (auto &FileAndEvents : FileEvents) {
std::vector<Event> &Events = FileAndEvents.second;
// Sweep.
@@ -630,10 +641,10 @@ void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
assert(OpenIntervals == 0 && "Amount of begin/end points doesn't match");
}
- for (unsigned I = 0; I < Errors.size(); ++I) {
+ for (unsigned I = 0; I < ErrorFixes.size(); ++I) {
if (!Apply[I]) {
- Errors[I].Fix.clear();
- Errors[I].Notes.emplace_back(
+ ErrorFixes[I].second->clear();
+ ErrorFixes[I].first->Notes.emplace_back(
"this fix will not be applied because it overlaps with another fix");
}
}
diff --git a/clang-tidy/ClangTidyDiagnosticConsumer.h b/clang-tidy/ClangTidyDiagnosticConsumer.h
index a868203f..400f0dc6 100644
--- a/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -1,9 +1,8 @@
//===--- ClangTidyDiagnosticConsumer.h - clang-tidy -------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -139,7 +138,7 @@ public:
/// \brief Returns the name of the clang-tidy check which produced this
/// diagnostic ID.
- StringRef getCheckName(unsigned DiagnosticID) const;
+ std::string getCheckName(unsigned DiagnosticID) const;
/// \brief Returns \c true if the check is enabled for the \c CurrentFile.
///
diff --git a/clang-tidy/ClangTidyForceLinker.h b/clang-tidy/ClangTidyForceLinker.h
index 2e8e8a83..6100cf6a 100644
--- a/clang-tidy/ClangTidyForceLinker.h
+++ b/clang-tidy/ClangTidyForceLinker.h
@@ -1,9 +1,8 @@
//===- ClangTidyForceLinker.h - clang-tidy --------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -78,6 +77,11 @@ static int LLVM_ATTRIBUTE_UNUSED MPIModuleAnchorDestination =
MPIModuleAnchorSource;
#endif
+// This anchor is used to force the linker to link the OpenMPModule.
+extern volatile int OpenMPModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED OpenMPModuleAnchorDestination =
+ OpenMPModuleAnchorSource;
+
// This anchor is used to force the linker to link the PerformanceModule.
extern volatile int PerformanceModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED PerformanceModuleAnchorDestination =
diff --git a/clang-tidy/ClangTidyModule.cpp b/clang-tidy/ClangTidyModule.cpp
index 9dbf0161..7d6de87a 100644
--- a/clang-tidy/ClangTidyModule.cpp
+++ b/clang-tidy/ClangTidyModule.cpp
@@ -1,9 +1,8 @@
//===--- tools/extra/clang-tidy/ClangTidyModule.cpp - Clang tidy tool -----===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
diff --git a/clang-tidy/ClangTidyModule.h b/clang-tidy/ClangTidyModule.h
index 47216368..378f1093 100644
--- a/clang-tidy/ClangTidyModule.h
+++ b/clang-tidy/ClangTidyModule.h
@@ -1,9 +1,8 @@
//===--- ClangTidyModule.h - clang-tidy -------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/ClangTidyModuleRegistry.h b/clang-tidy/ClangTidyModuleRegistry.h
index dc44d14e..891671a7 100644
--- a/clang-tidy/ClangTidyModuleRegistry.h
+++ b/clang-tidy/ClangTidyModuleRegistry.h
@@ -1,9 +1,8 @@
//===--- ClangTidyModuleRegistry.h - clang-tidy -----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/ClangTidyOptions.cpp b/clang-tidy/ClangTidyOptions.cpp
index c40e97c5..e6a60ee6 100644
--- a/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tidy/ClangTidyOptions.cpp
@@ -1,9 +1,8 @@
//===--- ClangTidyOptions.cpp - clang-tidy ----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/ClangTidyOptions.h b/clang-tidy/ClangTidyOptions.h
index 1a753544..87c7cf59 100644
--- a/clang-tidy/ClangTidyOptions.h
+++ b/clang-tidy/ClangTidyOptions.h
@@ -1,9 +1,8 @@
//===--- ClangTidyOptions.h - clang-tidy ------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/ClangTidyProfiling.cpp b/clang-tidy/ClangTidyProfiling.cpp
index fc0a9697..63eed227 100644
--- a/clang-tidy/ClangTidyProfiling.cpp
+++ b/clang-tidy/ClangTidyProfiling.cpp
@@ -1,9 +1,8 @@
//===--- ClangTidyProfiling.cpp - clang-tidy --------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/ClangTidyProfiling.h b/clang-tidy/ClangTidyProfiling.h
index 9d86b8e9..a266e388 100644
--- a/clang-tidy/ClangTidyProfiling.h
+++ b/clang-tidy/ClangTidyProfiling.h
@@ -1,9 +1,8 @@
//===--- ClangTidyProfiling.h - clang-tidy ----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/ExpandModularHeadersPPCallbacks.cpp b/clang-tidy/ExpandModularHeadersPPCallbacks.cpp
new file mode 100644
index 00000000..08037c7f
--- /dev/null
+++ b/clang-tidy/ExpandModularHeadersPPCallbacks.cpp
@@ -0,0 +1,294 @@
+//===- ExpandModularHeadersPPCallbacks.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
+//
+//===----------------------------------------------------------------------===//
+
+#include "ExpandModularHeadersPPCallbacks.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Serialization/ASTReader.h"
+
+namespace clang {
+namespace tooling {
+
+class ExpandModularHeadersPPCallbacks::FileRecorder {
+public:
+ /// Records that a given file entry is needed for replaying callbacks.
+ void addNecessaryFile(const FileEntry *File) { FilesToRecord.insert(File); }
+
+ /// Records content for a file and adds it to the FileSystem.
+ void recordFileContent(const FileEntry *File,
+ const SrcMgr::ContentCache &ContentCache,
+ llvm::vfs::InMemoryFileSystem &InMemoryFs) {
+ // Return if we are not interested in the contents of this file.
+ if (!FilesToRecord.count(File))
+ return;
+
+ // FIXME: Why is this happening? We might be losing contents here.
+ if (!ContentCache.getRawBuffer())
+ return;
+
+ InMemoryFs.addFile(File->getName(), /*ModificationTime=*/0,
+ llvm::MemoryBuffer::getMemBufferCopy(
+ ContentCache.getRawBuffer()->getBuffer()));
+ // Remove the file from the set of necessary files.
+ FilesToRecord.erase(File);
+ }
+
+ /// Makes sure we have contents for all the files we were interested in. Ideally
+ /// `FilesToRecord` should be empty.
+ void checkAllFilesRecorded() {
+ for (auto FileEntry : FilesToRecord)
+ llvm::errs() << "Did not record contents for input file: "
+ << FileEntry->getName() << "\n";
+ }
+
+private:
+ /// A set of files whose contents are to be recorded.
+ llvm::DenseSet<const FileEntry *> FilesToRecord;
+};
+
+ExpandModularHeadersPPCallbacks::ExpandModularHeadersPPCallbacks(
+ CompilerInstance *CI,
+ IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS)
+ : Recorder(llvm::make_unique<FileRecorder>()), Compiler(*CI),
+ InMemoryFs(new llvm::vfs::InMemoryFileSystem),
+ Sources(Compiler.getSourceManager()),
+ // Forward the new diagnostics to the original DiagnosticConsumer.
+ Diags(new DiagnosticIDs, new DiagnosticOptions,
+ new ForwardingDiagnosticConsumer(Compiler.getDiagnosticClient())),
+ LangOpts(Compiler.getLangOpts()) {
+ // Add a FileSystem containing the extra files needed in place of modular
+ // headers.
+ OverlayFS->pushOverlay(InMemoryFs);
+
+ Diags.setSourceManager(&Sources);
+
+ LangOpts.Modules = false;
+
+ auto HSO = std::make_shared<HeaderSearchOptions>();
+ *HSO = Compiler.getHeaderSearchOpts();
+
+ HeaderInfo = llvm::make_unique<HeaderSearch>(HSO, Sources, Diags, LangOpts,
+ &Compiler.getTarget());
+
+ auto PO = std::make_shared<PreprocessorOptions>();
+ *PO = Compiler.getPreprocessorOpts();
+
+ PP = llvm::make_unique<clang::Preprocessor>(PO, Diags, LangOpts, Sources,
+ *HeaderInfo, ModuleLoader,
+ /*IILookup=*/nullptr,
+ /*OwnsHeaderSearch=*/false);
+ PP->Initialize(Compiler.getTarget(), Compiler.getAuxTarget());
+ InitializePreprocessor(*PP, *PO, Compiler.getPCHContainerReader(),
+ Compiler.getFrontendOpts());
+ ApplyHeaderSearchOptions(*HeaderInfo, *HSO, LangOpts,
+ Compiler.getTarget().getTriple());
+}
+
+ExpandModularHeadersPPCallbacks::~ExpandModularHeadersPPCallbacks() = default;
+
+Preprocessor *ExpandModularHeadersPPCallbacks::getPreprocessor() const {
+ return PP.get();
+}
+
+void ExpandModularHeadersPPCallbacks::handleModuleFile(
+ serialization::ModuleFile *MF) {
+ if (!MF)
+ return;
+ // Avoid processing a ModuleFile more than once.
+ if (VisitedModules.count(MF))
+ return;
+ VisitedModules.insert(MF);
+
+ // Visit all the input files of this module and mark them to record their
+ // contents later.
+ Compiler.getModuleManager()->visitInputFiles(
+ *MF, true, false,
+ [this](const serialization::InputFile &IF, bool /*IsSystem*/) {
+ Recorder->addNecessaryFile(IF.getFile());
+ });
+ // Recursively handle all transitively imported modules.
+ for (auto Import : MF->Imports)
+ handleModuleFile(Import);
+}
+
+void ExpandModularHeadersPPCallbacks::parseToLocation(SourceLocation Loc) {
+ // Load all source locations present in the external sources.
+ for (unsigned I = 0, N = Sources.loaded_sloc_entry_size(); I != N; ++I) {
+ Sources.getLoadedSLocEntry(I, nullptr);
+ }
+ // Record contents of files we are interested in and add to the FileSystem.
+ for (auto It = Sources.fileinfo_begin(); It != Sources.fileinfo_end(); ++It) {
+ Recorder->recordFileContent(It->getFirst(), *It->getSecond(), *InMemoryFs);
+ }
+ Recorder->checkAllFilesRecorded();
+
+ if (!StartedLexing) {
+ StartedLexing = true;
+ PP->Lex(CurrentToken);
+ }
+ while (!CurrentToken.is(tok::eof) &&
+ Sources.isBeforeInTranslationUnit(CurrentToken.getLocation(), Loc)) {
+ PP->Lex(CurrentToken);
+ }
+}
+
+void ExpandModularHeadersPPCallbacks::FileChanged(
+ SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType, FileID PrevFID = FileID()) {
+ if (!EnteredMainFile) {
+ EnteredMainFile = true;
+ PP->EnterMainSourceFile();
+ }
+}
+
+void ExpandModularHeadersPPCallbacks::InclusionDirective(
+ SourceLocation DirectiveLoc, const Token &IncludeToken,
+ StringRef IncludedFilename, bool IsAngled, CharSourceRange FilenameRange,
+ const FileEntry *IncludedFile, StringRef SearchPath, StringRef RelativePath,
+ const Module *Imported, SrcMgr::CharacteristicKind FileType) {
+ if (Imported) {
+ serialization::ModuleFile *MF =
+ Compiler.getModuleManager()->getModuleManager().lookup(
+ Imported->getASTFile());
+ handleModuleFile(MF);
+ }
+ parseToLocation(DirectiveLoc);
+}
+
+void ExpandModularHeadersPPCallbacks::EndOfMainFile() {
+ while (!CurrentToken.is(tok::eof))
+ PP->Lex(CurrentToken);
+}
+
+// Handle all other callbacks.
+// Just parse to the corresponding location to generate the same callback for
+// the PPCallbacks registered in our custom preprocessor.
+void ExpandModularHeadersPPCallbacks::Ident(SourceLocation Loc, StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaDirective(SourceLocation Loc,
+ PragmaIntroducerKind) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaComment(SourceLocation Loc,
+ const IdentifierInfo *,
+ StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaDetectMismatch(SourceLocation Loc,
+ StringRef,
+ StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaDebug(SourceLocation Loc,
+ StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaMessage(SourceLocation Loc,
+ StringRef,
+ PragmaMessageKind,
+ StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPush(SourceLocation Loc,
+ StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPop(SourceLocation Loc,
+ StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaDiagnostic(SourceLocation Loc,
+ StringRef,
+ diag::Severity,
+ StringRef) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::HasInclude(SourceLocation Loc, StringRef,
+ bool, const FileEntry *,
+ SrcMgr::CharacteristicKind) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaOpenCLExtension(
+ SourceLocation NameLoc, const IdentifierInfo *, SourceLocation StateLoc,
+ unsigned) {
+ // FIME: Figure out whether it's the right location to parse to.
+ parseToLocation(NameLoc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaWarning(SourceLocation Loc,
+ StringRef, ArrayRef<int>) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaWarningPush(SourceLocation Loc,
+ int) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaWarningPop(SourceLocation Loc) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullBegin(
+ SourceLocation Loc) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullEnd(
+ SourceLocation Loc) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::MacroExpands(const Token &MacroNameTok,
+ const MacroDefinition &,
+ SourceRange Range,
+ const MacroArgs *) {
+ // FIME: Figure out whether it's the right location to parse to.
+ parseToLocation(Range.getBegin());
+}
+void ExpandModularHeadersPPCallbacks::MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) {
+ parseToLocation(MD->getLocation());
+}
+void ExpandModularHeadersPPCallbacks::MacroUndefined(
+ const Token &, const MacroDefinition &, const MacroDirective *Undef) {
+ if (Undef)
+ parseToLocation(Undef->getLocation());
+}
+void ExpandModularHeadersPPCallbacks::Defined(const Token &MacroNameTok,
+ const MacroDefinition &,
+ SourceRange Range) {
+ // FIME: Figure out whether it's the right location to parse to.
+ parseToLocation(Range.getBegin());
+}
+void ExpandModularHeadersPPCallbacks::SourceRangeSkipped(
+ SourceRange Range, SourceLocation EndifLoc) {
+ // FIME: Figure out whether it's the right location to parse to.
+ parseToLocation(EndifLoc);
+}
+void ExpandModularHeadersPPCallbacks::If(SourceLocation Loc, SourceRange,
+ ConditionValueKind) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::Elif(SourceLocation Loc, SourceRange,
+ ConditionValueKind, SourceLocation) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::Ifdef(SourceLocation Loc, const Token &,
+ const MacroDefinition &) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::Ifndef(SourceLocation Loc, const Token &,
+ const MacroDefinition &) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::Else(SourceLocation Loc, SourceLocation) {
+ parseToLocation(Loc);
+}
+void ExpandModularHeadersPPCallbacks::Endif(SourceLocation Loc,
+ SourceLocation) {
+ parseToLocation(Loc);
+}
+
+} // namespace tooling
+} // namespace clang
diff --git a/clang-tidy/ExpandModularHeadersPPCallbacks.h b/clang-tidy/ExpandModularHeadersPPCallbacks.h
new file mode 100644
index 00000000..4b431042
--- /dev/null
+++ b/clang-tidy/ExpandModularHeadersPPCallbacks.h
@@ -0,0 +1,137 @@
+//===- ExpandModularHeadersPPCallbacks.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_TOOLING_EXPANDMODULARHEADERSPPCALLBACKS_H_
+#define LLVM_CLANG_TOOLING_EXPANDMODULARHEADERSPPCALLBACKS_H_
+
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/DenseSet.h"
+
+namespace clang {
+class CompilerInstance;
+
+namespace serialization {
+class ModuleFile;
+} // namespace serialization
+
+namespace tooling {
+
+/// \brief Handles PPCallbacks and re-runs preprocessing of the whole
+/// translation unit with modules disabled.
+///
+/// This way it's possible to get PPCallbacks for the whole translation unit
+/// including the contents of the modular headers and all their transitive
+/// includes.
+///
+/// This allows existing tools based on PPCallbacks to retain their functionality
+/// when running with C++ modules enabled. This only works in the backwards
+/// compatible modules mode, i.e. when code can still be parsed in non-modular
+/// way.
+class ExpandModularHeadersPPCallbacks : public PPCallbacks {
+public:
+ ExpandModularHeadersPPCallbacks(
+ CompilerInstance *Compiler,
+ IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS);
+ ~ExpandModularHeadersPPCallbacks();
+
+ /// \brief Returns the preprocessor that provides callbacks for the whole
+ /// translation unit, including the main file, textual headers, and modular
+ /// headers.
+ ///
+ /// This preprocessor is separate from the one used by the rest of the
+ /// compiler.
+ Preprocessor *getPreprocessor() const;
+
+private:
+ class FileRecorder;
+
+ void handleModuleFile(serialization::ModuleFile *MF);
+ void parseToLocation(SourceLocation Loc);
+
+ // Handle PPCallbacks.
+ void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID) override;
+
+ void InclusionDirective(SourceLocation DirectiveLoc,
+ const Token &IncludeToken, StringRef IncludedFilename,
+ bool IsAngled, CharSourceRange FilenameRange,
+ const FileEntry *IncludedFile, StringRef SearchPath,
+ StringRef RelativePath, const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override;
+
+ void EndOfMainFile() override;
+
+ // Handle all other callbacks.
+ // Just parse to the corresponding location to generate PPCallbacks for the
+ // corresponding range
+ void Ident(SourceLocation Loc, StringRef) override;
+ void PragmaDirective(SourceLocation Loc, PragmaIntroducerKind) override;
+ void PragmaComment(SourceLocation Loc, const IdentifierInfo *,
+ StringRef) override;
+ void PragmaDetectMismatch(SourceLocation Loc, StringRef, StringRef) override;
+ void PragmaDebug(SourceLocation Loc, StringRef) override;
+ void PragmaMessage(SourceLocation Loc, StringRef, PragmaMessageKind,
+ StringRef) override;
+ void PragmaDiagnosticPush(SourceLocation Loc, StringRef) override;
+ void PragmaDiagnosticPop(SourceLocation Loc, StringRef) override;
+ void PragmaDiagnostic(SourceLocation Loc, StringRef, diag::Severity,
+ StringRef) override;
+ void HasInclude(SourceLocation Loc, StringRef, bool, const FileEntry *,
+ SrcMgr::CharacteristicKind) override;
+ void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *,
+ SourceLocation StateLoc, unsigned) override;
+ void PragmaWarning(SourceLocation Loc, StringRef, ArrayRef<int>) override;
+ void PragmaWarningPush(SourceLocation Loc, int) override;
+ void PragmaWarningPop(SourceLocation Loc) override;
+ void PragmaAssumeNonNullBegin(SourceLocation Loc) override;
+ void PragmaAssumeNonNullEnd(SourceLocation Loc) override;
+ void MacroExpands(const Token &MacroNameTok, const MacroDefinition &,
+ SourceRange Range, const MacroArgs *) override;
+ void MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) override;
+ void MacroUndefined(const Token &, const MacroDefinition &,
+ const MacroDirective *Undef) override;
+ void Defined(const Token &MacroNameTok, const MacroDefinition &,
+ SourceRange Range) override;
+ void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override;
+ void If(SourceLocation Loc, SourceRange, ConditionValueKind) override;
+ void Elif(SourceLocation Loc, SourceRange, ConditionValueKind,
+ SourceLocation) override;
+ void Ifdef(SourceLocation Loc, const Token &,
+ const MacroDefinition &) override;
+ void Ifndef(SourceLocation Loc, const Token &,
+ const MacroDefinition &) override;
+ void Else(SourceLocation Loc, SourceLocation) override;
+ void Endif(SourceLocation Loc, SourceLocation) override;
+
+ std::unique_ptr<FileRecorder> Recorder;
+ // Set of all the modules visited. Avoids processing a module more than once.
+ llvm::DenseSet<serialization::ModuleFile *> VisitedModules;
+
+ CompilerInstance &Compiler;
+ // Additional filesystem for replay. Provides all input files from modules.
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFs;
+
+ SourceManager &Sources;
+ DiagnosticsEngine Diags;
+ LangOptions LangOpts;
+ TrivialModuleLoader ModuleLoader;
+
+ std::unique_ptr<HeaderSearch> HeaderInfo;
+ std::unique_ptr<Preprocessor> PP;
+ bool EnteredMainFile = false;
+ bool StartedLexing = false;
+ Token CurrentToken;
+};
+
+} // namespace tooling
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLING_EXPANDMODULARHEADERSPPCALLBACKS_H_
diff --git a/clang-tidy/abseil/AbseilMatcher.h b/clang-tidy/abseil/AbseilMatcher.h
index 116aa953..3f7529d1 100644
--- a/clang-tidy/abseil/AbseilMatcher.h
+++ b/clang-tidy/abseil/AbseilMatcher.h
@@ -1,9 +1,8 @@
//===- AbseilMatcher.h - clang-tidy ---------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/AbseilTidyModule.cpp b/clang-tidy/abseil/AbseilTidyModule.cpp
index 18140015..c70ef900 100644
--- a/clang-tidy/abseil/AbseilTidyModule.cpp
+++ b/clang-tidy/abseil/AbseilTidyModule.cpp
@@ -1,26 +1,30 @@
//===------- AbseilTidyModule.cpp - clang-tidy ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
+#include "DurationAdditionCheck.h"
#include "DurationComparisonCheck.h"
+#include "DurationConversionCastCheck.h"
#include "DurationDivisionCheck.h"
#include "DurationFactoryFloatCheck.h"
#include "DurationFactoryScaleCheck.h"
#include "DurationSubtractionCheck.h"
+#include "DurationUnnecessaryConversionCheck.h"
#include "FasterStrsplitDelimiterCheck.h"
#include "NoInternalDependenciesCheck.h"
#include "NoNamespaceCheck.h"
#include "RedundantStrcatCallsCheck.h"
#include "StringFindStartswithCheck.h"
#include "StrCatAppendCheck.h"
+#include "TimeComparisonCheck.h"
+#include "TimeSubtractionCheck.h"
#include "UpgradeDurationConversionsCheck.h"
namespace clang {
@@ -30,8 +34,12 @@ namespace abseil {
class AbseilModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+ CheckFactories.registerCheck<DurationAdditionCheck>(
+ "abseil-duration-addition");
CheckFactories.registerCheck<DurationComparisonCheck>(
"abseil-duration-comparison");
+ CheckFactories.registerCheck<DurationConversionCastCheck>(
+ "abseil-duration-conversion-cast");
CheckFactories.registerCheck<DurationDivisionCheck>(
"abseil-duration-division");
CheckFactories.registerCheck<DurationFactoryFloatCheck>(
@@ -40,6 +48,8 @@ public:
"abseil-duration-factory-scale");
CheckFactories.registerCheck<DurationSubtractionCheck>(
"abseil-duration-subtraction");
+ CheckFactories.registerCheck<DurationUnnecessaryConversionCheck>(
+ "abseil-duration-unnecessary-conversion");
CheckFactories.registerCheck<FasterStrsplitDelimiterCheck>(
"abseil-faster-strsplit-delimiter");
CheckFactories.registerCheck<NoInternalDependenciesCheck>(
@@ -51,6 +61,10 @@ public:
"abseil-str-cat-append");
CheckFactories.registerCheck<StringFindStartswithCheck>(
"abseil-string-find-startswith");
+ CheckFactories.registerCheck<TimeComparisonCheck>(
+ "abseil-time-comparison");
+ CheckFactories.registerCheck<TimeSubtractionCheck>(
+ "abseil-time-subtraction");
CheckFactories.registerCheck<UpgradeDurationConversionsCheck>(
"abseil-upgrade-duration-conversions");
}
diff --git a/clang-tidy/abseil/CMakeLists.txt b/clang-tidy/abseil/CMakeLists.txt
index bf9d9e84..3f88da62 100644
--- a/clang-tidy/abseil/CMakeLists.txt
+++ b/clang-tidy/abseil/CMakeLists.txt
@@ -2,18 +2,23 @@ set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyAbseilModule
AbseilTidyModule.cpp
+ DurationAdditionCheck.cpp
DurationComparisonCheck.cpp
+ DurationConversionCastCheck.cpp
DurationDivisionCheck.cpp
DurationFactoryFloatCheck.cpp
DurationFactoryScaleCheck.cpp
DurationRewriter.cpp
DurationSubtractionCheck.cpp
+ DurationUnnecessaryConversionCheck.cpp
FasterStrsplitDelimiterCheck.cpp
NoInternalDependenciesCheck.cpp
NoNamespaceCheck.cpp
RedundantStrcatCallsCheck.cpp
StrCatAppendCheck.cpp
StringFindStartswithCheck.cpp
+ TimeComparisonCheck.cpp
+ TimeSubtractionCheck.cpp
UpgradeDurationConversionsCheck.cpp
LINK_LIBS
diff --git a/clang-tidy/abseil/DurationAdditionCheck.cpp b/clang-tidy/abseil/DurationAdditionCheck.cpp
new file mode 100644
index 00000000..60047096
--- /dev/null
+++ b/clang-tidy/abseil/DurationAdditionCheck.cpp
@@ -0,0 +1,73 @@
+//===--- DurationAdditionCheck.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 "DurationAdditionCheck.h"
+#include "DurationRewriter.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+void DurationAdditionCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(
+ binaryOperator(hasOperatorName("+"),
+ hasEitherOperand(expr(ignoringParenImpCasts(
+ callExpr(callee(functionDecl(TimeConversionFunction())
+ .bind("function_decl")))
+ .bind("call")))))
+ .bind("binop"),
+ this);
+}
+
+void DurationAdditionCheck::check(const MatchFinder::MatchResult &Result) {
+ const BinaryOperator *Binop =
+ Result.Nodes.getNodeAs<clang::BinaryOperator>("binop");
+ const CallExpr *Call = Result.Nodes.getNodeAs<clang::CallExpr>("call");
+
+ // Don't try to replace things inside of macro definitions.
+ if (Binop->getExprLoc().isMacroID() || Binop->getExprLoc().isInvalid())
+ return;
+
+ llvm::Optional<DurationScale> Scale = getScaleForTimeInverse(
+ Result.Nodes.getNodeAs<clang::FunctionDecl>("function_decl")->getName());
+ if (!Scale)
+ return;
+
+ llvm::StringRef TimeFactory = getTimeInverseForScale(*Scale);
+
+ FixItHint Hint;
+ if (Call == Binop->getLHS()->IgnoreParenImpCasts()) {
+ Hint = FixItHint::CreateReplacement(
+ Binop->getSourceRange(),
+ (llvm::Twine(TimeFactory) + "(" +
+ tooling::fixit::getText(*Call->getArg(0), *Result.Context) + " + " +
+ rewriteExprFromNumberToDuration(Result, *Scale, Binop->getRHS()) + ")")
+ .str());
+ } else {
+ assert(Call == Binop->getRHS()->IgnoreParenImpCasts() &&
+ "Call should be found on the RHS");
+ Hint = FixItHint::CreateReplacement(
+ Binop->getSourceRange(),
+ (llvm::Twine(TimeFactory) + "(" +
+ rewriteExprFromNumberToDuration(Result, *Scale, Binop->getLHS()) +
+ " + " + tooling::fixit::getText(*Call->getArg(0), *Result.Context) +
+ ")")
+ .str());
+ }
+
+ diag(Binop->getBeginLoc(), "perform addition in the duration domain") << Hint;
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/abseil/DurationAdditionCheck.h b/clang-tidy/abseil/DurationAdditionCheck.h
new file mode 100644
index 00000000..64b4d89e
--- /dev/null
+++ b/clang-tidy/abseil/DurationAdditionCheck.h
@@ -0,0 +1,35 @@
+//===--- DurationAdditionCheck.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_ABSEIL_TIMEADDITIONCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMEADDITIONCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// Checks for cases where addition should be performed in the
+/// ``absl::Time`` domain.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/abseil-duration-addition.html
+class DurationAdditionCheck : public ClangTidyCheck {
+public:
+ DurationAdditionCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMEADDITIONCHECK_H
diff --git a/clang-tidy/abseil/DurationComparisonCheck.cpp b/clang-tidy/abseil/DurationComparisonCheck.cpp
index 963da3f3..a6e12dd8 100644
--- a/clang-tidy/abseil/DurationComparisonCheck.cpp
+++ b/clang-tidy/abseil/DurationComparisonCheck.cpp
@@ -1,9 +1,8 @@
//===--- DurationComparisonCheck.cpp - clang-tidy -------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -19,35 +18,11 @@ namespace clang {
namespace tidy {
namespace abseil {
-/// Return `true` if `E` is a either: not a macro at all; or an argument to
-/// one. In the latter case, we should still transform it.
-static bool IsValidMacro(const MatchFinder::MatchResult &Result,
- const Expr *E) {
- if (!E->getBeginLoc().isMacroID())
- return true;
-
- SourceLocation Loc = E->getBeginLoc();
- // We want to get closer towards the initial macro typed into the source only
- // if the location is being expanded as a macro argument.
- while (Result.SourceManager->isMacroArgExpansion(Loc)) {
- // We are calling getImmediateMacroCallerLoc, but note it is essentially
- // equivalent to calling getImmediateSpellingLoc in this context according
- // to Clang implementation. We are not calling getImmediateSpellingLoc
- // because Clang comment says it "should not generally be used by clients."
- Loc = Result.SourceManager->getImmediateMacroCallerLoc(Loc);
- }
- return !Loc.isMacroID();
-}
-
void DurationComparisonCheck::registerMatchers(MatchFinder *Finder) {
- auto Matcher =
- binaryOperator(anyOf(hasOperatorName(">"), hasOperatorName(">="),
- hasOperatorName("=="), hasOperatorName("<="),
- hasOperatorName("<")),
- hasEitherOperand(ignoringImpCasts(callExpr(
- callee(functionDecl(DurationConversionFunction())
- .bind("function_decl"))))))
- .bind("binop");
+ auto Matcher = expr(comparisonOperatorWithCallee(functionDecl(
+ functionDecl(DurationConversionFunction())
+ .bind("function_decl"))))
+ .bind("binop");
Finder->addMatcher(Matcher, this);
}
@@ -55,7 +30,7 @@ void DurationComparisonCheck::registerMatchers(MatchFinder *Finder) {
void DurationComparisonCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Binop = Result.Nodes.getNodeAs<BinaryOperator>("binop");
- llvm::Optional<DurationScale> Scale = getScaleForInverse(
+ llvm::Optional<DurationScale> Scale = getScaleForDurationInverse(
Result.Nodes.getNodeAs<FunctionDecl>("function_decl")->getName());
if (!Scale)
return;
@@ -64,8 +39,7 @@ void DurationComparisonCheck::check(const MatchFinder::MatchResult &Result) {
// want to handle the case of rewriting both sides. This is much simpler if
// we unconditionally try and rewrite both, and let the rewriter determine
// if nothing needs to be done.
- if (!IsValidMacro(Result, Binop->getLHS()) ||
- !IsValidMacro(Result, Binop->getRHS()))
+ if (isInMacro(Result, Binop->getLHS()) || isInMacro(Result, Binop->getRHS()))
return;
std::string LhsReplacement =
rewriteExprFromNumberToDuration(Result, *Scale, Binop->getLHS());
diff --git a/clang-tidy/abseil/DurationComparisonCheck.h b/clang-tidy/abseil/DurationComparisonCheck.h
index 2d82f8ee..4c7085fc 100644
--- a/clang-tidy/abseil/DurationComparisonCheck.h
+++ b/clang-tidy/abseil/DurationComparisonCheck.h
@@ -1,9 +1,8 @@
//===--- DurationComparisonCheck.h - clang-tidy -----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/DurationConversionCastCheck.cpp b/clang-tidy/abseil/DurationConversionCastCheck.cpp
new file mode 100644
index 00000000..d9e91554
--- /dev/null
+++ b/clang-tidy/abseil/DurationConversionCastCheck.cpp
@@ -0,0 +1,85 @@
+//===--- DurationConversionCastCheck.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 "DurationConversionCastCheck.h"
+#include "DurationRewriter.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+void DurationConversionCastCheck::registerMatchers(MatchFinder *Finder) {
+ auto CallMatcher = ignoringImpCasts(callExpr(
+ callee(functionDecl(DurationConversionFunction()).bind("func_decl")),
+ hasArgument(0, expr().bind("arg"))));
+
+ Finder->addMatcher(
+ expr(anyOf(
+ cxxStaticCastExpr(hasSourceExpression(CallMatcher)).bind("cast_expr"),
+ cStyleCastExpr(hasSourceExpression(CallMatcher)).bind("cast_expr"),
+ cxxFunctionalCastExpr(hasSourceExpression(CallMatcher))
+ .bind("cast_expr"))),
+ this);
+}
+
+void DurationConversionCastCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ const auto *MatchedCast =
+ Result.Nodes.getNodeAs<ExplicitCastExpr>("cast_expr");
+
+ if (isInMacro(Result, MatchedCast))
+ return;
+
+ const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("func_decl");
+ const auto *Arg = Result.Nodes.getNodeAs<Expr>("arg");
+ StringRef ConversionFuncName = FuncDecl->getName();
+
+ llvm::Optional<DurationScale> Scale =
+ getScaleForDurationInverse(ConversionFuncName);
+ if (!Scale)
+ return;
+
+ // Casting a double to an integer.
+ if (MatchedCast->getTypeAsWritten()->isIntegerType() &&
+ ConversionFuncName.contains("Double")) {
+ llvm::StringRef NewFuncName = getDurationInverseForScale(*Scale).second;
+
+ diag(MatchedCast->getBeginLoc(),
+ "duration should be converted directly to an integer rather than "
+ "through a type cast")
+ << FixItHint::CreateReplacement(
+ MatchedCast->getSourceRange(),
+ (llvm::Twine(NewFuncName.substr(2)) + "(" +
+ tooling::fixit::getText(*Arg, *Result.Context) + ")")
+ .str());
+ }
+
+ // Casting an integer to a double.
+ if (MatchedCast->getTypeAsWritten()->isRealFloatingType() &&
+ ConversionFuncName.contains("Int64")) {
+ llvm::StringRef NewFuncName = getDurationInverseForScale(*Scale).first;
+
+ diag(MatchedCast->getBeginLoc(), "duration should be converted directly to "
+ "a floating-piont number rather than "
+ "through a type cast")
+ << FixItHint::CreateReplacement(
+ MatchedCast->getSourceRange(),
+ (llvm::Twine(NewFuncName.substr(2)) + "(" +
+ tooling::fixit::getText(*Arg, *Result.Context) + ")")
+ .str());
+ }
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/abseil/DurationConversionCastCheck.h b/clang-tidy/abseil/DurationConversionCastCheck.h
new file mode 100644
index 00000000..bc1d6203
--- /dev/null
+++ b/clang-tidy/abseil/DurationConversionCastCheck.h
@@ -0,0 +1,35 @@
+//===--- DurationConversionCastCheck.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_ABSEIL_DURATIONCONVERSIONCASTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_DURATIONCONVERSIONCASTCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// Checks for casts of ``absl::Duration`` conversion functions, and recommends
+/// the right conversion function instead.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/abseil-duration-conversion-cast.html
+class DurationConversionCastCheck : public ClangTidyCheck {
+public:
+ DurationConversionCastCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_DURATIONCONVERSIONCASTCHECK_H
diff --git a/clang-tidy/abseil/DurationDivisionCheck.cpp b/clang-tidy/abseil/DurationDivisionCheck.cpp
index 5edc1587..82c405f9 100644
--- a/clang-tidy/abseil/DurationDivisionCheck.cpp
+++ b/clang-tidy/abseil/DurationDivisionCheck.cpp
@@ -1,9 +1,8 @@
//===--- DurationDivisionCheck.cpp - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/DurationDivisionCheck.h b/clang-tidy/abseil/DurationDivisionCheck.h
index 932d0296..ac81e059 100644
--- a/clang-tidy/abseil/DurationDivisionCheck.h
+++ b/clang-tidy/abseil/DurationDivisionCheck.h
@@ -1,9 +1,8 @@
//===--- DurationDivisionCheck.h - clang-tidy--------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/DurationFactoryFloatCheck.cpp b/clang-tidy/abseil/DurationFactoryFloatCheck.cpp
index 06765144..d46265d1 100644
--- a/clang-tidy/abseil/DurationFactoryFloatCheck.cpp
+++ b/clang-tidy/abseil/DurationFactoryFloatCheck.cpp
@@ -1,9 +1,8 @@
//===--- DurationFactoryFloatCheck.cpp - clang-tidy -----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/DurationFactoryFloatCheck.h b/clang-tidy/abseil/DurationFactoryFloatCheck.h
index 8d215e44..cc773153 100644
--- a/clang-tidy/abseil/DurationFactoryFloatCheck.h
+++ b/clang-tidy/abseil/DurationFactoryFloatCheck.h
@@ -1,9 +1,8 @@
//===--- DurationFactoryFloatCheck.h - clang-tidy ---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/DurationFactoryScaleCheck.cpp b/clang-tidy/abseil/DurationFactoryScaleCheck.cpp
index e56ed819..c3b41919 100644
--- a/clang-tidy/abseil/DurationFactoryScaleCheck.cpp
+++ b/clang-tidy/abseil/DurationFactoryScaleCheck.cpp
@@ -1,9 +1,8 @@
//===--- DurationFactoryScaleCheck.cpp - clang-tidy -----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -210,7 +209,7 @@ void DurationFactoryScaleCheck::check(const MatchFinder::MatchResult &Result) {
diag(Call->getBeginLoc(), "internal duration scaling can be removed")
<< FixItHint::CreateReplacement(
Call->getSourceRange(),
- (llvm::Twine(getFactoryForScale(*NewScale)) + "(" +
+ (llvm::Twine(getDurationFactoryForScale(*NewScale)) + "(" +
tooling::fixit::getText(*Remainder, *Result.Context) + ")")
.str());
}
@@ -223,7 +222,7 @@ void DurationFactoryScaleCheck::check(const MatchFinder::MatchResult &Result) {
diag(Call->getBeginLoc(), "internal duration scaling can be removed")
<< FixItHint::CreateReplacement(
Call->getSourceRange(),
- (llvm::Twine(getFactoryForScale(*NewScale)) + "(" +
+ (llvm::Twine(getDurationFactoryForScale(*NewScale)) + "(" +
tooling::fixit::getText(*Remainder, *Result.Context) + ")")
.str());
}
diff --git a/clang-tidy/abseil/DurationFactoryScaleCheck.h b/clang-tidy/abseil/DurationFactoryScaleCheck.h
index 606724e6..3b79b91d 100644
--- a/clang-tidy/abseil/DurationFactoryScaleCheck.h
+++ b/clang-tidy/abseil/DurationFactoryScaleCheck.h
@@ -1,9 +1,8 @@
//===--- DurationFactoryScaleCheck.h - clang-tidy ---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/DurationRewriter.cpp b/clang-tidy/abseil/DurationRewriter.cpp
index ed648897..3466cdbb 100644
--- a/clang-tidy/abseil/DurationRewriter.cpp
+++ b/clang-tidy/abseil/DurationRewriter.cpp
@@ -1,9 +1,8 @@
//===--- DurationRewriter.cpp - clang-tidy --------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -38,7 +37,7 @@ truncateIfIntegral(const FloatingLiteral &FloatLiteral) {
}
const std::pair<llvm::StringRef, llvm::StringRef> &
-getInverseForScale(DurationScale Scale) {
+getDurationInverseForScale(DurationScale Scale) {
static const llvm::IndexedMap<std::pair<llvm::StringRef, llvm::StringRef>,
DurationScale2IndexFunctor>
InverseMap = []() {
@@ -72,7 +71,7 @@ static llvm::Optional<std::string>
rewriteInverseDurationCall(const MatchFinder::MatchResult &Result,
DurationScale Scale, const Expr &Node) {
const std::pair<llvm::StringRef, llvm::StringRef> &InverseFunctions =
- getInverseForScale(Scale);
+ getDurationInverseForScale(Scale);
if (const auto *MaybeCallArg = selectFirst<const Expr>(
"e",
match(callExpr(callee(functionDecl(hasAnyName(
@@ -85,8 +84,24 @@ rewriteInverseDurationCall(const MatchFinder::MatchResult &Result,
return llvm::None;
}
+/// If `Node` is a call to the inverse of `Scale`, return that inverse's
+/// argument, otherwise None.
+static llvm::Optional<std::string>
+rewriteInverseTimeCall(const MatchFinder::MatchResult &Result,
+ DurationScale Scale, const Expr &Node) {
+ llvm::StringRef InverseFunction = getTimeInverseForScale(Scale);
+ if (const auto *MaybeCallArg = selectFirst<const Expr>(
+ "e", match(callExpr(callee(functionDecl(hasName(InverseFunction))),
+ hasArgument(0, expr().bind("e"))),
+ Node, *Result.Context))) {
+ return tooling::fixit::getText(*MaybeCallArg, *Result.Context).str();
+ }
+
+ return llvm::None;
+}
+
/// Returns the factory function name for a given `Scale`.
-llvm::StringRef getFactoryForScale(DurationScale Scale) {
+llvm::StringRef getDurationFactoryForScale(DurationScale Scale) {
switch (Scale) {
case DurationScale::Hours:
return "absl::Hours";
@@ -104,6 +119,43 @@ llvm::StringRef getFactoryForScale(DurationScale Scale) {
llvm_unreachable("unknown scaling factor");
}
+llvm::StringRef getTimeFactoryForScale(DurationScale Scale) {
+ switch (Scale) {
+ case DurationScale::Hours:
+ return "absl::FromUnixHours";
+ case DurationScale::Minutes:
+ return "absl::FromUnixMinutes";
+ case DurationScale::Seconds:
+ return "absl::FromUnixSeconds";
+ case DurationScale::Milliseconds:
+ return "absl::FromUnixMillis";
+ case DurationScale::Microseconds:
+ return "absl::FromUnixMicros";
+ case DurationScale::Nanoseconds:
+ return "absl::FromUnixNanos";
+ }
+ llvm_unreachable("unknown scaling factor");
+}
+
+/// Returns the Time factory function name for a given `Scale`.
+llvm::StringRef getTimeInverseForScale(DurationScale scale) {
+ switch (scale) {
+ case DurationScale::Hours:
+ return "absl::ToUnixHours";
+ case DurationScale::Minutes:
+ return "absl::ToUnixMinutes";
+ case DurationScale::Seconds:
+ return "absl::ToUnixSeconds";
+ case DurationScale::Milliseconds:
+ return "absl::ToUnixMillis";
+ case DurationScale::Microseconds:
+ return "absl::ToUnixMicros";
+ case DurationScale::Nanoseconds:
+ return "absl::ToUnixNanos";
+ }
+ llvm_unreachable("unknown scaling factor");
+}
+
/// Returns `true` if `Node` is a value which evaluates to a literal `0`.
bool IsLiteralZero(const MatchFinder::MatchResult &Result, const Expr &Node) {
auto ZeroMatcher =
@@ -176,7 +228,7 @@ std::string simplifyDurationFactoryArg(const MatchFinder::MatchResult &Result,
return tooling::fixit::getText(Node, *Result.Context).str();
}
-llvm::Optional<DurationScale> getScaleForInverse(llvm::StringRef Name) {
+llvm::Optional<DurationScale> getScaleForDurationInverse(llvm::StringRef Name) {
static const llvm::StringMap<DurationScale> ScaleMap(
{{"ToDoubleHours", DurationScale::Hours},
{"ToInt64Hours", DurationScale::Hours},
@@ -198,6 +250,22 @@ llvm::Optional<DurationScale> getScaleForInverse(llvm::StringRef Name) {
return ScaleIter->second;
}
+llvm::Optional<DurationScale> getScaleForTimeInverse(llvm::StringRef Name) {
+ static const llvm::StringMap<DurationScale> ScaleMap(
+ {{"ToUnixHours", DurationScale::Hours},
+ {"ToUnixMinutes", DurationScale::Minutes},
+ {"ToUnixSeconds", DurationScale::Seconds},
+ {"ToUnixMillis", DurationScale::Milliseconds},
+ {"ToUnixMicros", DurationScale::Microseconds},
+ {"ToUnixNanos", DurationScale::Nanoseconds}});
+
+ auto ScaleIter = ScaleMap.find(std::string(Name));
+ if (ScaleIter == ScaleMap.end())
+ return llvm::None;
+
+ return ScaleIter->second;
+}
+
std::string rewriteExprFromNumberToDuration(
const ast_matchers::MatchFinder::MatchResult &Result, DurationScale Scale,
const Expr *Node) {
@@ -211,11 +279,46 @@ std::string rewriteExprFromNumberToDuration(
if (IsLiteralZero(Result, RootNode))
return std::string("absl::ZeroDuration()");
- return (llvm::Twine(getFactoryForScale(Scale)) + "(" +
+ return (llvm::Twine(getDurationFactoryForScale(Scale)) + "(" +
simplifyDurationFactoryArg(Result, RootNode) + ")")
.str();
}
+std::string rewriteExprFromNumberToTime(
+ const ast_matchers::MatchFinder::MatchResult &Result, DurationScale Scale,
+ const Expr *Node) {
+ const Expr &RootNode = *Node->IgnoreParenImpCasts();
+
+ // First check to see if we can undo a complimentary function call.
+ if (llvm::Optional<std::string> MaybeRewrite =
+ rewriteInverseTimeCall(Result, Scale, RootNode))
+ return *MaybeRewrite;
+
+ if (IsLiteralZero(Result, RootNode))
+ return std::string("absl::UnixEpoch()");
+
+ return (llvm::Twine(getTimeFactoryForScale(Scale)) + "(" +
+ tooling::fixit::getText(RootNode, *Result.Context) + ")")
+ .str();
+}
+
+bool isInMacro(const MatchFinder::MatchResult &Result, const Expr *E) {
+ if (!E->getBeginLoc().isMacroID())
+ return false;
+
+ SourceLocation Loc = E->getBeginLoc();
+ // We want to get closer towards the initial macro typed into the source only
+ // if the location is being expanded as a macro argument.
+ while (Result.SourceManager->isMacroArgExpansion(Loc)) {
+ // We are calling getImmediateMacroCallerLoc, but note it is essentially
+ // equivalent to calling getImmediateSpellingLoc in this context according
+ // to Clang implementation. We are not calling getImmediateSpellingLoc
+ // because Clang comment says it "should not generally be used by clients."
+ Loc = Result.SourceManager->getImmediateMacroCallerLoc(Loc);
+ }
+ return Loc.isMacroID();
+}
+
} // namespace abseil
} // namespace tidy
} // namespace clang
diff --git a/clang-tidy/abseil/DurationRewriter.h b/clang-tidy/abseil/DurationRewriter.h
index d0004d1c..1ae312c6 100644
--- a/clang-tidy/abseil/DurationRewriter.h
+++ b/clang-tidy/abseil/DurationRewriter.h
@@ -1,9 +1,8 @@
//===--- DurationRewriter.h - clang-tidy ------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -30,7 +29,11 @@ enum class DurationScale : std::uint8_t {
/// Given a `Scale`, return the appropriate factory function call for
/// constructing a `Duration` for that scale.
-llvm::StringRef getFactoryForScale(DurationScale Scale);
+llvm::StringRef getDurationFactoryForScale(DurationScale Scale);
+
+/// Given a 'Scale', return the appropriate factory function call for
+/// constructing a `Time` for that scale.
+llvm::StringRef getTimeFactoryForScale(DurationScale scale);
// Determine if `Node` represents a literal floating point or integral zero.
bool IsLiteralZero(const ast_matchers::MatchFinder::MatchResult &Result,
@@ -61,13 +64,20 @@ simplifyDurationFactoryArg(const ast_matchers::MatchFinder::MatchResult &Result,
/// Given the name of an inverse Duration function (e.g., `ToDoubleSeconds`),
/// return its `DurationScale`, or `None` if a match is not found.
-llvm::Optional<DurationScale> getScaleForInverse(llvm::StringRef Name);
+llvm::Optional<DurationScale> getScaleForDurationInverse(llvm::StringRef Name);
+
+/// Given the name of an inverse Time function (e.g., `ToUnixSeconds`),
+/// return its `DurationScale`, or `None` if a match is not found.
+llvm::Optional<DurationScale> getScaleForTimeInverse(llvm::StringRef Name);
/// Given a `Scale` return the fully qualified inverse functions for it.
/// The first returned value is the inverse for `double`, and the second
/// returned value is the inverse for `int64`.
const std::pair<llvm::StringRef, llvm::StringRef> &
-getInverseForScale(DurationScale Scale);
+getDurationInverseForScale(DurationScale Scale);
+
+/// Returns the Time inverse function name for a given `Scale`.
+llvm::StringRef getTimeInverseForScale(DurationScale scale);
/// Assuming `Node` has type `double` or `int` representing a time interval of
/// `Scale`, return the expression to make it a suitable `Duration`.
@@ -75,6 +85,17 @@ std::string rewriteExprFromNumberToDuration(
const ast_matchers::MatchFinder::MatchResult &Result, DurationScale Scale,
const Expr *Node);
+/// Assuming `Node` has a type `int` representing a time instant of `Scale`
+/// since The Epoch, return the expression to make it a suitable `Time`.
+std::string rewriteExprFromNumberToTime(
+ const ast_matchers::MatchFinder::MatchResult &Result, DurationScale Scale,
+ const Expr *Node);
+
+/// Return `false` if `E` is a either: not a macro at all; or an argument to
+/// one. In the both cases, we often want to do the transformation.
+bool isInMacro(const ast_matchers::MatchFinder::MatchResult &Result,
+ const Expr *E);
+
AST_MATCHER_FUNCTION(ast_matchers::internal::Matcher<FunctionDecl>,
DurationConversionFunction) {
using namespace clang::ast_matchers;
@@ -95,6 +116,24 @@ AST_MATCHER_FUNCTION(ast_matchers::internal::Matcher<FunctionDecl>,
"::absl::Minutes", "::absl::Hours"));
}
+AST_MATCHER_FUNCTION(ast_matchers::internal::Matcher<FunctionDecl>,
+ TimeConversionFunction) {
+ using namespace clang::ast_matchers;
+ return functionDecl(hasAnyName(
+ "::absl::ToUnixHours", "::absl::ToUnixMinutes", "::absl::ToUnixSeconds",
+ "::absl::ToUnixMillis", "::absl::ToUnixMicros", "::absl::ToUnixNanos"));
+}
+
+AST_MATCHER_FUNCTION_P(ast_matchers::internal::Matcher<Stmt>,
+ comparisonOperatorWithCallee,
+ ast_matchers::internal::Matcher<Decl>, funcDecl) {
+ using namespace clang::ast_matchers;
+ return binaryOperator(
+ anyOf(hasOperatorName(">"), hasOperatorName(">="), hasOperatorName("=="),
+ hasOperatorName("<="), hasOperatorName("<")),
+ hasEitherOperand(ignoringImpCasts(callExpr(callee(funcDecl)))));
+}
+
} // namespace abseil
} // namespace tidy
} // namespace clang
diff --git a/clang-tidy/abseil/DurationSubtractionCheck.cpp b/clang-tidy/abseil/DurationSubtractionCheck.cpp
index db9d407b..32217144 100644
--- a/clang-tidy/abseil/DurationSubtractionCheck.cpp
+++ b/clang-tidy/abseil/DurationSubtractionCheck.cpp
@@ -1,9 +1,8 @@
//===--- DurationSubtractionCheck.cpp - clang-tidy ------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -38,7 +37,8 @@ void DurationSubtractionCheck::check(const MatchFinder::MatchResult &Result) {
if (Binop->getExprLoc().isMacroID() || Binop->getExprLoc().isInvalid())
return;
- llvm::Optional<DurationScale> Scale = getScaleForInverse(FuncDecl->getName());
+ llvm::Optional<DurationScale> Scale =
+ getScaleForDurationInverse(FuncDecl->getName());
if (!Scale)
return;
diff --git a/clang-tidy/abseil/DurationSubtractionCheck.h b/clang-tidy/abseil/DurationSubtractionCheck.h
index 227dcdb5..89deb375 100644
--- a/clang-tidy/abseil/DurationSubtractionCheck.h
+++ b/clang-tidy/abseil/DurationSubtractionCheck.h
@@ -1,9 +1,8 @@
//===--- DurationSubtractionCheck.h - clang-tidy ----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp b/clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp
new file mode 100644
index 00000000..2ba90eec
--- /dev/null
+++ b/clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp
@@ -0,0 +1,82 @@
+//===--- DurationUnnecessaryConversionCheck.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 "DurationUnnecessaryConversionCheck.h"
+#include "DurationRewriter.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+void DurationUnnecessaryConversionCheck::registerMatchers(MatchFinder *Finder) {
+ for (const auto &Scale : {"Hours", "Minutes", "Seconds", "Milliseconds",
+ "Microseconds", "Nanoseconds"}) {
+ std::string DurationFactory = (llvm::Twine("::absl::") + Scale).str();
+ std::string FloatConversion =
+ (llvm::Twine("::absl::ToDouble") + Scale).str();
+ std::string IntegerConversion =
+ (llvm::Twine("::absl::ToInt64") + Scale).str();
+
+ // Matcher which matches the current scale's factory with a `1` argument,
+ // e.g. `absl::Seconds(1)`.
+ auto factory_matcher = cxxConstructExpr(hasArgument(
+ 0,
+ callExpr(callee(functionDecl(hasName(DurationFactory))),
+ hasArgument(0, ignoringImpCasts(integerLiteral(equals(1)))))));
+
+ // Matcher which matches either inverse function and binds its argument,
+ // e.g. `absl::ToDoubleSeconds(dur)`.
+ auto inverse_function_matcher = callExpr(
+ callee(functionDecl(hasAnyName(FloatConversion, IntegerConversion))),
+ hasArgument(0, expr().bind("arg")));
+
+ // Matcher which matches a duration divided by the factory_matcher above,
+ // e.g. `dur / absl::Seconds(1)`.
+ auto division_operator_matcher = cxxOperatorCallExpr(
+ hasOverloadedOperatorName("/"), hasArgument(0, expr().bind("arg")),
+ hasArgument(1, factory_matcher));
+
+ // Matcher which matches a duration argument to `FDivDuration`,
+ // e.g. `absl::FDivDuration(dur, absl::Seconds(1))`
+ auto fdiv_matcher = callExpr(
+ callee(functionDecl(hasName("::absl::FDivDuration"))),
+ hasArgument(0, expr().bind("arg")), hasArgument(1, factory_matcher));
+
+ Finder->addMatcher(
+ callExpr(callee(functionDecl(hasName(DurationFactory))),
+ hasArgument(0, anyOf(inverse_function_matcher,
+ division_operator_matcher, fdiv_matcher)))
+ .bind("call"),
+ this);
+ }
+}
+
+void DurationUnnecessaryConversionCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ const auto *OuterCall = Result.Nodes.getNodeAs<Expr>("call");
+ const auto *Arg = Result.Nodes.getNodeAs<Expr>("arg");
+
+ if (isInMacro(Result, OuterCall))
+ return;
+
+ diag(OuterCall->getBeginLoc(),
+ "remove unnecessary absl::Duration conversions")
+ << FixItHint::CreateReplacement(
+ OuterCall->getSourceRange(),
+ tooling::fixit::getText(*Arg, *Result.Context));
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/abseil/DurationUnnecessaryConversionCheck.h b/clang-tidy/abseil/DurationUnnecessaryConversionCheck.h
new file mode 100644
index 00000000..18061338
--- /dev/null
+++ b/clang-tidy/abseil/DurationUnnecessaryConversionCheck.h
@@ -0,0 +1,35 @@
+//===--- DurationUnnecessaryConversionCheck.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_ABSEIL_TIMEDOUBLECONVERSIONCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMEDOUBLECONVERSIONCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// Finds and fixes cases where ``absl::Duration`` values are being converted
+/// to numeric types and back again.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/abseil-duration-unnecessary-conversion.html
+class DurationUnnecessaryConversionCheck : public ClangTidyCheck {
+public:
+ DurationUnnecessaryConversionCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMEDOUBLECONVERSIONCHECK_H
diff --git a/clang-tidy/abseil/FasterStrsplitDelimiterCheck.cpp b/clang-tidy/abseil/FasterStrsplitDelimiterCheck.cpp
index 35d99ac1..57f822ec 100644
--- a/clang-tidy/abseil/FasterStrsplitDelimiterCheck.cpp
+++ b/clang-tidy/abseil/FasterStrsplitDelimiterCheck.cpp
@@ -1,9 +1,8 @@
//===--- FasterStrsplitDelimiterCheck.cpp - clang-tidy---------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/FasterStrsplitDelimiterCheck.h b/clang-tidy/abseil/FasterStrsplitDelimiterCheck.h
index 17e231cb..7dc77e7d 100644
--- a/clang-tidy/abseil/FasterStrsplitDelimiterCheck.h
+++ b/clang-tidy/abseil/FasterStrsplitDelimiterCheck.h
@@ -1,9 +1,8 @@
//===--- FasterStrsplitDelimiterCheck.h - clang-tidy-------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/NoInternalDependenciesCheck.cpp b/clang-tidy/abseil/NoInternalDependenciesCheck.cpp
index cb77e95f..dcb8585d 100644
--- a/clang-tidy/abseil/NoInternalDependenciesCheck.cpp
+++ b/clang-tidy/abseil/NoInternalDependenciesCheck.cpp
@@ -1,9 +1,8 @@
//===--- NoInternalDependenciesCheck.cpp - clang-tidy----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/NoInternalDependenciesCheck.h b/clang-tidy/abseil/NoInternalDependenciesCheck.h
index 7e659df5..301c89d6 100644
--- a/clang-tidy/abseil/NoInternalDependenciesCheck.h
+++ b/clang-tidy/abseil/NoInternalDependenciesCheck.h
@@ -1,9 +1,8 @@
//===--- NoInternalDependenciesCheck.h - clang-tidy----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/NoNamespaceCheck.cpp b/clang-tidy/abseil/NoNamespaceCheck.cpp
index fc9e6980..5db50de0 100644
--- a/clang-tidy/abseil/NoNamespaceCheck.cpp
+++ b/clang-tidy/abseil/NoNamespaceCheck.cpp
@@ -1,9 +1,8 @@
//===--- NoNamespaceCheck.cpp - clang-tidy---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/NoNamespaceCheck.h b/clang-tidy/abseil/NoNamespaceCheck.h
index 00686d16..058d1101 100644
--- a/clang-tidy/abseil/NoNamespaceCheck.h
+++ b/clang-tidy/abseil/NoNamespaceCheck.h
@@ -1,9 +1,8 @@
//===--- NoNamespaceCheck.h - clang-tidy-------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp b/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp
index 19806685..f8e6e7a5 100644
--- a/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp
+++ b/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp
@@ -1,9 +1,8 @@
//===--- RedundantStrcatCallsCheck.cpp - clang-tidy------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/RedundantStrcatCallsCheck.h b/clang-tidy/abseil/RedundantStrcatCallsCheck.h
index ede03547..71f3ff64 100644
--- a/clang-tidy/abseil/RedundantStrcatCallsCheck.h
+++ b/clang-tidy/abseil/RedundantStrcatCallsCheck.h
@@ -1,9 +1,8 @@
//===--- RedundantStrcatCallsCheck.h - clang-tidy----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/StrCatAppendCheck.cpp b/clang-tidy/abseil/StrCatAppendCheck.cpp
index 49072371..a249b121 100644
--- a/clang-tidy/abseil/StrCatAppendCheck.cpp
+++ b/clang-tidy/abseil/StrCatAppendCheck.cpp
@@ -1,9 +1,8 @@
//===--- StrCatAppendCheck.cpp - clang-tidy--------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/StrCatAppendCheck.h b/clang-tidy/abseil/StrCatAppendCheck.h
index eaa750da..72203fdd 100644
--- a/clang-tidy/abseil/StrCatAppendCheck.h
+++ b/clang-tidy/abseil/StrCatAppendCheck.h
@@ -1,9 +1,8 @@
//===--- StrCatAppendCheck.h - clang-tidy------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/StringFindStartswithCheck.cpp b/clang-tidy/abseil/StringFindStartswithCheck.cpp
index 2701c24b..3fd9fd47 100644
--- a/clang-tidy/abseil/StringFindStartswithCheck.cpp
+++ b/clang-tidy/abseil/StringFindStartswithCheck.cpp
@@ -1,9 +1,8 @@
//===--- StringFindStartswithCheck.cc - clang-tidy---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -115,11 +114,10 @@ void StringFindStartswithCheck::check(const MatchFinder::MatchResult &Result) {
}
void StringFindStartswithCheck::registerPPCallbacks(
- CompilerInstance &Compiler) {
- IncludeInserter = llvm::make_unique<clang::tidy::utils::IncludeInserter>(
- Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle);
- Compiler.getPreprocessor().addPPCallbacks(
- IncludeInserter->CreatePPCallbacks());
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ IncludeInserter = llvm::make_unique<utils::IncludeInserter>(SM, getLangOpts(),
+ IncludeStyle);
+ PP->addPPCallbacks(IncludeInserter->CreatePPCallbacks());
}
void StringFindStartswithCheck::storeOptions(
diff --git a/clang-tidy/abseil/StringFindStartswithCheck.h b/clang-tidy/abseil/StringFindStartswithCheck.h
index 1c04e805..8a702f73 100644
--- a/clang-tidy/abseil/StringFindStartswithCheck.h
+++ b/clang-tidy/abseil/StringFindStartswithCheck.h
@@ -1,9 +1,8 @@
//===--- StringFindStartswithCheck.h - clang-tidy----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -29,7 +28,8 @@ class StringFindStartswithCheck : public ClangTidyCheck {
public:
using ClangTidyCheck::ClangTidyCheck;
StringFindStartswithCheck(StringRef Name, ClangTidyContext *Context);
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
diff --git a/clang-tidy/abseil/TimeComparisonCheck.cpp b/clang-tidy/abseil/TimeComparisonCheck.cpp
new file mode 100644
index 00000000..391f38f1
--- /dev/null
+++ b/clang-tidy/abseil/TimeComparisonCheck.cpp
@@ -0,0 +1,61 @@
+//===--- TimeComparisonCheck.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 "TimeComparisonCheck.h"
+#include "DurationRewriter.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+void TimeComparisonCheck::registerMatchers(MatchFinder *Finder) {
+ auto Matcher =
+ expr(comparisonOperatorWithCallee(functionDecl(
+ functionDecl(TimeConversionFunction()).bind("function_decl"))))
+ .bind("binop");
+
+ Finder->addMatcher(Matcher, this);
+}
+
+void TimeComparisonCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *Binop = Result.Nodes.getNodeAs<BinaryOperator>("binop");
+
+ llvm::Optional<DurationScale> Scale = getScaleForTimeInverse(
+ Result.Nodes.getNodeAs<FunctionDecl>("function_decl")->getName());
+ if (!Scale)
+ return;
+
+ if (isInMacro(Result, Binop->getLHS()) || isInMacro(Result, Binop->getRHS()))
+ return;
+
+ // In most cases, we'll only need to rewrite one of the sides, but we also
+ // want to handle the case of rewriting both sides. This is much simpler if
+ // we unconditionally try and rewrite both, and let the rewriter determine
+ // if nothing needs to be done.
+ std::string LhsReplacement =
+ rewriteExprFromNumberToTime(Result, *Scale, Binop->getLHS());
+ std::string RhsReplacement =
+ rewriteExprFromNumberToTime(Result, *Scale, Binop->getRHS());
+
+ diag(Binop->getBeginLoc(), "perform comparison in the time domain")
+ << FixItHint::CreateReplacement(Binop->getSourceRange(),
+ (llvm::Twine(LhsReplacement) + " " +
+ Binop->getOpcodeStr() + " " +
+ RhsReplacement)
+ .str());
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/abseil/TimeComparisonCheck.h b/clang-tidy/abseil/TimeComparisonCheck.h
new file mode 100644
index 00000000..55984338
--- /dev/null
+++ b/clang-tidy/abseil/TimeComparisonCheck.h
@@ -0,0 +1,35 @@
+//===--- TimeComparisonCheck.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_ABSEIL_TIMECOMPARECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMECOMPARECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// Prefer comparison in the `absl::Time` domain instead of the numeric
+/// domain.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/abseil-time-comparison.html
+class TimeComparisonCheck : public ClangTidyCheck {
+public:
+ TimeComparisonCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMECOMPARECHECK_H
diff --git a/clang-tidy/abseil/TimeSubtractionCheck.cpp b/clang-tidy/abseil/TimeSubtractionCheck.cpp
new file mode 100644
index 00000000..0a7c4016
--- /dev/null
+++ b/clang-tidy/abseil/TimeSubtractionCheck.cpp
@@ -0,0 +1,181 @@
+//===--- TimeSubtractionCheck.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 "TimeSubtractionCheck.h"
+#include "DurationRewriter.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+// Returns `true` if `Range` is inside a macro definition.
+static bool InsideMacroDefinition(const MatchFinder::MatchResult &Result,
+ SourceRange Range) {
+ return !clang::Lexer::makeFileCharRange(
+ clang::CharSourceRange::getCharRange(Range),
+ *Result.SourceManager, Result.Context->getLangOpts())
+ .isValid();
+}
+
+static bool isConstructorAssignment(const MatchFinder::MatchResult &Result,
+ const Expr *Node) {
+ return selectFirst<const Expr>(
+ "e", match(expr(hasParent(materializeTemporaryExpr(hasParent(
+ cxxConstructExpr(hasParent(exprWithCleanups(
+ hasParent(varDecl()))))))))
+ .bind("e"),
+ *Node, *Result.Context)) != nullptr;
+}
+
+static bool isArgument(const MatchFinder::MatchResult &Result,
+ const Expr *Node) {
+ return selectFirst<const Expr>(
+ "e",
+ match(expr(hasParent(
+ materializeTemporaryExpr(hasParent(cxxConstructExpr(
+ hasParent(callExpr()),
+ unless(hasParent(cxxOperatorCallExpr())))))))
+ .bind("e"),
+ *Node, *Result.Context)) != nullptr;
+}
+
+static bool isReturn(const MatchFinder::MatchResult &Result, const Expr *Node) {
+ return selectFirst<const Expr>(
+ "e", match(expr(hasParent(materializeTemporaryExpr(hasParent(
+ cxxConstructExpr(hasParent(exprWithCleanups(
+ hasParent(returnStmt()))))))))
+ .bind("e"),
+ *Node, *Result.Context)) != nullptr;
+}
+
+static bool parensRequired(const MatchFinder::MatchResult &Result,
+ const Expr *Node) {
+ // TODO: Figure out any more contexts in which we can omit the surrounding
+ // parentheses.
+ return !(isConstructorAssignment(Result, Node) || isArgument(Result, Node) ||
+ isReturn(Result, Node));
+}
+
+void TimeSubtractionCheck::emitDiagnostic(const Expr *Node,
+ llvm::StringRef Replacement) {
+ diag(Node->getBeginLoc(), "perform subtraction in the time domain")
+ << FixItHint::CreateReplacement(Node->getSourceRange(), Replacement);
+}
+
+void TimeSubtractionCheck::registerMatchers(MatchFinder *Finder) {
+ for (auto ScaleName :
+ {"Hours", "Minutes", "Seconds", "Millis", "Micros", "Nanos"}) {
+ std::string TimeInverse = (llvm::Twine("ToUnix") + ScaleName).str();
+ llvm::Optional<DurationScale> Scale = getScaleForTimeInverse(TimeInverse);
+ assert(Scale && "Unknow scale encountered");
+
+ auto TimeInverseMatcher = callExpr(callee(
+ functionDecl(hasName((llvm::Twine("::absl::") + TimeInverse).str()))
+ .bind("func_decl")));
+
+ // Match the cases where we know that the result is a 'Duration' and the
+ // first argument is a 'Time'. Just knowing the type of the first operand
+ // is not sufficient, since the second operand could be either a 'Time' or
+ // a 'Duration'. If we know the result is a 'Duration', we can then infer
+ // that the second operand must be a 'Time'.
+ auto CallMatcher =
+ callExpr(
+ callee(functionDecl(hasName(getDurationFactoryForScale(*Scale)))),
+ hasArgument(0, binaryOperator(hasOperatorName("-"),
+ hasLHS(TimeInverseMatcher))
+ .bind("binop")))
+ .bind("outer_call");
+ Finder->addMatcher(CallMatcher, this);
+
+ // Match cases where we know the second operand is a 'Time'. Since
+ // subtracting a 'Time' from a 'Duration' is not defined, in these cases,
+ // we always know the first operand is a 'Time' if the second is a 'Time'.
+ auto OperandMatcher =
+ binaryOperator(hasOperatorName("-"), hasRHS(TimeInverseMatcher))
+ .bind("binop");
+ Finder->addMatcher(OperandMatcher, this);
+ }
+}
+
+void TimeSubtractionCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("binop");
+ std::string InverseName =
+ Result.Nodes.getNodeAs<FunctionDecl>("func_decl")->getNameAsString();
+ if (InsideMacroDefinition(Result, BinOp->getSourceRange()))
+ return;
+
+ llvm::Optional<DurationScale> Scale = getScaleForTimeInverse(InverseName);
+ if (!Scale)
+ return;
+
+ const auto *OuterCall = Result.Nodes.getNodeAs<CallExpr>("outer_call");
+ if (OuterCall) {
+ if (InsideMacroDefinition(Result, OuterCall->getSourceRange()))
+ return;
+
+ // We're working with the first case of matcher, and need to replace the
+ // entire 'Duration' factory call. (Which also means being careful about
+ // our order-of-operations and optionally putting in some parenthesis.
+ bool NeedParens = parensRequired(Result, OuterCall);
+
+ emitDiagnostic(
+ OuterCall,
+ (llvm::Twine(NeedParens ? "(" : "") +
+ rewriteExprFromNumberToTime(Result, *Scale, BinOp->getLHS()) + " - " +
+ rewriteExprFromNumberToTime(Result, *Scale, BinOp->getRHS()) +
+ (NeedParens ? ")" : ""))
+ .str());
+ } else {
+ // We're working with the second case of matcher, and either just need to
+ // change the arguments, or perhaps remove an outer function call. In the
+ // latter case (addressed first), we also need to worry about parenthesis.
+ const auto *MaybeCallArg = selectFirst<const CallExpr>(
+ "arg", match(expr(hasAncestor(
+ callExpr(callee(functionDecl(hasName(
+ getDurationFactoryForScale(*Scale)))))
+ .bind("arg"))),
+ *BinOp, *Result.Context));
+ if (MaybeCallArg && MaybeCallArg->getArg(0)->IgnoreImpCasts() == BinOp &&
+ !InsideMacroDefinition(Result, MaybeCallArg->getSourceRange())) {
+ // Handle the case where the matched expression is inside a call which
+ // converts it from the inverse to a Duration. In this case, we replace
+ // the outer with just the subtraction expresison, which gives the right
+ // type and scale, taking care again about parenthesis.
+ bool NeedParens = parensRequired(Result, MaybeCallArg);
+
+ emitDiagnostic(
+ MaybeCallArg,
+ (llvm::Twine(NeedParens ? "(" : "") +
+ rewriteExprFromNumberToTime(Result, *Scale, BinOp->getLHS()) +
+ " - " +
+ rewriteExprFromNumberToTime(Result, *Scale, BinOp->getRHS()) +
+ (NeedParens ? ")" : ""))
+ .str());
+ } else {
+ // In the last case, just convert the arguments and wrap the result in
+ // the correct inverse function.
+ emitDiagnostic(
+ BinOp,
+ (llvm::Twine(
+ getDurationInverseForScale(*Scale).second.str().substr(2)) +
+ "(" + rewriteExprFromNumberToTime(Result, *Scale, BinOp->getLHS()) +
+ " - " +
+ rewriteExprFromNumberToTime(Result, *Scale, BinOp->getRHS()) + ")")
+ .str());
+ }
+ }
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/abseil/TimeSubtractionCheck.h b/clang-tidy/abseil/TimeSubtractionCheck.h
new file mode 100644
index 00000000..4e3cd3b5
--- /dev/null
+++ b/clang-tidy/abseil/TimeSubtractionCheck.h
@@ -0,0 +1,38 @@
+//===--- TimeSubtractionCheck.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_ABSEIL_TIMESUBTRACTIONCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMESUBTRACTIONCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// Finds and fixes `absl::Time` subtraction expressions to do subtraction
+/// in the time domain instead of the numeric domain.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/abseil-time-subtraction.html
+class TimeSubtractionCheck : public ClangTidyCheck {
+public:
+ TimeSubtractionCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ void emitDiagnostic(const Expr* Node, llvm::StringRef Replacement);
+};
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMESUBTRACTIONCHECK_H
diff --git a/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp b/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp
index 1925f48c..9c709d25 100644
--- a/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp
+++ b/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp
@@ -1,9 +1,8 @@
//===--- UpgradeDurationConversionsCheck.cpp - clang-tidy -----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/UpgradeDurationConversionsCheck.h b/clang-tidy/abseil/UpgradeDurationConversionsCheck.h
index 63712e2c..b1096a67 100644
--- a/clang-tidy/abseil/UpgradeDurationConversionsCheck.h
+++ b/clang-tidy/abseil/UpgradeDurationConversionsCheck.h
@@ -1,9 +1,8 @@
//===--- UpgradeDurationConversionsCheck.h - clang-tidy ---------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/add_new_check.py b/clang-tidy/add_new_check.py
index f4c518d0..8f96cbd8 100755
--- a/clang-tidy/add_new_check.py
+++ b/clang-tidy/add_new_check.py
@@ -2,10 +2,9 @@
#
#===- add_new_check.py - clang-tidy check generator ----------*- python -*--===#
#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
+# 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
#
#===------------------------------------------------------------------------===#
@@ -61,17 +60,16 @@ def write_header(module_path, module, check_name, check_name_camel):
f.write('*- C++ -*-===//')
f.write("""
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 %(header_guard)s
#define %(header_guard)s
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
@@ -112,10 +110,9 @@ def write_implementation(module_path, module, check_name_camel):
f.write('-===//')
f.write("""
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -140,7 +137,8 @@ void %(check_name)s::check(const MatchFinder::MatchResult &Result) {
if (MatchedDecl->getName().startswith("awesome_"))
return;
diag(MatchedDecl->getLocation(), "function %%0 is insufficiently awesome")
- << MatchedDecl
+ << MatchedDecl;
+ diag(MatchedDecl->getLocation(), "insert 'awesome'", DiagnosticIDs::Note)
<< FixItHint::CreateInsertion(MatchedDecl->getLocation(), "awesome_");
}
@@ -201,7 +199,7 @@ def add_release_notes(module_path, module, check_name):
lines = f.readlines()
lineMatcher = re.compile('Improvements to clang-tidy')
- nextSectionMatcher = re.compile('Improvements to include-fixer')
+ nextSectionMatcher = re.compile('Improvements to clang-include-fixer')
checkerMatcher = re.compile('- New :doc:`(.*)')
print('Updating %s...' % filename)
diff --git a/clang-tidy/android/AndroidTidyModule.cpp b/clang-tidy/android/AndroidTidyModule.cpp
index bbb4b715..2baa3fba 100644
--- a/clang-tidy/android/AndroidTidyModule.cpp
+++ b/clang-tidy/android/AndroidTidyModule.cpp
@@ -1,9 +1,8 @@
//===--- AndroidTidyModule.cpp - clang-tidy--------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecAccept4Check.cpp b/clang-tidy/android/CloexecAccept4Check.cpp
index 3d172ef3..fe1f341f 100644
--- a/clang-tidy/android/CloexecAccept4Check.cpp
+++ b/clang-tidy/android/CloexecAccept4Check.cpp
@@ -1,9 +1,8 @@
//===--- CloexecAccept4Check.cpp - clang-tidy------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecAccept4Check.h b/clang-tidy/android/CloexecAccept4Check.h
index 0cf32152..21196de3 100644
--- a/clang-tidy/android/CloexecAccept4Check.h
+++ b/clang-tidy/android/CloexecAccept4Check.h
@@ -1,9 +1,8 @@
//===--- CloexecAccept4Check.h - clang-tidy----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecAcceptCheck.cpp b/clang-tidy/android/CloexecAcceptCheck.cpp
index f583bd0c..b26ad75d 100644
--- a/clang-tidy/android/CloexecAcceptCheck.cpp
+++ b/clang-tidy/android/CloexecAcceptCheck.cpp
@@ -1,9 +1,8 @@
//===--- CloexecAcceptCheck.cpp - clang-tidy-------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecAcceptCheck.h b/clang-tidy/android/CloexecAcceptCheck.h
index cba1c098..304ac51f 100644
--- a/clang-tidy/android/CloexecAcceptCheck.h
+++ b/clang-tidy/android/CloexecAcceptCheck.h
@@ -1,9 +1,8 @@
//===--- CloexecAcceptCheck.h - clang-tidy-----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecCheck.cpp b/clang-tidy/android/CloexecCheck.cpp
index 4cc0f614..148839a6 100644
--- a/clang-tidy/android/CloexecCheck.cpp
+++ b/clang-tidy/android/CloexecCheck.cpp
@@ -1,9 +1,8 @@
//===--- CloexecCheck.cpp - clang-tidy-------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecCheck.h b/clang-tidy/android/CloexecCheck.h
index 1c58a313..92cdf780 100644
--- a/clang-tidy/android/CloexecCheck.h
+++ b/clang-tidy/android/CloexecCheck.h
@@ -1,9 +1,8 @@
//===--- CloexecCheck.h - clang-tidy-----------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
@@ -16,7 +15,7 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/android/CloexecCreatCheck.cpp b/clang-tidy/android/CloexecCreatCheck.cpp
index 83ca49a3..f096884d 100644
--- a/clang-tidy/android/CloexecCreatCheck.cpp
+++ b/clang-tidy/android/CloexecCreatCheck.cpp
@@ -1,9 +1,8 @@
//===--- CloexecCreatCheck.cpp - clang-tidy--------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecCreatCheck.h b/clang-tidy/android/CloexecCreatCheck.h
index 335990cc..cb60e258 100644
--- a/clang-tidy/android/CloexecCreatCheck.h
+++ b/clang-tidy/android/CloexecCreatCheck.h
@@ -1,9 +1,8 @@
//===--- CloexecCreatCheck.h - clang-tidy------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecDupCheck.cpp b/clang-tidy/android/CloexecDupCheck.cpp
index ec4ff0ac..9a676d14 100644
--- a/clang-tidy/android/CloexecDupCheck.cpp
+++ b/clang-tidy/android/CloexecDupCheck.cpp
@@ -1,9 +1,8 @@
//===--- CloexecDupCheck.cpp - clang-tidy----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecDupCheck.h b/clang-tidy/android/CloexecDupCheck.h
index c040b380..e87c0abb 100644
--- a/clang-tidy/android/CloexecDupCheck.h
+++ b/clang-tidy/android/CloexecDupCheck.h
@@ -1,9 +1,8 @@
//===--- CloexecDupCheck.h - clang-tidy-------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecEpollCreate1Check.cpp b/clang-tidy/android/CloexecEpollCreate1Check.cpp
index d94b4a06..8fb175ee 100644
--- a/clang-tidy/android/CloexecEpollCreate1Check.cpp
+++ b/clang-tidy/android/CloexecEpollCreate1Check.cpp
@@ -1,9 +1,8 @@
//===--- CloexecEpollCreate1Check.cpp - clang-tidy-------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecEpollCreate1Check.h b/clang-tidy/android/CloexecEpollCreate1Check.h
index 9890d5f0..cac2581b 100644
--- a/clang-tidy/android/CloexecEpollCreate1Check.h
+++ b/clang-tidy/android/CloexecEpollCreate1Check.h
@@ -1,9 +1,8 @@
//===--- CloexecEpollCreate1Check.h - clang-tidy-----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecEpollCreateCheck.cpp b/clang-tidy/android/CloexecEpollCreateCheck.cpp
index 7165d24f..f1d7edfd 100644
--- a/clang-tidy/android/CloexecEpollCreateCheck.cpp
+++ b/clang-tidy/android/CloexecEpollCreateCheck.cpp
@@ -1,9 +1,8 @@
//===--- CloexecEpollCreateCheck.cpp - clang-tidy--------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecEpollCreateCheck.h b/clang-tidy/android/CloexecEpollCreateCheck.h
index 21d2b2ab..8db80c84 100644
--- a/clang-tidy/android/CloexecEpollCreateCheck.h
+++ b/clang-tidy/android/CloexecEpollCreateCheck.h
@@ -1,9 +1,8 @@
//===--- CloexecEpollCreateCheck.h - clang-tidy------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecFopenCheck.cpp b/clang-tidy/android/CloexecFopenCheck.cpp
index 33058d6e..dc9908b6 100644
--- a/clang-tidy/android/CloexecFopenCheck.cpp
+++ b/clang-tidy/android/CloexecFopenCheck.cpp
@@ -1,9 +1,9 @@
//===--- CloexecFopenCheck.cpp - clang-tidy--------------------------------===//
//
-// The LLVM Compiler Infrastructure
+// 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
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details. //
//===----------------------------------------------------------------------===//
#include "CloexecFopenCheck.h"
diff --git a/clang-tidy/android/CloexecFopenCheck.h b/clang-tidy/android/CloexecFopenCheck.h
index 1c82b8bd..0b617ffd 100644
--- a/clang-tidy/android/CloexecFopenCheck.h
+++ b/clang-tidy/android/CloexecFopenCheck.h
@@ -1,9 +1,8 @@
//===--- CloexecFopenCheck.h - clang-tidy------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source //
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecInotifyInit1Check.cpp b/clang-tidy/android/CloexecInotifyInit1Check.cpp
index ca0aeb87..f0a0b982 100644
--- a/clang-tidy/android/CloexecInotifyInit1Check.cpp
+++ b/clang-tidy/android/CloexecInotifyInit1Check.cpp
@@ -1,9 +1,8 @@
//===--- CloexecInotifyInit1Check.cpp - clang-tidy-------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecInotifyInit1Check.h b/clang-tidy/android/CloexecInotifyInit1Check.h
index deb04f2a..d4a392d3 100644
--- a/clang-tidy/android/CloexecInotifyInit1Check.h
+++ b/clang-tidy/android/CloexecInotifyInit1Check.h
@@ -1,9 +1,8 @@
//===--- CloexecInotifyInit1Check.h - clang-tidy-----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecInotifyInitCheck.cpp b/clang-tidy/android/CloexecInotifyInitCheck.cpp
index 0d5a56da..e11cbb8b 100644
--- a/clang-tidy/android/CloexecInotifyInitCheck.cpp
+++ b/clang-tidy/android/CloexecInotifyInitCheck.cpp
@@ -1,9 +1,8 @@
//===--- CloexecInotifyInitCheck.cpp - clang-tidy--------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecInotifyInitCheck.h b/clang-tidy/android/CloexecInotifyInitCheck.h
index ceeecbea..3b6e0574 100644
--- a/clang-tidy/android/CloexecInotifyInitCheck.h
+++ b/clang-tidy/android/CloexecInotifyInitCheck.h
@@ -1,9 +1,8 @@
//===--- CloexecInotifyInitCheck.h - clang-tidy------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecMemfdCreateCheck.cpp b/clang-tidy/android/CloexecMemfdCreateCheck.cpp
index 4820e2bd..6fa606b8 100644
--- a/clang-tidy/android/CloexecMemfdCreateCheck.cpp
+++ b/clang-tidy/android/CloexecMemfdCreateCheck.cpp
@@ -1,9 +1,8 @@
//===--- CloexecMemfdCreateCheck.cpp - clang-tidy--------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecMemfdCreateCheck.h b/clang-tidy/android/CloexecMemfdCreateCheck.h
index 0fe96f46..f429ee5f 100644
--- a/clang-tidy/android/CloexecMemfdCreateCheck.h
+++ b/clang-tidy/android/CloexecMemfdCreateCheck.h
@@ -1,9 +1,8 @@
//===--- CloexecMemfdCreateCheck.h - clang-tidy-----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecOpenCheck.cpp b/clang-tidy/android/CloexecOpenCheck.cpp
index a4d3bc68..d0617a33 100644
--- a/clang-tidy/android/CloexecOpenCheck.cpp
+++ b/clang-tidy/android/CloexecOpenCheck.cpp
@@ -1,9 +1,8 @@
//===--- CloexecOpenCheck.cpp - clang-tidy---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecOpenCheck.h b/clang-tidy/android/CloexecOpenCheck.h
index c221087f..eb3319c7 100644
--- a/clang-tidy/android/CloexecOpenCheck.h
+++ b/clang-tidy/android/CloexecOpenCheck.h
@@ -1,9 +1,8 @@
//===--- CloexecOpenCheck.h - clang-tidy-----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecSocketCheck.cpp b/clang-tidy/android/CloexecSocketCheck.cpp
index b223918f..dd0f6244 100644
--- a/clang-tidy/android/CloexecSocketCheck.cpp
+++ b/clang-tidy/android/CloexecSocketCheck.cpp
@@ -1,9 +1,8 @@
//===--- CloexecSocketCheck.cpp - clang-tidy-------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/CloexecSocketCheck.h b/clang-tidy/android/CloexecSocketCheck.h
index c1fd01f1..acbfceab 100644
--- a/clang-tidy/android/CloexecSocketCheck.h
+++ b/clang-tidy/android/CloexecSocketCheck.h
@@ -1,9 +1,8 @@
//===--- CloexecSocketCheck.h - clang-tidy-----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/ComparisonInTempFailureRetryCheck.cpp b/clang-tidy/android/ComparisonInTempFailureRetryCheck.cpp
index a98eb8ca..f43d9496 100644
--- a/clang-tidy/android/ComparisonInTempFailureRetryCheck.cpp
+++ b/clang-tidy/android/ComparisonInTempFailureRetryCheck.cpp
@@ -1,9 +1,8 @@
//===--- ComparisonInTempFailureRetryCheck.cpp - clang-tidy----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/android/ComparisonInTempFailureRetryCheck.h b/clang-tidy/android/ComparisonInTempFailureRetryCheck.h
index de812323..d12c9997 100644
--- a/clang-tidy/android/ComparisonInTempFailureRetryCheck.h
+++ b/clang-tidy/android/ComparisonInTempFailureRetryCheck.h
@@ -1,16 +1,15 @@
//===--- ComparisonInTempFailureRetryCheck.h - clang-tidy--------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_ANDROID_COMPARISONINTEMPFAILURERETRYCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_COMPARISONINTEMPFAILURERETRYCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/boost/BoostTidyModule.cpp b/clang-tidy/boost/BoostTidyModule.cpp
index 28eb1d65..4ab22ade 100644
--- a/clang-tidy/boost/BoostTidyModule.cpp
+++ b/clang-tidy/boost/BoostTidyModule.cpp
@@ -1,9 +1,8 @@
//===------- BoostTidyModule.cpp - clang-tidy -----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/boost/UseToStringCheck.cpp b/clang-tidy/boost/UseToStringCheck.cpp
index 259f3dfd..29bedcf5 100644
--- a/clang-tidy/boost/UseToStringCheck.cpp
+++ b/clang-tidy/boost/UseToStringCheck.cpp
@@ -1,9 +1,8 @@
//===--- UseToStringCheck.cpp - clang-tidy---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/boost/UseToStringCheck.h b/clang-tidy/boost/UseToStringCheck.h
index 76e7823b..058a34c7 100644
--- a/clang-tidy/boost/UseToStringCheck.h
+++ b/clang-tidy/boost/UseToStringCheck.h
@@ -1,16 +1,15 @@
//===--- UseToStringCheck.h - clang-tidy-------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_BOOST_USE_TO_STRING_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BOOST_USE_TO_STRING_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/ArgumentCommentCheck.cpp b/clang-tidy/bugprone/ArgumentCommentCheck.cpp
index 62f30f79..5d6c7c9a 100644
--- a/clang-tidy/bugprone/ArgumentCommentCheck.cpp
+++ b/clang-tidy/bugprone/ArgumentCommentCheck.cpp
@@ -1,9 +1,8 @@
//===--- ArgumentCommentCheck.cpp - clang-tidy ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -12,6 +11,7 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Token.h"
+
#include "../utils/LexerUtils.h"
using namespace clang::ast_matchers;
@@ -24,17 +24,37 @@ ArgumentCommentCheck::ArgumentCommentCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
StrictMode(Options.getLocalOrGlobal("StrictMode", 0) != 0),
+ CommentBoolLiterals(Options.getLocalOrGlobal("CommentBoolLiterals", 0) !=
+ 0),
+ CommentIntegerLiterals(
+ Options.getLocalOrGlobal("CommentIntegerLiterals", 0) != 0),
+ CommentFloatLiterals(
+ Options.getLocalOrGlobal("CommentFloatLiterals", 0) != 0),
+ CommentStringLiterals(
+ Options.getLocalOrGlobal("CommentStringLiterals", 0) != 0),
+ CommentUserDefinedLiterals(
+ Options.getLocalOrGlobal("CommentUserDefinedLiterals", 0) != 0),
+ CommentCharacterLiterals(
+ Options.getLocalOrGlobal("CommentCharacterLiterals", 0) != 0),
+ CommentNullPtrs(Options.getLocalOrGlobal("CommentNullPtrs", 0) != 0),
IdentRE("^(/\\* *)([_A-Za-z][_A-Za-z0-9]*)( *= *\\*/)$") {}
void ArgumentCommentCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "StrictMode", StrictMode);
+ Options.store(Opts, "CommentBoolLiterals", CommentBoolLiterals);
+ Options.store(Opts, "CommentIntegerLiterals", CommentIntegerLiterals);
+ Options.store(Opts, "CommentFloatLiterals", CommentFloatLiterals);
+ Options.store(Opts, "CommentStringLiterals", CommentStringLiterals);
+ Options.store(Opts, "CommentUserDefinedLiterals", CommentUserDefinedLiterals);
+ Options.store(Opts, "CommentCharacterLiterals", CommentCharacterLiterals);
+ Options.store(Opts, "CommentNullPtrs", CommentNullPtrs);
}
void ArgumentCommentCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
callExpr(unless(cxxOperatorCallExpr()),
- // NewCallback's arguments relate to the pointed function, don't
- // check them against NewCallback's parameter names.
+ // NewCallback's arguments relate to the pointed function,
+ // don't check them against NewCallback's parameter names.
// FIXME: Make this configurable.
unless(hasDeclaration(functionDecl(
hasAnyName("NewCallback", "NewPermanentCallback")))))
@@ -127,8 +147,8 @@ static bool isLikelyTypo(llvm::ArrayRef<ParmVarDecl *> Params,
const unsigned Threshold = 2;
// Other parameters must be an edit distance at least Threshold more away
- // from this parameter. This gives us greater confidence that this is a typo
- // of this parameter and not one with a similar name.
+ // from this parameter. This gives us greater confidence that this is a
+ // typo of this parameter and not one with a similar name.
unsigned OtherED = ArgNameLower.edit_distance(II->getName().lower(),
/*AllowReplacements=*/true,
ThisED + Threshold);
@@ -181,8 +201,8 @@ static const CXXMethodDecl *findMockedMethod(const CXXMethodDecl *Method) {
}
return nullptr;
}
- if (const auto *Next = dyn_cast_or_null<CXXMethodDecl>(
- Method->getNextDeclInContext())) {
+ if (const auto *Next =
+ dyn_cast_or_null<CXXMethodDecl>(Method->getNextDeclInContext())) {
if (looksLikeExpectMethod(Next) && areMockAndExpectMethods(Method, Next))
return Method;
}
@@ -207,6 +227,21 @@ static const FunctionDecl *resolveMocks(const FunctionDecl *Func) {
return Func;
}
+// Given the argument type and the options determine if we should
+// be adding an argument comment.
+bool ArgumentCommentCheck::shouldAddComment(const Expr *Arg) const {
+ if (Arg->getExprLoc().isMacroID())
+ return false;
+ Arg = Arg->IgnoreImpCasts();
+ return (CommentBoolLiterals && isa<CXXBoolLiteralExpr>(Arg)) ||
+ (CommentIntegerLiterals && isa<IntegerLiteral>(Arg)) ||
+ (CommentFloatLiterals && isa<FloatingLiteral>(Arg)) ||
+ (CommentUserDefinedLiterals && isa<UserDefinedLiteral>(Arg)) ||
+ (CommentCharacterLiterals && isa<CharacterLiteral>(Arg)) ||
+ (CommentStringLiterals && isa<StringLiteral>(Arg)) ||
+ (CommentNullPtrs && isa<CXXNullPtrLiteralExpr>(Arg));
+}
+
void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx,
const FunctionDecl *OriginalCallee,
SourceLocation ArgBeginLoc,
@@ -220,7 +255,7 @@ void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx,
if (NumArgs == 0)
return;
- auto makeFileCharRange = [Ctx](SourceLocation Begin, SourceLocation End) {
+ auto MakeFileCharRange = [Ctx](SourceLocation Begin, SourceLocation End) {
return Lexer::makeFileCharRange(CharSourceRange::getCharRange(Begin, End),
Ctx->getSourceManager(),
Ctx->getLangOpts());
@@ -243,7 +278,7 @@ void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx,
}
CharSourceRange BeforeArgument =
- makeFileCharRange(ArgBeginLoc, Args[I]->getBeginLoc());
+ MakeFileCharRange(ArgBeginLoc, Args[I]->getBeginLoc());
ArgBeginLoc = Args[I]->getEndLoc();
std::vector<std::pair<SourceLocation, StringRef>> Comments;
@@ -251,7 +286,7 @@ void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx,
Comments = getCommentsInRange(Ctx, BeforeArgument);
} else {
// Fall back to parsing back from the start of the argument.
- CharSourceRange ArgsRange = makeFileCharRange(
+ CharSourceRange ArgsRange = MakeFileCharRange(
Args[I]->getBeginLoc(), Args[NumArgs - 1]->getEndLoc());
Comments = getCommentsBeforeLoc(Ctx, ArgsRange.getBegin());
}
@@ -278,8 +313,19 @@ void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx,
}
}
}
+
+ // If the argument comments are missing for literals add them.
+ if (Comments.empty() && shouldAddComment(Args[I])) {
+ std::string ArgComment =
+ (llvm::Twine("/*") + II->getName() + "=*/").str();
+ DiagnosticBuilder Diag =
+ diag(Args[I]->getBeginLoc(),
+ "argument comment missing for literal argument %0")
+ << II
+ << FixItHint::CreateInsertion(Args[I]->getBeginLoc(), ArgComment);
+ }
}
-}
+} // namespace bugprone
void ArgumentCommentCheck::check(const MatchFinder::MatchResult &Result) {
const auto *E = Result.Nodes.getNodeAs<Expr>("expr");
diff --git a/clang-tidy/bugprone/ArgumentCommentCheck.h b/clang-tidy/bugprone/ArgumentCommentCheck.h
index 2f5a751b..216d92c5 100644
--- a/clang-tidy/bugprone/ArgumentCommentCheck.h
+++ b/clang-tidy/bugprone/ArgumentCommentCheck.h
@@ -1,16 +1,15 @@
//===--- ArgumentCommentCheck.h - clang-tidy --------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_ARGUMENTCOMMENTCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ARGUMENTCOMMENTCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "llvm/Support/Regex.h"
namespace clang {
@@ -27,7 +26,8 @@ namespace bugprone {
///
/// ...
/// f(/*bar=*/true);
-/// // warning: argument name 'bar' in comment does not match parameter name 'foo'
+/// // warning: argument name 'bar' in comment does not match parameter name
+/// 'foo'
/// \endcode
///
/// The check tries to detect typos and suggest automated fixes for them.
@@ -40,12 +40,21 @@ public:
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
private:
- const bool StrictMode;
+ const unsigned StrictMode : 1;
+ const unsigned CommentBoolLiterals : 1;
+ const unsigned CommentIntegerLiterals : 1;
+ const unsigned CommentFloatLiterals : 1;
+ const unsigned CommentStringLiterals : 1;
+ const unsigned CommentUserDefinedLiterals : 1;
+ const unsigned CommentCharacterLiterals : 1;
+ const unsigned CommentNullPtrs : 1;
llvm::Regex IdentRE;
void checkCallArgs(ASTContext *Ctx, const FunctionDecl *Callee,
SourceLocation ArgBeginLoc,
llvm::ArrayRef<const Expr *> Args);
+
+ bool shouldAddComment(const Expr *Arg) const;
};
} // namespace bugprone
diff --git a/clang-tidy/bugprone/AssertSideEffectCheck.cpp b/clang-tidy/bugprone/AssertSideEffectCheck.cpp
index c747980b..a28ef113 100644
--- a/clang-tidy/bugprone/AssertSideEffectCheck.cpp
+++ b/clang-tidy/bugprone/AssertSideEffectCheck.cpp
@@ -1,9 +1,8 @@
//===--- AssertSideEffectCheck.cpp - clang-tidy ---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/AssertSideEffectCheck.h b/clang-tidy/bugprone/AssertSideEffectCheck.h
index 0f386c9d..15d1a69c 100644
--- a/clang-tidy/bugprone/AssertSideEffectCheck.h
+++ b/clang-tidy/bugprone/AssertSideEffectCheck.h
@@ -1,16 +1,15 @@
//===--- AssertSideEffectCheck.h - clang-tidy -------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_ASSERTSIDEEFFECTCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ASSERTSIDEEFFECTCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include <string>
diff --git a/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp b/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp
index 675322dd..b7f5b0d6 100644
--- a/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp
+++ b/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp
@@ -1,9 +1,8 @@
//===--- BoolPointerImplicitConversionCheck.cpp - clang-tidy --------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.h b/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.h
index b3416a92..2eed4711 100644
--- a/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.h
+++ b/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.h
@@ -1,16 +1,15 @@
//===--- BoolPointerImplicitConversionCheck.h - clang-tidy ------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_BOOLPOINTERIMPLICITCONVERSIONCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BOOLPOINTERIMPLICITCONVERSIONCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tidy/bugprone/BugproneTidyModule.cpp
index beb58f5d..01bc0e54 100644
--- a/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -1,9 +1,8 @@
//===--- BugproneTidyModule.cpp - clang-tidy ------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/CopyConstructorInitCheck.cpp b/clang-tidy/bugprone/CopyConstructorInitCheck.cpp
index f0488254..5ae7999c 100644
--- a/clang-tidy/bugprone/CopyConstructorInitCheck.cpp
+++ b/clang-tidy/bugprone/CopyConstructorInitCheck.cpp
@@ -1,9 +1,8 @@
//===--- CopyConstructorInitCheck.cpp - clang-tidy-------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/CopyConstructorInitCheck.h b/clang-tidy/bugprone/CopyConstructorInitCheck.h
index 4d13da4a..648aa423 100644
--- a/clang-tidy/bugprone/CopyConstructorInitCheck.h
+++ b/clang-tidy/bugprone/CopyConstructorInitCheck.h
@@ -1,16 +1,15 @@
//===--- CopyConstructorInitCheck.h - clang-tidy--------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_COPY_CONSTRUCTOR_INIT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_COPY_CONSTRUCTOR_INIT_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/DanglingHandleCheck.cpp b/clang-tidy/bugprone/DanglingHandleCheck.cpp
index 81b799ed..74ad2e75 100644
--- a/clang-tidy/bugprone/DanglingHandleCheck.cpp
+++ b/clang-tidy/bugprone/DanglingHandleCheck.cpp
@@ -1,9 +1,8 @@
//===--- DanglingHandleCheck.cpp - clang-tidy------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -164,9 +163,8 @@ void DanglingHandleCheck::registerMatchersForReturn(MatchFinder *Finder) {
// Return a temporary.
Finder->addMatcher(
- returnStmt(
- has(ignoringParenImpCasts(exprWithCleanups(has(ignoringParenImpCasts(
- handleFrom(IsAHandle, handleFromTemporaryValue(IsAHandle))))))))
+ returnStmt(has(exprWithCleanups(has(ignoringParenImpCasts(handleFrom(
+ IsAHandle, handleFromTemporaryValue(IsAHandle)))))))
.bind("bad_stmt"),
this);
}
diff --git a/clang-tidy/bugprone/DanglingHandleCheck.h b/clang-tidy/bugprone/DanglingHandleCheck.h
index add8d427..650522d9 100644
--- a/clang-tidy/bugprone/DanglingHandleCheck.h
+++ b/clang-tidy/bugprone/DanglingHandleCheck.h
@@ -1,16 +1,15 @@
//===--- DanglingHandleCheck.h - clang-tidy----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_DANGLING_HANDLE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DANGLING_HANDLE_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/ExceptionEscapeCheck.cpp b/clang-tidy/bugprone/ExceptionEscapeCheck.cpp
index 3c8a6c5d..951c6f1e 100644
--- a/clang-tidy/bugprone/ExceptionEscapeCheck.cpp
+++ b/clang-tidy/bugprone/ExceptionEscapeCheck.cpp
@@ -1,9 +1,8 @@
-//===--- ExceptionEscapeCheck.cpp - clang-tidy-----------------------------===//
+//===--- ExceptionEscapeCheck.cpp - clang-tidy ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -11,158 +10,21 @@
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
-
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringSet.h"
using namespace clang::ast_matchers;
-namespace {
-typedef llvm::SmallVector<const clang::Type *, 8> TypeVec;
-} // namespace
-
namespace clang {
-
-static bool isBaseOf(const Type *DerivedType, const Type *BaseType) {
- const auto *DerivedClass = DerivedType->getAsCXXRecordDecl();
- const auto *BaseClass = BaseType->getAsCXXRecordDecl();
- if (!DerivedClass || !BaseClass)
- return false;
-
- return !DerivedClass->forallBases(
- [BaseClass](const CXXRecordDecl *Cur) { return Cur != BaseClass; });
-}
-
-static const TypeVec
-throwsException(const Stmt *St, const TypeVec &Caught,
- llvm::SmallSet<const FunctionDecl *, 32> &CallStack);
-
-static const TypeVec
-throwsException(const FunctionDecl *Func,
- llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
- if (CallStack.count(Func))
- return TypeVec();
-
- if (const Stmt *Body = Func->getBody()) {
- CallStack.insert(Func);
- const TypeVec Result = throwsException(Body, TypeVec(), CallStack);
- CallStack.erase(Func);
- return Result;
- }
-
- TypeVec Result;
- if (const auto *FPT = Func->getType()->getAs<FunctionProtoType>()) {
- for (const QualType Ex : FPT->exceptions()) {
- Result.push_back(Ex.getTypePtr());
- }
- }
- return Result;
-}
-
-static const TypeVec
-throwsException(const Stmt *St, const TypeVec &Caught,
- llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
- TypeVec Results;
-
- if (!St)
- return Results;
-
- if (const auto *Throw = dyn_cast<CXXThrowExpr>(St)) {
- if (const auto *ThrownExpr = Throw->getSubExpr()) {
- const auto *ThrownType =
- ThrownExpr->getType()->getUnqualifiedDesugaredType();
- if (ThrownType->isReferenceType()) {
- ThrownType = ThrownType->castAs<ReferenceType>()
- ->getPointeeType()
- ->getUnqualifiedDesugaredType();
- }
- if (const auto *TD = ThrownType->getAsTagDecl()) {
- if (TD->getDeclName().isIdentifier() && TD->getName() == "bad_alloc"
- && TD->isInStdNamespace())
- return Results;
- }
- Results.push_back(ThrownExpr->getType()->getUnqualifiedDesugaredType());
- } else {
- Results.append(Caught.begin(), Caught.end());
- }
- } else if (const auto *Try = dyn_cast<CXXTryStmt>(St)) {
- TypeVec Uncaught = throwsException(Try->getTryBlock(), Caught, CallStack);
- for (unsigned i = 0; i < Try->getNumHandlers(); ++i) {
- const CXXCatchStmt *Catch = Try->getHandler(i);
- if (!Catch->getExceptionDecl()) {
- const TypeVec Rethrown =
- throwsException(Catch->getHandlerBlock(), Uncaught, CallStack);
- Results.append(Rethrown.begin(), Rethrown.end());
- Uncaught.clear();
- } else {
- const auto *CaughtType =
- Catch->getCaughtType()->getUnqualifiedDesugaredType();
- if (CaughtType->isReferenceType()) {
- CaughtType = CaughtType->castAs<ReferenceType>()
- ->getPointeeType()
- ->getUnqualifiedDesugaredType();
- }
- auto NewEnd =
- llvm::remove_if(Uncaught, [&CaughtType](const Type *ThrownType) {
- return ThrownType == CaughtType ||
- isBaseOf(ThrownType, CaughtType);
- });
- if (NewEnd != Uncaught.end()) {
- Uncaught.erase(NewEnd, Uncaught.end());
- const TypeVec Rethrown = throwsException(
- Catch->getHandlerBlock(), TypeVec(1, CaughtType), CallStack);
- Results.append(Rethrown.begin(), Rethrown.end());
- }
- }
- }
- Results.append(Uncaught.begin(), Uncaught.end());
- } else if (const auto *Call = dyn_cast<CallExpr>(St)) {
- if (const FunctionDecl *Func = Call->getDirectCallee()) {
- TypeVec Excs = throwsException(Func, CallStack);
- Results.append(Excs.begin(), Excs.end());
- }
- } else {
- for (const Stmt *Child : St->children()) {
- TypeVec Excs = throwsException(Child, Caught, CallStack);
- Results.append(Excs.begin(), Excs.end());
- }
- }
- return Results;
-}
-
-static const TypeVec throwsException(const FunctionDecl *Func) {
- llvm::SmallSet<const FunctionDecl *, 32> CallStack;
- return throwsException(Func, CallStack);
-}
-
-namespace ast_matchers {
-AST_MATCHER_P(FunctionDecl, throws, internal::Matcher<Type>, InnerMatcher) {
- TypeVec ExceptionList = throwsException(&Node);
- auto NewEnd = llvm::remove_if(
- ExceptionList, [this, Finder, Builder](const Type *Exception) {
- return !InnerMatcher.matches(*Exception, Finder, Builder);
- });
- ExceptionList.erase(NewEnd, ExceptionList.end());
- return ExceptionList.size();
-}
-
-AST_MATCHER_P(Type, isIgnored, llvm::StringSet<>, IgnoredExceptions) {
- if (const auto *TD = Node.getAsTagDecl()) {
- if (TD->getDeclName().isIdentifier())
- return IgnoredExceptions.count(TD->getName()) > 0;
- }
- return false;
-}
-
+namespace {
AST_MATCHER_P(FunctionDecl, isEnabled, llvm::StringSet<>,
FunctionsThatShouldNotThrow) {
return FunctionsThatShouldNotThrow.count(Node.getNameAsString()) > 0;
}
-} // namespace ast_matchers
+} // namespace
namespace tidy {
namespace bugprone {
-
ExceptionEscapeCheck::ExceptionEscapeCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), RawFunctionsThatShouldNotThrow(Options.get(
@@ -174,9 +36,13 @@ ExceptionEscapeCheck::ExceptionEscapeCheck(StringRef Name,
.split(FunctionsThatShouldNotThrowVec, ",", -1, false);
FunctionsThatShouldNotThrow.insert(FunctionsThatShouldNotThrowVec.begin(),
FunctionsThatShouldNotThrowVec.end());
+
+ llvm::StringSet<> IgnoredExceptions;
StringRef(RawIgnoredExceptions).split(IgnoredExceptionsVec, ",", -1, false);
IgnoredExceptions.insert(IgnoredExceptionsVec.begin(),
IgnoredExceptionsVec.end());
+ Tracer.ignoreExceptions(std::move(IgnoredExceptions));
+ Tracer.ignoreBadAlloc(true);
}
void ExceptionEscapeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
@@ -194,22 +60,26 @@ void ExceptionEscapeCheck::registerMatchers(MatchFinder *Finder) {
cxxConstructorDecl(isMoveConstructor()),
cxxMethodDecl(isMoveAssignmentOperator()),
hasName("main"), hasName("swap"),
- isEnabled(FunctionsThatShouldNotThrow)),
- throws(unless(isIgnored(IgnoredExceptions))))
+ isEnabled(FunctionsThatShouldNotThrow)))
.bind("thrower"),
this);
}
void ExceptionEscapeCheck::check(const MatchFinder::MatchResult &Result) {
- const FunctionDecl *MatchedDecl =
- Result.Nodes.getNodeAs<FunctionDecl>("thrower");
+ const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>("thrower");
+
if (!MatchedDecl)
return;
- // FIXME: We should provide more information about the exact location where
- // the exception is thrown, maybe the full path the exception escapes
- diag(MatchedDecl->getLocation(), "an exception may be thrown in function %0 "
- "which should not throw exceptions") << MatchedDecl;
+ if (Tracer.analyze(MatchedDecl).getBehaviour() ==
+ utils::ExceptionAnalyzer::State::Throwing)
+ // FIXME: We should provide more information about the exact location where
+ // the exception is thrown, maybe the full path the exception escapes
+ diag(MatchedDecl->getLocation(),
+ "an exception may be thrown in function %0 "
+
+ "which should not throw exceptions")
+ << MatchedDecl;
}
} // namespace bugprone
diff --git a/clang-tidy/bugprone/ExceptionEscapeCheck.h b/clang-tidy/bugprone/ExceptionEscapeCheck.h
index d690022a..85bb7133 100644
--- a/clang-tidy/bugprone/ExceptionEscapeCheck.h
+++ b/clang-tidy/bugprone/ExceptionEscapeCheck.h
@@ -1,17 +1,16 @@
-//===--- ExceptionEscapeCheck.h - clang-tidy---------------------*- C++ -*-===//
+//===--- ExceptionEscapeCheck.h - clang-tidy --------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_EXCEPTION_ESCAPE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTION_ESCAPE_H
-#include "../ClangTidy.h"
-
+#include "../ClangTidyCheck.h"
+#include "../utils/ExceptionAnalyzer.h"
#include "llvm/ADT/StringSet.h"
namespace clang {
@@ -37,7 +36,7 @@ private:
std::string RawIgnoredExceptions;
llvm::StringSet<> FunctionsThatShouldNotThrow;
- llvm::StringSet<> IgnoredExceptions;
+ utils::ExceptionAnalyzer Tracer;
};
} // namespace bugprone
diff --git a/clang-tidy/bugprone/FoldInitTypeCheck.cpp b/clang-tidy/bugprone/FoldInitTypeCheck.cpp
index 6d7fd285..e77c981c 100644
--- a/clang-tidy/bugprone/FoldInitTypeCheck.cpp
+++ b/clang-tidy/bugprone/FoldInitTypeCheck.cpp
@@ -1,9 +1,8 @@
//===--- FoldInitTypeCheck.cpp - clang-tidy--------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/FoldInitTypeCheck.h b/clang-tidy/bugprone/FoldInitTypeCheck.h
index e6170de0..926b9e85 100644
--- a/clang-tidy/bugprone/FoldInitTypeCheck.h
+++ b/clang-tidy/bugprone/FoldInitTypeCheck.h
@@ -1,16 +1,15 @@
//===--- FoldInitTypeCheck.h - clang-tidy------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_FOLD_INIT_TYPE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FOLD_INIT_TYPE_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp b/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp
index 9ea5b553..a03f8609 100644
--- a/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp
+++ b/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp
@@ -1,9 +1,8 @@
//===--- ForwardDeclarationNamespaceCheck.cpp - clang-tidy ------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.h b/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.h
index c3d30186..cd07a945 100644
--- a/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.h
+++ b/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.h
@@ -1,16 +1,15 @@
//===--- ForwardDeclarationNamespaceCheck.h - clang-tidy --------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_FORWARDDECLARATIONNAMESPACECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FORWARDDECLARATIONNAMESPACECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "llvm/ADT/SmallPtrSet.h"
#include <set>
#include <vector>
diff --git a/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp b/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
index 17bdc76c..57055ff2 100644
--- a/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
+++ b/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
@@ -1,9 +1,8 @@
//===--- ForwardingReferenceOverloadCheck.cpp - clang-tidy-----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.h b/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.h
index 4b00ab29..a27156c0 100644
--- a/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.h
+++ b/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.h
@@ -1,16 +1,15 @@
//===--- ForwardingReferenceOverloadCheck.h - clang-tidy---------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_FORWARDINGREFERENCEOVERLOADCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FORWARDINGREFERENCEOVERLOADCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/InaccurateEraseCheck.cpp b/clang-tidy/bugprone/InaccurateEraseCheck.cpp
index c1e65b58..95babc7a 100644
--- a/clang-tidy/bugprone/InaccurateEraseCheck.cpp
+++ b/clang-tidy/bugprone/InaccurateEraseCheck.cpp
@@ -1,9 +1,8 @@
//===--- InaccurateEraseCheck.cpp - clang-tidy-----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -18,10 +17,6 @@ namespace clang {
namespace tidy {
namespace bugprone {
-namespace {
-AST_MATCHER(Decl, isInStdNamespace) { return Node.isInStdNamespace(); }
-}
-
void InaccurateEraseCheck::registerMatchers(MatchFinder *Finder) {
// Only register the matchers for C++; the functionality currently does not
// provide any benefit to other languages, despite being benign.
diff --git a/clang-tidy/bugprone/InaccurateEraseCheck.h b/clang-tidy/bugprone/InaccurateEraseCheck.h
index d6b37290..93ea239e 100644
--- a/clang-tidy/bugprone/InaccurateEraseCheck.h
+++ b/clang-tidy/bugprone/InaccurateEraseCheck.h
@@ -1,16 +1,15 @@
//===--- InaccurateEraseCheck.h - clang-tidy---------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_INACCURATEERASECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INACCURATEERASECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp b/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp
index 549799f1..bc58e8e6 100644
--- a/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp
+++ b/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp
@@ -1,9 +1,8 @@
//===--- IncorrectRoundingsCheck.cpp - clang-tidy ------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/IncorrectRoundingsCheck.h b/clang-tidy/bugprone/IncorrectRoundingsCheck.h
index b1886fd8..436472fd 100644
--- a/clang-tidy/bugprone/IncorrectRoundingsCheck.h
+++ b/clang-tidy/bugprone/IncorrectRoundingsCheck.h
@@ -1,16 +1,15 @@
//===--- IncorrectRoundingsCheck.h - clang-tidy -----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_INCORRECTROUNDINGSCHECK_H_
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INCORRECTROUNDINGSCHECK_H_
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/IntegerDivisionCheck.cpp b/clang-tidy/bugprone/IntegerDivisionCheck.cpp
index 094d9913..670efe2a 100644
--- a/clang-tidy/bugprone/IntegerDivisionCheck.cpp
+++ b/clang-tidy/bugprone/IntegerDivisionCheck.cpp
@@ -1,9 +1,8 @@
//===--- IntegerDivisionCheck.cpp - clang-tidy-----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/IntegerDivisionCheck.h b/clang-tidy/bugprone/IntegerDivisionCheck.h
index 307e4938..6d2fb794 100644
--- a/clang-tidy/bugprone/IntegerDivisionCheck.h
+++ b/clang-tidy/bugprone/IntegerDivisionCheck.h
@@ -1,16 +1,15 @@
//===--- IntegerDivisionCheck.h - clang-tidy---------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_INTEGER_DIVISION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INTEGER_DIVISION_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp b/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp
index bdb769dc..cc8cb3bd 100644
--- a/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp
+++ b/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp
@@ -1,9 +1,8 @@
//===--- LambdaFunctionNameCheck.cpp - clang-tidy--------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -65,10 +64,10 @@ void LambdaFunctionNameCheck::registerMatchers(MatchFinder *Finder) {
this);
}
-void LambdaFunctionNameCheck::registerPPCallbacks(CompilerInstance &Compiler) {
- Compiler.getPreprocessor().addPPCallbacks(
- llvm::make_unique<MacroExpansionsWithFileAndLine>(
- &SuppressMacroExpansions));
+void LambdaFunctionNameCheck::registerPPCallbacks(
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ PP->addPPCallbacks(llvm::make_unique<MacroExpansionsWithFileAndLine>(
+ &SuppressMacroExpansions));
}
void LambdaFunctionNameCheck::check(const MatchFinder::MatchResult &Result) {
diff --git a/clang-tidy/bugprone/LambdaFunctionNameCheck.h b/clang-tidy/bugprone/LambdaFunctionNameCheck.h
index b7b1b441..d36ed464 100644
--- a/clang-tidy/bugprone/LambdaFunctionNameCheck.h
+++ b/clang-tidy/bugprone/LambdaFunctionNameCheck.h
@@ -1,16 +1,15 @@
//===--- LambdaFunctionNameCheck.h - clang-tidy------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_LAMBDAFUNCTIONNAMECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_LAMBDAFUNCTIONNAMECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
@@ -37,7 +36,8 @@ public:
LambdaFunctionNameCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
private:
diff --git a/clang-tidy/bugprone/MacroParenthesesCheck.cpp b/clang-tidy/bugprone/MacroParenthesesCheck.cpp
index 6846bc2f..874cd470 100644
--- a/clang-tidy/bugprone/MacroParenthesesCheck.cpp
+++ b/clang-tidy/bugprone/MacroParenthesesCheck.cpp
@@ -1,9 +1,8 @@
//===--- MacroParenthesesCheck.cpp - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -249,10 +248,9 @@ void MacroParenthesesPPCallbacks::argument(const Token &MacroNameTok,
}
}
-void MacroParenthesesCheck::registerPPCallbacks(CompilerInstance &Compiler) {
- Compiler.getPreprocessor().addPPCallbacks(
- llvm::make_unique<MacroParenthesesPPCallbacks>(
- &Compiler.getPreprocessor(), this));
+void MacroParenthesesCheck::registerPPCallbacks(
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ PP->addPPCallbacks(llvm::make_unique<MacroParenthesesPPCallbacks>(PP, this));
}
} // namespace bugprone
diff --git a/clang-tidy/bugprone/MacroParenthesesCheck.h b/clang-tidy/bugprone/MacroParenthesesCheck.h
index 383a6cce..8b6edaac 100644
--- a/clang-tidy/bugprone/MacroParenthesesCheck.h
+++ b/clang-tidy/bugprone/MacroParenthesesCheck.h
@@ -1,16 +1,15 @@
//===--- MacroParenthesesCheck.h - clang-tidy--------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MACROPARENTHESESCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MACROPARENTHESESCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
@@ -33,7 +32,8 @@ class MacroParenthesesCheck : public ClangTidyCheck {
public:
MacroParenthesesCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
};
} // namespace bugprone
diff --git a/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.cpp b/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.cpp
index 30c770e3..ee703466 100644
--- a/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.cpp
+++ b/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.cpp
@@ -1,9 +1,8 @@
//===--- MacroRepeatedSideEffectsCheck.cpp - clang-tidy--------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -173,10 +172,8 @@ bool MacroRepeatedPPCallbacks::hasSideEffects(
}
void MacroRepeatedSideEffectsCheck::registerPPCallbacks(
- CompilerInstance &Compiler) {
- Compiler.getPreprocessor().addPPCallbacks(
- ::llvm::make_unique<MacroRepeatedPPCallbacks>(
- *this, Compiler.getPreprocessor()));
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ PP->addPPCallbacks(::llvm::make_unique<MacroRepeatedPPCallbacks>(*this, *PP));
}
} // namespace bugprone
diff --git a/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.h b/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.h
index a2a31341..0189c7a6 100644
--- a/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.h
+++ b/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.h
@@ -1,16 +1,15 @@
//===--- MacroRepeatedSideEffectsCheck.h - clang-tidy -----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MACROREPEATEDSIDEEFFECTSCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MACROREPEATEDSIDEEFFECTSCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
@@ -21,7 +20,8 @@ class MacroRepeatedSideEffectsCheck : public ClangTidyCheck {
public:
MacroRepeatedSideEffectsCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
};
} // namespace bugprone
diff --git a/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp b/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp
index 83ddbcfb..3e6f9fde 100644
--- a/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp
+++ b/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp
@@ -1,9 +1,8 @@
//===--- MisplacedOperatorInStrlenInAllocCheck.cpp - clang-tidy------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h b/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h
index 99cfcfbb..0eb1b433 100644
--- a/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h
+++ b/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h
@@ -1,16 +1,15 @@
//===--- MisplacedOperatorInStrlenInAllocCheck.h - clang-tidy----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISPLACED_OPERATOR_IN_STRLEN_IN_ALLOC_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACED_OPERATOR_IN_STRLEN_IN_ALLOC_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp b/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp
index 46fbd2b4..98a1a0c3 100644
--- a/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp
+++ b/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp
@@ -1,9 +1,8 @@
//===--- MisplacedWideningCastCheck.cpp - clang-tidy-----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/MisplacedWideningCastCheck.h b/clang-tidy/bugprone/MisplacedWideningCastCheck.h
index b61556fd..a1b37372 100644
--- a/clang-tidy/bugprone/MisplacedWideningCastCheck.h
+++ b/clang-tidy/bugprone/MisplacedWideningCastCheck.h
@@ -1,16 +1,15 @@
//===--- MisplacedWideningCastCheck.h - clang-tidy---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISPLACEDWIDENINGCASTCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACEDWIDENINGCASTCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp b/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp
index f75a194f..bf6f2f6e 100644
--- a/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp
+++ b/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp
@@ -1,9 +1,8 @@
//===--- MoveForwardingReferenceCheck.cpp - clang-tidy --------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/MoveForwardingReferenceCheck.h b/clang-tidy/bugprone/MoveForwardingReferenceCheck.h
index c61de757..2ed08cb7 100644
--- a/clang-tidy/bugprone/MoveForwardingReferenceCheck.h
+++ b/clang-tidy/bugprone/MoveForwardingReferenceCheck.h
@@ -1,16 +1,15 @@
//===--- MoveForwardingReferenceCheck.h - clang-tidy ----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MOVEFORWARDINGREFERENCECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MOVEFORWARDINGREFERENCECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/MultipleStatementMacroCheck.cpp b/clang-tidy/bugprone/MultipleStatementMacroCheck.cpp
index 5c498213..5cc7febc 100644
--- a/clang-tidy/bugprone/MultipleStatementMacroCheck.cpp
+++ b/clang-tidy/bugprone/MultipleStatementMacroCheck.cpp
@@ -1,9 +1,8 @@
//===--- MultipleStatementMacroCheck.cpp - clang-tidy----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/MultipleStatementMacroCheck.h b/clang-tidy/bugprone/MultipleStatementMacroCheck.h
index efc65991..72823d3a 100644
--- a/clang-tidy/bugprone/MultipleStatementMacroCheck.h
+++ b/clang-tidy/bugprone/MultipleStatementMacroCheck.h
@@ -1,16 +1,15 @@
//===--- MultipleStatementMacroCheck.h - clang-tidy--------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MULTIPLE_STATEMENT_MACRO_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLE_STATEMENT_MACRO_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/ParentVirtualCallCheck.cpp b/clang-tidy/bugprone/ParentVirtualCallCheck.cpp
index a5293b15..b2f51426 100755
--- a/clang-tidy/bugprone/ParentVirtualCallCheck.cpp
+++ b/clang-tidy/bugprone/ParentVirtualCallCheck.cpp
@@ -1,9 +1,8 @@
//===--- ParentVirtualCallCheck.cpp - clang-tidy---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/ParentVirtualCallCheck.h b/clang-tidy/bugprone/ParentVirtualCallCheck.h
index 08c3aefb..ade80172 100755
--- a/clang-tidy/bugprone/ParentVirtualCallCheck.h
+++ b/clang-tidy/bugprone/ParentVirtualCallCheck.h
@@ -1,16 +1,15 @@
//===--- ParentVirtualCallCheck.h - clang-tidy-------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_PARENTVIRTUALCALLCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_PARENTVIRTUALCALLCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/SizeofContainerCheck.cpp b/clang-tidy/bugprone/SizeofContainerCheck.cpp
index f7d63b1a..411fe8de 100644
--- a/clang-tidy/bugprone/SizeofContainerCheck.cpp
+++ b/clang-tidy/bugprone/SizeofContainerCheck.cpp
@@ -1,9 +1,8 @@
//===--- SizeofContainerCheck.cpp - clang-tidy-----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/SizeofContainerCheck.h b/clang-tidy/bugprone/SizeofContainerCheck.h
index 76b82b00..c74b7556 100644
--- a/clang-tidy/bugprone/SizeofContainerCheck.h
+++ b/clang-tidy/bugprone/SizeofContainerCheck.h
@@ -1,16 +1,15 @@
//===--- SizeofContainerCheck.h - clang-tidy---------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_SIZEOFCONTAINERCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SIZEOFCONTAINERCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/SizeofExpressionCheck.cpp b/clang-tidy/bugprone/SizeofExpressionCheck.cpp
index d662657a..fb161957 100644
--- a/clang-tidy/bugprone/SizeofExpressionCheck.cpp
+++ b/clang-tidy/bugprone/SizeofExpressionCheck.cpp
@@ -1,9 +1,8 @@
//===--- SizeofExpressionCheck.cpp - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -85,8 +84,11 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
const auto IntegerCallExpr = expr(ignoringParenImpCasts(
callExpr(anyOf(hasType(isInteger()), hasType(enumType())),
unless(isInTemplateInstantiation()))));
- const auto SizeOfExpr =
- expr(anyOf(sizeOfExpr(has(type())), sizeOfExpr(has(expr()))));
+ const auto SizeOfExpr = expr(anyOf(
+ sizeOfExpr(
+ has(hasUnqualifiedDesugaredType(type().bind("sizeof-arg-type")))),
+ sizeOfExpr(has(expr(hasType(
+ hasUnqualifiedDesugaredType(type().bind("sizeof-arg-type"))))))));
const auto SizeOfZero = expr(
sizeOfExpr(has(ignoringParenImpCasts(expr(integerLiteral(equals(0)))))));
@@ -210,6 +212,36 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
hasSizeOfDescendant(8, expr(SizeOfExpr, unless(SizeOfZero))))))))
.bind("sizeof-sizeof-expr"),
this);
+
+ // Detect sizeof in pointer aritmetic like: N * sizeof(S) == P1 - P2 or
+ // (P1 - P2) / sizeof(S) where P1 and P2 are pointers to type S.
+ const auto PtrDiffExpr = binaryOperator(
+ hasOperatorName("-"),
+ hasLHS(expr(hasType(hasUnqualifiedDesugaredType(pointerType(pointee(
+ hasUnqualifiedDesugaredType(type().bind("left-ptr-type")))))))),
+ hasRHS(expr(hasType(hasUnqualifiedDesugaredType(pointerType(pointee(
+ hasUnqualifiedDesugaredType(type().bind("right-ptr-type")))))))));
+
+ Finder->addMatcher(
+ binaryOperator(
+ anyOf(hasOperatorName("=="), hasOperatorName("!="),
+ hasOperatorName("<"), hasOperatorName("<="),
+ hasOperatorName(">"), hasOperatorName(">="),
+ hasOperatorName("+"), hasOperatorName("-")),
+ hasEitherOperand(expr(anyOf(
+ ignoringParenImpCasts(SizeOfExpr),
+ ignoringParenImpCasts(binaryOperator(
+ hasOperatorName("*"),
+ hasEitherOperand(ignoringParenImpCasts(SizeOfExpr))))))),
+ hasEitherOperand(ignoringParenImpCasts(PtrDiffExpr)))
+ .bind("sizeof-in-ptr-arithmetic-mul"),
+ this);
+
+ Finder->addMatcher(binaryOperator(hasOperatorName("/"),
+ hasLHS(ignoringParenImpCasts(PtrDiffExpr)),
+ hasRHS(ignoringParenImpCasts(SizeOfExpr)))
+ .bind("sizeof-in-ptr-arithmetic-div"),
+ this);
}
void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) {
@@ -276,6 +308,26 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) {
} else if (const auto *E =
Result.Nodes.getNodeAs<Expr>("sizeof-multiply-sizeof")) {
diag(E->getBeginLoc(), "suspicious 'sizeof' by 'sizeof' multiplication");
+ } else if (const auto *E =
+ Result.Nodes.getNodeAs<Expr>("sizeof-in-ptr-arithmetic-mul")) {
+ const auto *LPtrTy = Result.Nodes.getNodeAs<Type>("left-ptr-type");
+ const auto *RPtrTy = Result.Nodes.getNodeAs<Type>("right-ptr-type");
+ const auto *SizeofArgTy = Result.Nodes.getNodeAs<Type>("sizeof-arg-type");
+
+ if ((LPtrTy == RPtrTy) && (LPtrTy == SizeofArgTy)) {
+ diag(E->getBeginLoc(), "suspicious usage of 'sizeof(...)' in "
+ "pointer arithmetic");
+ }
+ } else if (const auto *E =
+ Result.Nodes.getNodeAs<Expr>("sizeof-in-ptr-arithmetic-div")) {
+ const auto *LPtrTy = Result.Nodes.getNodeAs<Type>("left-ptr-type");
+ const auto *RPtrTy = Result.Nodes.getNodeAs<Type>("right-ptr-type");
+ const auto *SizeofArgTy = Result.Nodes.getNodeAs<Type>("sizeof-arg-type");
+
+ if ((LPtrTy == RPtrTy) && (LPtrTy == SizeofArgTy)) {
+ diag(E->getBeginLoc(), "suspicious usage of 'sizeof(...)' in "
+ "pointer arithmetic");
+ }
}
}
diff --git a/clang-tidy/bugprone/SizeofExpressionCheck.h b/clang-tidy/bugprone/SizeofExpressionCheck.h
index 8e14c315..90d81229 100644
--- a/clang-tidy/bugprone/SizeofExpressionCheck.h
+++ b/clang-tidy/bugprone/SizeofExpressionCheck.h
@@ -1,16 +1,15 @@
//===--- SizeofExpressionCheck.h - clang-tidy--------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_SIZEOFEXPRESSIONCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SIZEOFEXPRESSIONCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/StringConstructorCheck.cpp b/clang-tidy/bugprone/StringConstructorCheck.cpp
index cc6e2973..a4b83ada 100644
--- a/clang-tidy/bugprone/StringConstructorCheck.cpp
+++ b/clang-tidy/bugprone/StringConstructorCheck.cpp
@@ -1,9 +1,8 @@
//===--- StringConstructorCheck.cpp - clang-tidy---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -139,7 +138,8 @@ void StringConstructorCheck::check(const MatchFinder::MatchResult &Result) {
}
} else if (const auto *Ptr = Result.Nodes.getNodeAs<Expr>("from-ptr")) {
Expr::EvalResult ConstPtr;
- if (Ptr->EvaluateAsRValue(ConstPtr, Ctx) &&
+ if (!Ptr->isInstantiationDependent() &&
+ Ptr->EvaluateAsRValue(ConstPtr, Ctx) &&
((ConstPtr.Val.isInt() && ConstPtr.Val.getInt().isNullValue()) ||
(ConstPtr.Val.isLValue() && ConstPtr.Val.isNullPointer()))) {
diag(Loc, "constructing string from nullptr is undefined behaviour");
diff --git a/clang-tidy/bugprone/StringConstructorCheck.h b/clang-tidy/bugprone/StringConstructorCheck.h
index 52e9791f..e7b4c874 100644
--- a/clang-tidy/bugprone/StringConstructorCheck.h
+++ b/clang-tidy/bugprone/StringConstructorCheck.h
@@ -1,16 +1,15 @@
//===--- StringConstructorCheck.h - clang-tidy-------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_STRING_CONSTRUCTOR_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRING_CONSTRUCTOR_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp b/clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp
index f49a5709..c64b5f36 100644
--- a/clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp
+++ b/clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp
@@ -1,9 +1,8 @@
//===--- StringIntegerAssignmentCheck.cpp - clang-tidy---------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -27,20 +26,121 @@ void StringIntegerAssignmentCheck::registerMatchers(MatchFinder *Finder) {
hasOverloadedOperatorName("+=")),
callee(cxxMethodDecl(ofClass(classTemplateSpecializationDecl(
hasName("::std::basic_string"),
- hasTemplateArgument(0, refersToType(qualType().bind("type"))))))),
- hasArgument(1,
- ignoringImpCasts(expr(hasType(isInteger()),
- unless(hasType(isAnyCharacter())))
- .bind("expr"))),
+ hasTemplateArgument(0, refersToType(hasCanonicalType(
+ qualType().bind("type")))))))),
+ hasArgument(
+ 1,
+ ignoringImpCasts(
+ expr(hasType(isInteger()), unless(hasType(isAnyCharacter())),
+ // Ignore calls to tolower/toupper (see PR27723).
+ unless(callExpr(callee(functionDecl(
+ hasAnyName("tolower", "std::tolower", "toupper",
+ "std::toupper"))))),
+ // Do not warn if assigning e.g. `CodePoint` to
+ // `basic_string<CodePoint>`
+ unless(hasType(qualType(
+ hasCanonicalType(equalsBoundNode("type"))))))
+ .bind("expr"))),
unless(isInTemplateInstantiation())),
this);
}
+class CharExpressionDetector {
+public:
+ CharExpressionDetector(QualType CharType, const ASTContext &Ctx)
+ : CharType(CharType), Ctx(Ctx) {}
+
+ bool isLikelyCharExpression(const Expr *E) const {
+ if (isCharTyped(E))
+ return true;
+
+ if (const auto *BinOp = dyn_cast<BinaryOperator>(E)) {
+ const auto *LHS = BinOp->getLHS()->IgnoreParenImpCasts();
+ const auto *RHS = BinOp->getRHS()->IgnoreParenImpCasts();
+ // Handle both directions, e.g. `'a' + (i % 26)` and `(i % 26) + 'a'`.
+ if (BinOp->isAdditiveOp() || BinOp->isBitwiseOp())
+ return handleBinaryOp(BinOp->getOpcode(), LHS, RHS) ||
+ handleBinaryOp(BinOp->getOpcode(), RHS, LHS);
+ // Except in the case of '%'.
+ if (BinOp->getOpcode() == BO_Rem)
+ return handleBinaryOp(BinOp->getOpcode(), LHS, RHS);
+ return false;
+ }
+
+ // Ternary where at least one branch is a likely char expression, e.g.
+ // i < 265 ? i : ' '
+ if (const auto *CondOp = dyn_cast<AbstractConditionalOperator>(E))
+ return isLikelyCharExpression(
+ CondOp->getFalseExpr()->IgnoreParenImpCasts()) ||
+ isLikelyCharExpression(
+ CondOp->getTrueExpr()->IgnoreParenImpCasts());
+ return false;
+ }
+
+private:
+ bool handleBinaryOp(clang::BinaryOperatorKind Opcode, const Expr *const LHS,
+ const Expr *const RHS) const {
+ // <char_expr> <op> <char_expr> (c++ integer promotion rules make this an
+ // int), e.g.
+ // 'a' + c
+ if (isCharTyped(LHS) && isCharTyped(RHS))
+ return true;
+
+ // <expr> & <char_valued_constant> or <expr> % <char_valued_constant>, e.g.
+ // i & 0xff
+ if ((Opcode == BO_And || Opcode == BO_Rem) && isCharValuedConstant(RHS))
+ return true;
+
+ // <char_expr> | <char_valued_constant>, e.g.
+ // c | 0x80
+ if (Opcode == BO_Or && isCharTyped(LHS) && isCharValuedConstant(RHS))
+ return true;
+
+ // <char_constant> + <likely_char_expr>, e.g.
+ // 'a' + (i % 26)
+ if (Opcode == BO_Add)
+ return isCharConstant(LHS) && isLikelyCharExpression(RHS);
+
+ return false;
+ }
+
+ // Returns true if `E` is an character constant.
+ bool isCharConstant(const Expr *E) const {
+ return isCharTyped(E) && isCharValuedConstant(E);
+ };
+
+ // Returns true if `E` is an integer constant which fits in `CharType`.
+ bool isCharValuedConstant(const Expr *E) const {
+ if (E->isInstantiationDependent())
+ return false;
+ Expr::EvalResult EvalResult;
+ if (!E->EvaluateAsInt(EvalResult, Ctx, Expr::SE_AllowSideEffects))
+ return false;
+ return EvalResult.Val.getInt().getActiveBits() <= Ctx.getTypeSize(CharType);
+ };
+
+ // Returns true if `E` has the right character type.
+ bool isCharTyped(const Expr *E) const {
+ return E->getType().getCanonicalType().getTypePtr() ==
+ CharType.getTypePtr();
+ };
+
+ const QualType CharType;
+ const ASTContext &Ctx;
+};
+
void StringIntegerAssignmentCheck::check(
const MatchFinder::MatchResult &Result) {
const auto *Argument = Result.Nodes.getNodeAs<Expr>("expr");
+ const auto CharType =
+ Result.Nodes.getNodeAs<QualType>("type")->getCanonicalType();
SourceLocation Loc = Argument->getBeginLoc();
+ // Try to detect a few common expressions to reduce false positives.
+ if (CharExpressionDetector(CharType, *Result.Context)
+ .isLikelyCharExpression(Argument))
+ return;
+
auto Diag =
diag(Loc, "an integer is interpreted as a character code when assigning "
"it to a string; if this is intended, cast the integer to the "
@@ -50,7 +150,6 @@ void StringIntegerAssignmentCheck::check(
if (Loc.isMacroID())
return;
- auto CharType = *Result.Nodes.getNodeAs<QualType>("type");
bool IsWideCharType = CharType->isWideCharType();
if (!CharType->isCharType() && !IsWideCharType)
return;
diff --git a/clang-tidy/bugprone/StringIntegerAssignmentCheck.h b/clang-tidy/bugprone/StringIntegerAssignmentCheck.h
index 42fa53e9..733e7bed 100644
--- a/clang-tidy/bugprone/StringIntegerAssignmentCheck.h
+++ b/clang-tidy/bugprone/StringIntegerAssignmentCheck.h
@@ -1,16 +1,15 @@
//===--- StringIntegerAssignmentCheck.h - clang-tidy-------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_STRINGINTEGERASSIGNMENTCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRINGINTEGERASSIGNMENTCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.cpp b/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.cpp
index b440b616..0fbd93e8 100644
--- a/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.cpp
+++ b/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.cpp
@@ -1,9 +1,8 @@
//===--- StringLiteralWithEmbeddedNulCheck.cpp - clang-tidy----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.h b/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.h
index f5341c31..a163a9f2 100644
--- a/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.h
+++ b/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.h
@@ -1,16 +1,15 @@
//===--- StringLiteralWithEmbeddedNulCheck.h - clang-tidy--------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_STRINGLITERALWITHEMBEDDEDNULCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRINGLITERALWITHEMBEDDEDNULCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp b/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp
index 53537005..42965a6d 100644
--- a/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp
+++ b/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp
@@ -1,9 +1,8 @@
//===--- SuspiciousEnumUsageCheck.cpp - clang-tidy-------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/SuspiciousEnumUsageCheck.h b/clang-tidy/bugprone/SuspiciousEnumUsageCheck.h
index 9c1b53d7..f05f3e1c 100644
--- a/clang-tidy/bugprone/SuspiciousEnumUsageCheck.h
+++ b/clang-tidy/bugprone/SuspiciousEnumUsageCheck.h
@@ -1,16 +1,15 @@
//===--- SuspiciousEnumUsageCheck.h - clang-tidy--------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_SUSPICIOUSENUMUSAGECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSENUMUSAGECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp b/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp
index ca3c1263..9f983169 100644
--- a/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp
+++ b/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp
@@ -1,9 +1,8 @@
//===--- SuspiciousMemsetUsageCheck.cpp - clang-tidy-----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h b/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h
index 1c0d1bcf..40746413 100644
--- a/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h
+++ b/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h
@@ -1,16 +1,15 @@
//===--- SuspiciousMemsetUsageCheck.h - clang-tidy---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_SUSPICIOUS_MEMSET_USAGE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUS_MEMSET_USAGE_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp b/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp
index a66cf431..09409d87 100644
--- a/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp
+++ b/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp
@@ -1,9 +1,8 @@
//===--- SuspiciousMissingCommaCheck.cpp - clang-tidy----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/SuspiciousMissingCommaCheck.h b/clang-tidy/bugprone/SuspiciousMissingCommaCheck.h
index 4ae3ecf0..bf90f0a3 100644
--- a/clang-tidy/bugprone/SuspiciousMissingCommaCheck.h
+++ b/clang-tidy/bugprone/SuspiciousMissingCommaCheck.h
@@ -1,16 +1,15 @@
//===--- SuspiciousMissingCommaCheck.h - clang-tidy--------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_SUSPICIOUSMISSINGCOMMACHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSMISSINGCOMMACHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp b/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp
index f92fc37f..d94731be 100644
--- a/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp
+++ b/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp
@@ -1,9 +1,8 @@
//===--- SuspiciousSemicolonCheck.cpp - clang-tidy-------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -54,7 +53,7 @@ void SuspiciousSemicolonCheck::check(const MatchFinder::MatchResult &Result) {
SourceLocation LocEnd = Semicolon->getEndLoc();
FileID FID = SM.getFileID(LocEnd);
- llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, LocEnd);
+ const llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, LocEnd);
Lexer Lexer(SM.getLocForStartOfFile(FID), Ctxt.getLangOpts(),
Buffer->getBufferStart(), SM.getCharacterData(LocEnd) + 1,
Buffer->getBufferEnd());
diff --git a/clang-tidy/bugprone/SuspiciousSemicolonCheck.h b/clang-tidy/bugprone/SuspiciousSemicolonCheck.h
index adfced1a..0228f386 100644
--- a/clang-tidy/bugprone/SuspiciousSemicolonCheck.h
+++ b/clang-tidy/bugprone/SuspiciousSemicolonCheck.h
@@ -1,16 +1,15 @@
//===--- SuspiciousSemicolonCheck.h - clang-tidy-----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_SUSPICIOUSSEMICOLONCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSSEMICOLONCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp b/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp
index a16da4af..8de64608 100644
--- a/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp
+++ b/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp
@@ -1,9 +1,8 @@
//===--- SuspiciousStringCompareCheck.cpp - clang-tidy---------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/SuspiciousStringCompareCheck.h b/clang-tidy/bugprone/SuspiciousStringCompareCheck.h
index 38a9d9cd..d0cda51c 100644
--- a/clang-tidy/bugprone/SuspiciousStringCompareCheck.h
+++ b/clang-tidy/bugprone/SuspiciousStringCompareCheck.h
@@ -1,16 +1,15 @@
//===--- SuspiciousStringCompareCheck.h - clang-tidy-------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_SUSPICIOUSSTRINGCOMPARECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSSTRINGCOMPARECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/SwappedArgumentsCheck.cpp b/clang-tidy/bugprone/SwappedArgumentsCheck.cpp
index c1550f6d..9f055306 100644
--- a/clang-tidy/bugprone/SwappedArgumentsCheck.cpp
+++ b/clang-tidy/bugprone/SwappedArgumentsCheck.cpp
@@ -1,9 +1,8 @@
//===--- SwappedArgumentsCheck.cpp - clang-tidy ---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/SwappedArgumentsCheck.h b/clang-tidy/bugprone/SwappedArgumentsCheck.h
index 59ec3add..484972cc 100644
--- a/clang-tidy/bugprone/SwappedArgumentsCheck.h
+++ b/clang-tidy/bugprone/SwappedArgumentsCheck.h
@@ -1,16 +1,15 @@
//===--- SwappedArgumentsCheck.h - clang-tidy -------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_SWAPPEDARGUMENTSCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SWAPPEDARGUMENTSCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/TerminatingContinueCheck.cpp b/clang-tidy/bugprone/TerminatingContinueCheck.cpp
index e41fc1fa..beeeb2c8 100644
--- a/clang-tidy/bugprone/TerminatingContinueCheck.cpp
+++ b/clang-tidy/bugprone/TerminatingContinueCheck.cpp
@@ -1,9 +1,8 @@
//===--- TerminatingContinueCheck.cpp - clang-tidy-------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/TerminatingContinueCheck.h b/clang-tidy/bugprone/TerminatingContinueCheck.h
index 5985693c..480db5d1 100644
--- a/clang-tidy/bugprone/TerminatingContinueCheck.h
+++ b/clang-tidy/bugprone/TerminatingContinueCheck.h
@@ -1,16 +1,15 @@
//===--- TerminatingContinueCheck.h - clang-tidy-----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_TERMINATINGCONTINUECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_TERMINATINGCONTINUECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/ThrowKeywordMissingCheck.cpp b/clang-tidy/bugprone/ThrowKeywordMissingCheck.cpp
index 695d9c5f..767f9a4a 100644
--- a/clang-tidy/bugprone/ThrowKeywordMissingCheck.cpp
+++ b/clang-tidy/bugprone/ThrowKeywordMissingCheck.cpp
@@ -1,9 +1,8 @@
//===--- ThrowKeywordMissingCheck.cpp - clang-tidy-------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/ThrowKeywordMissingCheck.h b/clang-tidy/bugprone/ThrowKeywordMissingCheck.h
index cc57083c..d5e7d4ef 100644
--- a/clang-tidy/bugprone/ThrowKeywordMissingCheck.h
+++ b/clang-tidy/bugprone/ThrowKeywordMissingCheck.h
@@ -1,16 +1,15 @@
//===--- ThrowKeywordMissingCheck.h - clang-tidy-----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_THROWKEYWORDMISSINGCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_THROWKEYWORDMISSINGCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp b/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
index 59cc185e..1e31fde1 100644
--- a/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
+++ b/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
@@ -1,9 +1,8 @@
//===--- TooSmallLoopVariableCheck.cpp - clang-tidy -----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -28,6 +27,17 @@ static constexpr llvm::StringLiteral LoopUpperBoundName =
static constexpr llvm::StringLiteral LoopIncrementName =
llvm::StringLiteral("loopIncrement");
+TooSmallLoopVariableCheck::TooSmallLoopVariableCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ MagnitudeBitsUpperLimit(Options.get<unsigned>(
+ "MagnitudeBitsUpperLimit", 16)) {}
+
+void TooSmallLoopVariableCheck::storeOptions(
+ ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "MagnitudeBitsUpperLimit", MagnitudeBitsUpperLimit);
+}
+
/// \brief The matcher for loops with suspicious integer loop variable.
///
/// In this general example, assuming 'j' and 'k' are of integral type:
@@ -85,9 +95,9 @@ void TooSmallLoopVariableCheck::registerMatchers(MatchFinder *Finder) {
this);
}
-/// Returns the positive part of the integer width for an integer type.
-static unsigned calcPositiveBits(const ASTContext &Context,
- const QualType &IntExprType) {
+/// Returns the magnitude bits of an integer type.
+static unsigned calcMagnitudeBits(const ASTContext &Context,
+ const QualType &IntExprType) {
assert(IntExprType->isIntegerType());
return IntExprType->isUnsignedIntegerType()
@@ -95,13 +105,13 @@ static unsigned calcPositiveBits(const ASTContext &Context,
: Context.getIntWidth(IntExprType) - 1;
}
-/// \brief Calculate the upper bound expression's positive bits, but ignore
+/// \brief Calculate the upper bound expression's magnitude bits, but ignore
/// constant like values to reduce false positives.
-static unsigned calcUpperBoundPositiveBits(const ASTContext &Context,
- const Expr *UpperBound,
- const QualType &UpperBoundType) {
+static unsigned calcUpperBoundMagnitudeBits(const ASTContext &Context,
+ const Expr *UpperBound,
+ const QualType &UpperBoundType) {
// Ignore casting caused by constant values inside a binary operator.
- // We are interested in variable values' positive bits.
+ // We are interested in variable values' magnitude bits.
if (const auto *BinOperator = dyn_cast<BinaryOperator>(UpperBound)) {
const Expr *RHSE = BinOperator->getRHS()->IgnoreParenImpCasts();
const Expr *LHSE = BinOperator->getLHS()->IgnoreParenImpCasts();
@@ -123,15 +133,15 @@ static unsigned calcUpperBoundPositiveBits(const ASTContext &Context,
if (RHSEIsConstantValue && LHSEIsConstantValue)
return 0;
if (RHSEIsConstantValue)
- return calcPositiveBits(Context, LHSEType);
+ return calcMagnitudeBits(Context, LHSEType);
if (LHSEIsConstantValue)
- return calcPositiveBits(Context, RHSEType);
+ return calcMagnitudeBits(Context, RHSEType);
- return std::max(calcPositiveBits(Context, LHSEType),
- calcPositiveBits(Context, RHSEType));
+ return std::max(calcMagnitudeBits(Context, LHSEType),
+ calcMagnitudeBits(Context, RHSEType));
}
- return calcPositiveBits(Context, UpperBoundType);
+ return calcMagnitudeBits(Context, UpperBoundType);
}
void TooSmallLoopVariableCheck::check(const MatchFinder::MatchResult &Result) {
@@ -150,14 +160,17 @@ void TooSmallLoopVariableCheck::check(const MatchFinder::MatchResult &Result) {
ASTContext &Context = *Result.Context;
- unsigned LoopVarPosBits = calcPositiveBits(Context, LoopVarType);
- unsigned UpperBoundPosBits =
- calcUpperBoundPositiveBits(Context, UpperBound, UpperBoundType);
+ unsigned LoopVarMagnitudeBits = calcMagnitudeBits(Context, LoopVarType);
+ unsigned UpperBoundMagnitudeBits =
+ calcUpperBoundMagnitudeBits(Context, UpperBound, UpperBoundType);
+
+ if (UpperBoundMagnitudeBits == 0)
+ return;
- if (UpperBoundPosBits == 0)
+ if (LoopVarMagnitudeBits > MagnitudeBitsUpperLimit)
return;
- if (LoopVarPosBits < UpperBoundPosBits)
+ if (LoopVarMagnitudeBits < UpperBoundMagnitudeBits)
diag(LoopVar->getBeginLoc(), "loop variable has narrower type %0 than "
"iteration's upper bound %1")
<< LoopVarType << UpperBoundType;
diff --git a/clang-tidy/bugprone/TooSmallLoopVariableCheck.h b/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
index 0819fcf1..c48b4460 100644
--- a/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
+++ b/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
@@ -1,16 +1,15 @@
//===--- TooSmallLoopVariableCheck.h - clang-tidy ---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_TOOSMALLLOOPVARIABLECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_TOOSMALLLOOPVARIABLECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
@@ -30,10 +29,14 @@ namespace bugprone {
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-too-small-loop-variable.html
class TooSmallLoopVariableCheck : public ClangTidyCheck {
public:
- TooSmallLoopVariableCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context) {}
+ TooSmallLoopVariableCheck(StringRef Name, ClangTidyContext *Context);
+
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ const unsigned MagnitudeBitsUpperLimit;
};
} // namespace bugprone
diff --git a/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp b/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
index 0665e080..514ee5ab 100644
--- a/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
+++ b/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
@@ -1,9 +1,8 @@
//===--- UndefinedMemoryManipulationCheck.cpp - clang-tidy-----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h b/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h
index 64d6c56b..25af704f 100644
--- a/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h
+++ b/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h
@@ -1,16 +1,15 @@
//===--- UndefinedMemoryManipulationCheck.h - clang-tidy---------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_UNDEFINED_MEMORY_MANIPULATION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDEFINED_MEMORY_MANIPULATION_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/UndelegatedConstructorCheck.cpp b/clang-tidy/bugprone/UndelegatedConstructorCheck.cpp
index 90c07b9a..32a023fc 100644
--- a/clang-tidy/bugprone/UndelegatedConstructorCheck.cpp
+++ b/clang-tidy/bugprone/UndelegatedConstructorCheck.cpp
@@ -1,9 +1,8 @@
//===--- UndelegatedConstructorCheck.cpp - clang-tidy --------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/UndelegatedConstructorCheck.h b/clang-tidy/bugprone/UndelegatedConstructorCheck.h
index ed881e15..09060529 100644
--- a/clang-tidy/bugprone/UndelegatedConstructorCheck.h
+++ b/clang-tidy/bugprone/UndelegatedConstructorCheck.h
@@ -1,16 +1,15 @@
//===--- UndelegatedConstructorCheck.h - clang-tidy -------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISC_UNDELEGATEDCONSTRUCTOR_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNDELEGATEDCONSTRUCTOR_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/UnusedRaiiCheck.cpp b/clang-tidy/bugprone/UnusedRaiiCheck.cpp
index e9089b77..e89cbe19 100644
--- a/clang-tidy/bugprone/UnusedRaiiCheck.cpp
+++ b/clang-tidy/bugprone/UnusedRaiiCheck.cpp
@@ -1,9 +1,8 @@
//===--- UnusedRaiiCheck.cpp - clang-tidy ---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/UnusedRaiiCheck.h b/clang-tidy/bugprone/UnusedRaiiCheck.h
index 34190ece..1307a77b 100644
--- a/clang-tidy/bugprone/UnusedRaiiCheck.h
+++ b/clang-tidy/bugprone/UnusedRaiiCheck.h
@@ -1,16 +1,15 @@
//===--- UnusedRaiiCheck.h - clang-tidy -------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_UNUSEDRAIICHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNUSEDRAIICHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/UnusedReturnValueCheck.cpp b/clang-tidy/bugprone/UnusedReturnValueCheck.cpp
index b8de045e..c3efb08d 100644
--- a/clang-tidy/bugprone/UnusedReturnValueCheck.cpp
+++ b/clang-tidy/bugprone/UnusedReturnValueCheck.cpp
@@ -1,9 +1,8 @@
//===--- UnusedReturnValueCheck.cpp - clang-tidy---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/UnusedReturnValueCheck.h b/clang-tidy/bugprone/UnusedReturnValueCheck.h
index 9475f56b..7e100cd5 100644
--- a/clang-tidy/bugprone/UnusedReturnValueCheck.h
+++ b/clang-tidy/bugprone/UnusedReturnValueCheck.h
@@ -1,16 +1,15 @@
//===--- UnusedReturnValueCheck.h - clang-tidy-------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_UNUSEDRETURNVALUECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNUSEDRETURNVALUECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include <string>
namespace clang {
diff --git a/clang-tidy/bugprone/UseAfterMoveCheck.cpp b/clang-tidy/bugprone/UseAfterMoveCheck.cpp
index 99c847eb..8e316ebc 100644
--- a/clang-tidy/bugprone/UseAfterMoveCheck.cpp
+++ b/clang-tidy/bugprone/UseAfterMoveCheck.cpp
@@ -1,9 +1,8 @@
//===--- UseAfterMoveCheck.cpp - clang-tidy -------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/UseAfterMoveCheck.h b/clang-tidy/bugprone/UseAfterMoveCheck.h
index f6dea68d..27cb32bb 100644
--- a/clang-tidy/bugprone/UseAfterMoveCheck.h
+++ b/clang-tidy/bugprone/UseAfterMoveCheck.h
@@ -1,16 +1,15 @@
//===--- UseAfterMoveCheck.h - clang-tidy ---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_USEAFTERMOVECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_USEAFTERMOVECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/bugprone/VirtualNearMissCheck.cpp b/clang-tidy/bugprone/VirtualNearMissCheck.cpp
index ede1bf33..32ca1b48 100644
--- a/clang-tidy/bugprone/VirtualNearMissCheck.cpp
+++ b/clang-tidy/bugprone/VirtualNearMissCheck.cpp
@@ -1,9 +1,8 @@
//===--- VirtualNearMissCheck.cpp - clang-tidy-----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/VirtualNearMissCheck.h b/clang-tidy/bugprone/VirtualNearMissCheck.h
index ea1e2566..d5f4a11e 100644
--- a/clang-tidy/bugprone/VirtualNearMissCheck.h
+++ b/clang-tidy/bugprone/VirtualNearMissCheck.h
@@ -1,16 +1,15 @@
//===--- VirtualNearMissCheck.h - clang-tidy---------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_VIRTUAL_NEAR_MISS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_VIRTUAL_NEAR_MISS_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "llvm/ADT/DenseMap.h"
namespace clang {
diff --git a/clang-tidy/cert/CERTTidyModule.cpp b/clang-tidy/cert/CERTTidyModule.cpp
index b6a0e7b6..cd8da0c6 100644
--- a/clang-tidy/cert/CERTTidyModule.cpp
+++ b/clang-tidy/cert/CERTTidyModule.cpp
@@ -1,9 +1,8 @@
//===--- CERTTidyModule.cpp - clang-tidy ----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cert/CommandProcessorCheck.cpp b/clang-tidy/cert/CommandProcessorCheck.cpp
index e2dbeca2..72b39d18 100644
--- a/clang-tidy/cert/CommandProcessorCheck.cpp
+++ b/clang-tidy/cert/CommandProcessorCheck.cpp
@@ -1,9 +1,8 @@
-//===--- Env33CCheck.cpp - clang-tidy--------------------------------------===//
+//===-- CommandProcessorCheck.cpp - clang-tidy ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cert/CommandProcessorCheck.h b/clang-tidy/cert/CommandProcessorCheck.h
index a85a7eda..14ebd081 100644
--- a/clang-tidy/cert/CommandProcessorCheck.h
+++ b/clang-tidy/cert/CommandProcessorCheck.h
@@ -1,16 +1,15 @@
//===--- CommandInterpreterCheck.h - clang-tidy------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CERT_COMMAND_PROCESSOR_CHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_COMMAND_PROCESSOR_CHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/cert/DontModifyStdNamespaceCheck.cpp b/clang-tidy/cert/DontModifyStdNamespaceCheck.cpp
index e5759a52..7b2c7597 100644
--- a/clang-tidy/cert/DontModifyStdNamespaceCheck.cpp
+++ b/clang-tidy/cert/DontModifyStdNamespaceCheck.cpp
@@ -1,9 +1,8 @@
//===--- DontModifyStdNamespaceCheck.cpp - clang-tidy----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cert/DontModifyStdNamespaceCheck.h b/clang-tidy/cert/DontModifyStdNamespaceCheck.h
index 0cc23f79..3e90111a 100644
--- a/clang-tidy/cert/DontModifyStdNamespaceCheck.h
+++ b/clang-tidy/cert/DontModifyStdNamespaceCheck.h
@@ -1,16 +1,15 @@
//===--- DontModifyStdNamespaceCheck.h - clang-tidy--------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CERT_DONT_MODIFY_STD_NAMESPACE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_DONT_MODIFY_STD_NAMESPACE_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/cert/FloatLoopCounter.cpp b/clang-tidy/cert/FloatLoopCounter.cpp
index e92552ed..b6b3b194 100644
--- a/clang-tidy/cert/FloatLoopCounter.cpp
+++ b/clang-tidy/cert/FloatLoopCounter.cpp
@@ -1,9 +1,8 @@
//===--- FloatLoopCounter.cpp - clang-tidy---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cert/FloatLoopCounter.h b/clang-tidy/cert/FloatLoopCounter.h
index c66e44ae..be993c44 100644
--- a/clang-tidy/cert/FloatLoopCounter.h
+++ b/clang-tidy/cert/FloatLoopCounter.h
@@ -1,16 +1,15 @@
//===--- FloatLoopCounter.h - clang-tidy-------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CERT_FLOAT_LOOP_COUNTER_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_FLOAT_LOOP_COUNTER_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/cert/LICENSE.TXT b/clang-tidy/cert/LICENSE.TXT
index d8395ccc..769cc46f 100644
--- a/clang-tidy/cert/LICENSE.TXT
+++ b/clang-tidy/cert/LICENSE.TXT
@@ -1,8 +1,8 @@
------------------------------------------------------------------------------
clang-tidy CERT Files
------------------------------------------------------------------------------
-All clang-tidy files are licensed under the LLVM license with the following
-additions:
+All clang-tidy files are licensed under the same terms as the rest of the LLVM
+project with the following additions:
Any file referencing a CERT Secure Coding guideline:
Please allow this letter to serve as confirmation that open source projects on
diff --git a/clang-tidy/cert/LimitedRandomnessCheck.cpp b/clang-tidy/cert/LimitedRandomnessCheck.cpp
index 3f6f948d..847f05e7 100644
--- a/clang-tidy/cert/LimitedRandomnessCheck.cpp
+++ b/clang-tidy/cert/LimitedRandomnessCheck.cpp
@@ -1,9 +1,8 @@
//===--- LimitedRandomnessCheck.cpp - clang-tidy---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cert/LimitedRandomnessCheck.h b/clang-tidy/cert/LimitedRandomnessCheck.h
index 59d511cb..7ef75e37 100644
--- a/clang-tidy/cert/LimitedRandomnessCheck.h
+++ b/clang-tidy/cert/LimitedRandomnessCheck.h
@@ -1,16 +1,15 @@
//===--- LimitedRandomnessCheck.h - clang-tidy-------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CERT_LIMITED_RANDOMNESS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_LIMITED_RANDOMNESS_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/cert/PostfixOperatorCheck.cpp b/clang-tidy/cert/PostfixOperatorCheck.cpp
index b8e84df9..45c74814 100644
--- a/clang-tidy/cert/PostfixOperatorCheck.cpp
+++ b/clang-tidy/cert/PostfixOperatorCheck.cpp
@@ -1,9 +1,8 @@
//===--- PostfixOperatorCheck.cpp - clang-tidy-----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cert/PostfixOperatorCheck.h b/clang-tidy/cert/PostfixOperatorCheck.h
index 29c2306d..4a6133bb 100644
--- a/clang-tidy/cert/PostfixOperatorCheck.h
+++ b/clang-tidy/cert/PostfixOperatorCheck.h
@@ -1,16 +1,15 @@
//===--- PostfixOperatorCheck.h - clang-tidy---------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CERT_POSTFIX_OPERATOR_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_POSTFIX_OPERATOR_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp b/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp
index 6ae9bd29..3be83cf4 100644
--- a/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp
+++ b/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp
@@ -1,9 +1,8 @@
//===--- ProperlySeededRandomGeneratorCheck.cpp - clang-tidy---------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h b/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h
index ac5507c9..04d1f7bd 100644
--- a/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h
+++ b/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h
@@ -1,16 +1,15 @@
//===--- ProperlySeededRandomGeneratorCheck.h - clang-tidy-------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CERT_PROPERLY_SEEDED_RANDOM_GENERATOR_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_PROPERLY_SEEDED_RANDOM_GENERATOR_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include <string>
namespace clang {
diff --git a/clang-tidy/cert/SetLongJmpCheck.cpp b/clang-tidy/cert/SetLongJmpCheck.cpp
index 89ba5e77..87ac2de5 100644
--- a/clang-tidy/cert/SetLongJmpCheck.cpp
+++ b/clang-tidy/cert/SetLongJmpCheck.cpp
@@ -1,9 +1,8 @@
//===--- SetLongJmpCheck.cpp - clang-tidy----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -20,10 +19,10 @@ namespace clang {
namespace tidy {
namespace cert {
-const char SetLongJmpCheck::DiagWording[] =
+namespace {
+const char DiagWording[] =
"do not call %0; consider using exception handling instead";
-namespace {
class SetJmpMacroCallbacks : public PPCallbacks {
SetLongJmpCheck &Check;
@@ -37,12 +36,14 @@ public:
return;
if (II->getName() == "setjmp")
- Check.diag(Range.getBegin(), Check.DiagWording) << II;
+ Check.diag(Range.getBegin(), DiagWording) << II;
}
};
} // namespace
-void SetLongJmpCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+void SetLongJmpCheck::registerPPCallbacks(const SourceManager &SM,
+ Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) {
// This checker only applies to C++, where exception handling is a superior
// solution to setjmp/longjmp calls.
if (!getLangOpts().CPlusPlus)
@@ -50,8 +51,7 @@ void SetLongJmpCheck::registerPPCallbacks(CompilerInstance &Compiler) {
// Per [headers]p5, setjmp must be exposed as a macro instead of a function,
// despite the allowance in C for setjmp to also be an extern function.
- Compiler.getPreprocessor().addPPCallbacks(
- llvm::make_unique<SetJmpMacroCallbacks>(*this));
+ PP->addPPCallbacks(llvm::make_unique<SetJmpMacroCallbacks>(*this));
}
void SetLongJmpCheck::registerMatchers(MatchFinder *Finder) {
@@ -63,10 +63,10 @@ void SetLongJmpCheck::registerMatchers(MatchFinder *Finder) {
// In case there is an implementation that happens to define setjmp as a
// function instead of a macro, this will also catch use of it. However, we
// are primarily searching for uses of longjmp.
- Finder->addMatcher(callExpr(callee(functionDecl(anyOf(hasName("setjmp"),
- hasName("longjmp")))))
- .bind("expr"),
- this);
+ Finder->addMatcher(
+ callExpr(callee(functionDecl(hasAnyName("setjmp", "longjmp"))))
+ .bind("expr"),
+ this);
}
void SetLongJmpCheck::check(const MatchFinder::MatchResult &Result) {
diff --git a/clang-tidy/cert/SetLongJmpCheck.h b/clang-tidy/cert/SetLongJmpCheck.h
index 1d6c0981..d9cef1b6 100644
--- a/clang-tidy/cert/SetLongJmpCheck.h
+++ b/clang-tidy/cert/SetLongJmpCheck.h
@@ -1,16 +1,15 @@
//===--- SetLongJmpCheck.h - clang-tidy--------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_SETLONGJMPCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SETLONGJMPCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
@@ -26,9 +25,8 @@ public:
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
- void registerPPCallbacks(CompilerInstance &Compiler) override;
-
- static const char DiagWording[];
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
};
} // namespace cert
diff --git a/clang-tidy/cert/StaticObjectExceptionCheck.cpp b/clang-tidy/cert/StaticObjectExceptionCheck.cpp
index 30f86aa9..363c96a2 100644
--- a/clang-tidy/cert/StaticObjectExceptionCheck.cpp
+++ b/clang-tidy/cert/StaticObjectExceptionCheck.cpp
@@ -1,9 +1,8 @@
//===--- StaticObjectExceptionCheck.cpp - clang-tidy-----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cert/StaticObjectExceptionCheck.h b/clang-tidy/cert/StaticObjectExceptionCheck.h
index 463f4336..64a1eb56 100644
--- a/clang-tidy/cert/StaticObjectExceptionCheck.h
+++ b/clang-tidy/cert/StaticObjectExceptionCheck.h
@@ -1,16 +1,15 @@
//===--- StaticObjectExceptionCheck.h - clang-tidy---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CERT_ERR58_CPP_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_ERR58_CPP_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/cert/StrToNumCheck.cpp b/clang-tidy/cert/StrToNumCheck.cpp
index 0b3ea43b..9d26060c 100644
--- a/clang-tidy/cert/StrToNumCheck.cpp
+++ b/clang-tidy/cert/StrToNumCheck.cpp
@@ -1,9 +1,8 @@
-//===--- Err34CCheck.cpp - clang-tidy--------------------------------------===//
+//===-- StrToNumCheck.cpp - clang-tidy ------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cert/StrToNumCheck.h b/clang-tidy/cert/StrToNumCheck.h
index 55f13bea..3ac090b7 100644
--- a/clang-tidy/cert/StrToNumCheck.h
+++ b/clang-tidy/cert/StrToNumCheck.h
@@ -1,16 +1,15 @@
//===--- StrToNumCheck.h - clang-tidy----------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CERT_STRTONUMCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_STRTONUMCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/cert/ThrownExceptionTypeCheck.cpp b/clang-tidy/cert/ThrownExceptionTypeCheck.cpp
index 37fb355f..94784055 100644
--- a/clang-tidy/cert/ThrownExceptionTypeCheck.cpp
+++ b/clang-tidy/cert/ThrownExceptionTypeCheck.cpp
@@ -1,9 +1,8 @@
//===--- ThrownExceptionTypeCheck.cpp - clang-tidy-------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cert/ThrownExceptionTypeCheck.h b/clang-tidy/cert/ThrownExceptionTypeCheck.h
index 2f9d887f..dc37b6a0 100644
--- a/clang-tidy/cert/ThrownExceptionTypeCheck.h
+++ b/clang-tidy/cert/ThrownExceptionTypeCheck.h
@@ -1,16 +1,15 @@
//===--- ThrownExceptionTypeCheck.h - clang-tidy-----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CERT_THROWNEXCEPTIONTYPECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_THROWNEXCEPTIONTYPECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/cert/VariadicFunctionDefCheck.cpp b/clang-tidy/cert/VariadicFunctionDefCheck.cpp
index ea6112a6..8ee67f91 100644
--- a/clang-tidy/cert/VariadicFunctionDefCheck.cpp
+++ b/clang-tidy/cert/VariadicFunctionDefCheck.cpp
@@ -1,9 +1,8 @@
-//===--- VariadicfunctiondefCheck.cpp - clang-tidy-------------------------===//
+//===-- VariadicFunctionDefCheck.cpp - clang-tidy -------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cert/VariadicFunctionDefCheck.h b/clang-tidy/cert/VariadicFunctionDefCheck.h
index e215e8df..24408ace 100644
--- a/clang-tidy/cert/VariadicFunctionDefCheck.h
+++ b/clang-tidy/cert/VariadicFunctionDefCheck.h
@@ -1,16 +1,15 @@
//===--- VariadicFunctionDefCheck.h - clang-tidy-----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CERT_VARIADICFUNCTIONDEF_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_VARIADICFUNCTIONDEF_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/cppcoreguidelines/AvoidGotoCheck.cpp b/clang-tidy/cppcoreguidelines/AvoidGotoCheck.cpp
index eaed15f9..9e7bf636 100644
--- a/clang-tidy/cppcoreguidelines/AvoidGotoCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/AvoidGotoCheck.cpp
@@ -1,9 +1,8 @@
//===--- AvoidGotoCheck.cpp - clang-tidy-----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/AvoidGotoCheck.h b/clang-tidy/cppcoreguidelines/AvoidGotoCheck.h
index cf7dd76f..f27e22c7 100644
--- a/clang-tidy/cppcoreguidelines/AvoidGotoCheck.h
+++ b/clang-tidy/cppcoreguidelines/AvoidGotoCheck.h
@@ -1,9 +1,8 @@
//===--- AvoidGotoCheck.h - clang-tidy---------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
index 0870f1ee..7c7fd1b7 100644
--- a/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
+++ b/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
@@ -1,9 +1,8 @@
-//===--- CppCoreGuidelinesModule.cpp - clang-tidy -------------------------===//
+//===-- CppCoreGuidelinesTidyModule.cpp - clang-tidy ----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -13,6 +12,7 @@
#include "../misc/NonPrivateMemberVariablesInClassesCheck.h"
#include "../misc/UnconventionalAssignOperatorCheck.h"
#include "../modernize/AvoidCArraysCheck.h"
+#include "../modernize/UseOverrideCheck.h"
#include "../readability/MagicNumbersCheck.h"
#include "AvoidGotoCheck.h"
#include "InterfacesGlobalInitCheck.h"
@@ -47,6 +47,8 @@ public:
"cppcoreguidelines-avoid-goto");
CheckFactories.registerCheck<readability::MagicNumbersCheck>(
"cppcoreguidelines-avoid-magic-numbers");
+ CheckFactories.registerCheck<modernize::UseOverrideCheck>(
+ "cppcoreguidelines-explicit-virtual-functions");
CheckFactories.registerCheck<InterfacesGlobalInitCheck>(
"cppcoreguidelines-interfaces-global-init");
CheckFactories.registerCheck<MacroUsageCheck>(
@@ -92,6 +94,9 @@ public:
Opts["cppcoreguidelines-non-private-member-variables-in-classes."
"IgnoreClassesWithAllMemberVariablesBeingPublic"] = "1";
+ Opts["cppcoreguidelines-explicit-virtual-functions."
+ "IgnoreDestructors"] = "1";
+
return Options;
}
};
diff --git a/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp b/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp
index 59993cba..d9c91b23 100644
--- a/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp
@@ -1,9 +1,8 @@
//===--- InterfacesGlobalInitCheck.cpp - clang-tidy------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.h b/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.h
index 13712d11..ecaaaa33 100644
--- a/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.h
+++ b/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.h
@@ -1,9 +1,8 @@
//===--- InterfacesGlobalInitCheck.h - clang-tidy----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp b/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp
index 8b893c7c..ac5ec130 100644
--- a/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp
@@ -1,9 +1,8 @@
//===--- MacroUsageCheck.cpp - clang-tidy----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -37,7 +36,8 @@ public:
IgnoreCommandLineMacros(IgnoreCommandLine) {}
void MacroDefined(const Token &MacroNameTok,
const MacroDirective *MD) override {
- if (MD->getMacroInfo()->isUsedForHeaderGuard() ||
+ if (SM.isWrittenInBuiltinFile(MD->getLocation()) ||
+ MD->getMacroInfo()->isUsedForHeaderGuard() ||
MD->getMacroInfo()->getNumTokens() == 0)
return;
@@ -68,14 +68,14 @@ void MacroUsageCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IgnoreCommandLineMacros", IgnoreCommandLineMacros);
}
-void MacroUsageCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+void MacroUsageCheck::registerPPCallbacks(const SourceManager &SM,
+ Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) {
if (!getLangOpts().CPlusPlus11)
return;
- Compiler.getPreprocessor().addPPCallbacks(
- llvm::make_unique<MacroUsageCallbacks>(this, Compiler.getSourceManager(),
- AllowedRegexp, CheckCapsOnly,
- IgnoreCommandLineMacros));
+ PP->addPPCallbacks(llvm::make_unique<MacroUsageCallbacks>(
+ this, SM, AllowedRegexp, CheckCapsOnly, IgnoreCommandLineMacros));
}
void MacroUsageCheck::warnMacro(const MacroDirective *MD, StringRef MacroName) {
diff --git a/clang-tidy/cppcoreguidelines/MacroUsageCheck.h b/clang-tidy/cppcoreguidelines/MacroUsageCheck.h
index a39d55a2..978edd8e 100644
--- a/clang-tidy/cppcoreguidelines/MacroUsageCheck.h
+++ b/clang-tidy/cppcoreguidelines/MacroUsageCheck.h
@@ -1,9 +1,8 @@
//===--- MacroUsageCheck.h - clang-tidy--------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -31,7 +30,8 @@ public:
CheckCapsOnly(Options.get("CheckCapsOnly", 0)),
IgnoreCommandLineMacros(Options.get("IgnoreCommandLineMacros", 1)) {}
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
void warnMacro(const MacroDirective *MD, StringRef MacroName);
void warnNaming(const MacroDirective *MD, StringRef MacroName);
diff --git a/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp b/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
index 132d84ad..57311166 100644
--- a/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
@@ -1,9 +1,8 @@
//===--- NarrowingConversionsCheck.cpp - clang-tidy------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h b/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h
index 3e72248f..cc598edd 100644
--- a/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h
+++ b/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h
@@ -1,9 +1,8 @@
//===--- NarrowingConversionsCheck.h - clang-tidy----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp b/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp
index f9cec51e..b78e7d17 100644
--- a/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp
@@ -1,9 +1,8 @@
//===--- NoMallocCheck.cpp - clang-tidy------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/NoMallocCheck.h b/clang-tidy/cppcoreguidelines/NoMallocCheck.h
index 4cec8a83..023202ae 100644
--- a/clang-tidy/cppcoreguidelines/NoMallocCheck.h
+++ b/clang-tidy/cppcoreguidelines/NoMallocCheck.h
@@ -1,9 +1,8 @@
//===--- NoMallocCheck.h - clang-tidy----------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp b/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp
index 0b7e0a3d..11d1e3eb 100644
--- a/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp
@@ -1,9 +1,8 @@
//===--- OwningMemoryCheck.cpp - clang-tidy--------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/OwningMemoryCheck.h b/clang-tidy/cppcoreguidelines/OwningMemoryCheck.h
index e68e4c09..0498eea9 100644
--- a/clang-tidy/cppcoreguidelines/OwningMemoryCheck.h
+++ b/clang-tidy/cppcoreguidelines/OwningMemoryCheck.h
@@ -1,9 +1,8 @@
//===--- OwningMemoryCheck.h - clang-tidy------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp b/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp
index af41386d..6939ec9b 100644
--- a/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp
@@ -1,9 +1,8 @@
//===--- ProBoundsArrayToPointerDecayCheck.cpp - clang-tidy----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.h b/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.h
index 0afffb64..28099654 100644
--- a/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.h
+++ b/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.h
@@ -1,9 +1,8 @@
//===--- ProBoundsArrayToPointerDecayCheck.h - clang-tidy--------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp b/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp
index 9fbb1219..28fccfdb 100644
--- a/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp
@@ -1,9 +1,8 @@
//===--- ProBoundsConstantArrayIndexCheck.cpp - clang-tidy-----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -32,13 +31,13 @@ void ProBoundsConstantArrayIndexCheck::storeOptions(
}
void ProBoundsConstantArrayIndexCheck::registerPPCallbacks(
- CompilerInstance &Compiler) {
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
if (!getLangOpts().CPlusPlus)
return;
- Inserter.reset(new utils::IncludeInserter(
- Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle));
- Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+ Inserter = llvm::make_unique<utils::IncludeInserter>(SM, getLangOpts(),
+ IncludeStyle);
+ PP->addPPCallbacks(Inserter->CreatePPCallbacks());
}
void ProBoundsConstantArrayIndexCheck::registerMatchers(MatchFinder *Finder) {
diff --git a/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h b/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h
index 28b24a6b..c75795ac 100644
--- a/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h
+++ b/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h
@@ -1,9 +1,8 @@
//===--- ProBoundsConstantArrayIndexCheck.h - clang-tidy---------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -29,7 +28,8 @@ class ProBoundsConstantArrayIndexCheck : public ClangTidyCheck {
public:
ProBoundsConstantArrayIndexCheck(StringRef Name, ClangTidyContext *Context);
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
diff --git a/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp b/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp
index dfbb51be..384c8be9 100644
--- a/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp
@@ -1,9 +1,8 @@
//===--- ProBoundsPointerArithmeticCheck.cpp - clang-tidy------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h b/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h
index 5ecf93cc..ab43c789 100644
--- a/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h
+++ b/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h
@@ -1,9 +1,8 @@
//===--- ProBoundsPointerArithmeticCheck.h - clang-tidy----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.cpp b/clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.cpp
index 4b6fb420..419c6765 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.cpp
@@ -1,9 +1,8 @@
//===--- ProTypeConstCastCheck.cpp - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.h b/clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.h
index 92a3a1b5..2fbfdd3b 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.h
+++ b/clang-tidy/cppcoreguidelines/ProTypeConstCastCheck.h
@@ -1,9 +1,8 @@
//===--- ProTypeConstCastCheck.h - clang-tidy--------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp b/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp
index bc2418d6..18fad579 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp
@@ -1,9 +1,8 @@
//===--- ProTypeCstyleCastCheck.cpp - clang-tidy---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.h b/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.h
index c08b883c..aebc57ec 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.h
+++ b/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.h
@@ -1,9 +1,8 @@
//===--- ProTypeCstyleCastCheck.h - clang-tidy-------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp b/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
index 82f50a1a..c6cfe5ec 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
@@ -1,9 +1,8 @@
//===--- ProTypeMemberInitCheck.cpp - clang-tidy---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h b/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h
index 20d3f60f..807acfe3 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h
+++ b/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h
@@ -1,9 +1,8 @@
//===--- ProTypeMemberInitCheck.h - clang-tidy-------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.cpp b/clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.cpp
index e56e6388..4c4c6ce1 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.cpp
@@ -1,9 +1,8 @@
//===--- ProTypeReinterpretCastCheck.cpp - clang-tidy----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.h b/clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.h
index 9610546f..5afd461f 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.h
+++ b/clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.h
@@ -1,9 +1,8 @@
//===--- ProTypeReinterpretCast.h - clang-tidy------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.cpp b/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.cpp
index f43e4fa1..59503ba6 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.cpp
@@ -1,9 +1,8 @@
//===--- ProTypeStaticCastDowncastCheck.cpp - clang-tidy-------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.h b/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.h
index b6d76a69..e7c45aec 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.h
+++ b/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.h
@@ -1,9 +1,8 @@
//===--- ProTypeStaticCastDowncastCheck.h - clang-tidy-----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.cpp b/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.cpp
index 09752f69..e50dd4e6 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.cpp
@@ -1,9 +1,8 @@
//===--- ProTypeUnionAccessCheck.cpp - clang-tidy--------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.h b/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.h
index fc7dd671..70080f43 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.h
+++ b/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.h
@@ -1,9 +1,8 @@
//===--- ProTypeUnionAccessCheck.h - clang-tidy------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp b/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp
index 56227b23..650e668d 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp
@@ -1,9 +1,8 @@
//===--- ProTypeVarargCheck.cpp - clang-tidy-------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.h b/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.h
index 558c8568..98acc5ad 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.h
+++ b/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.h
@@ -1,9 +1,8 @@
//===--- ProTypeVarargCheck.h - clang-tidy--------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/SlicingCheck.cpp b/clang-tidy/cppcoreguidelines/SlicingCheck.cpp
index 53b2f728..8ad47505 100644
--- a/clang-tidy/cppcoreguidelines/SlicingCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/SlicingCheck.cpp
@@ -1,9 +1,8 @@
//===--- SlicingCheck.cpp - clang-tidy-------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/SlicingCheck.h b/clang-tidy/cppcoreguidelines/SlicingCheck.h
index 9ee91bcd..a2322a9f 100644
--- a/clang-tidy/cppcoreguidelines/SlicingCheck.h
+++ b/clang-tidy/cppcoreguidelines/SlicingCheck.h
@@ -1,9 +1,8 @@
//===--- SlicingCheck.h - clang-tidy-----------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp b/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp
index df3c2796..8f95e501 100644
--- a/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp
@@ -1,9 +1,8 @@
//===--- SpecialMemberFunctionsCheck.cpp - clang-tidy----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h b/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h
index 8ab0c92b..71caa4da 100644
--- a/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h
+++ b/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h
@@ -1,9 +1,8 @@
//===--- SpecialMemberFunctionsCheck.h - clang-tidy--------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/fuchsia/DefaultArgumentsCheck.cpp b/clang-tidy/fuchsia/DefaultArgumentsCheck.cpp
index e6a67e0a..7f83ac67 100644
--- a/clang-tidy/fuchsia/DefaultArgumentsCheck.cpp
+++ b/clang-tidy/fuchsia/DefaultArgumentsCheck.cpp
@@ -1,9 +1,8 @@
//===--- DefaultArgumentsCheck.cpp - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/fuchsia/DefaultArgumentsCheck.h b/clang-tidy/fuchsia/DefaultArgumentsCheck.h
index f54fd964..8d26c35a 100644
--- a/clang-tidy/fuchsia/DefaultArgumentsCheck.h
+++ b/clang-tidy/fuchsia/DefaultArgumentsCheck.h
@@ -1,16 +1,15 @@
//===--- DefaultArgumentsCheck.h - clang-tidy--------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_FUCHSIA_DEFAULT_ARGUMENTS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_DEFAULT_ARGUMENTS_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/fuchsia/FuchsiaTidyModule.cpp b/clang-tidy/fuchsia/FuchsiaTidyModule.cpp
index 0d3bbfe7..034a30ea 100644
--- a/clang-tidy/fuchsia/FuchsiaTidyModule.cpp
+++ b/clang-tidy/fuchsia/FuchsiaTidyModule.cpp
@@ -1,9 +1,8 @@
//===--- FuchsiaTidyModule.cpp - clang-tidy--------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp b/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp
index a49c952f..a5f9d6ed 100644
--- a/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp
+++ b/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp
@@ -1,9 +1,8 @@
//===--- MultipleInheritanceCheck.cpp - clang-tidy-------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/fuchsia/MultipleInheritanceCheck.h b/clang-tidy/fuchsia/MultipleInheritanceCheck.h
index 6250e3ec..c79050a0 100644
--- a/clang-tidy/fuchsia/MultipleInheritanceCheck.h
+++ b/clang-tidy/fuchsia/MultipleInheritanceCheck.h
@@ -1,16 +1,15 @@
//===--- MultipleInheritanceCheck.h - clang-tidy-----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_FUCHSIA_MULTIPLE_INHERITANCE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_MULTIPLE_INHERITANCE_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/fuchsia/OverloadedOperatorCheck.cpp b/clang-tidy/fuchsia/OverloadedOperatorCheck.cpp
index 4aab1e01..fb77efc3 100644
--- a/clang-tidy/fuchsia/OverloadedOperatorCheck.cpp
+++ b/clang-tidy/fuchsia/OverloadedOperatorCheck.cpp
@@ -1,9 +1,8 @@
//===--- OverloadedOperatorCheck.cpp - clang-tidy--------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/fuchsia/OverloadedOperatorCheck.h b/clang-tidy/fuchsia/OverloadedOperatorCheck.h
index a22e5ae5..122d5dcf 100644
--- a/clang-tidy/fuchsia/OverloadedOperatorCheck.h
+++ b/clang-tidy/fuchsia/OverloadedOperatorCheck.h
@@ -1,16 +1,15 @@
//===--- OverloadedOperatorCheck.h - clang-tidy------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_FUCHSIA_OVERLOADED_OPERATOR_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_OVERLOADED_OPERATOR_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/fuchsia/RestrictSystemIncludesCheck.cpp b/clang-tidy/fuchsia/RestrictSystemIncludesCheck.cpp
index 4817e904..08981fce 100644
--- a/clang-tidy/fuchsia/RestrictSystemIncludesCheck.cpp
+++ b/clang-tidy/fuchsia/RestrictSystemIncludesCheck.cpp
@@ -1,9 +1,8 @@
//===--- RestrictSystemIncludesCheck.cpp - clang-tidy----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -24,7 +23,7 @@ namespace fuchsia {
class RestrictedIncludesPPCallbacks : public PPCallbacks {
public:
explicit RestrictedIncludesPPCallbacks(RestrictSystemIncludesCheck &Check,
- SourceManager &SM)
+ const SourceManager &SM)
: Check(Check), SM(SM) {}
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
@@ -54,7 +53,7 @@ private:
llvm::SmallDenseMap<FileID, FileIncludes> IncludeDirectives;
RestrictSystemIncludesCheck &Check;
- SourceManager &SM;
+ const SourceManager &SM;
};
void RestrictedIncludesPPCallbacks::InclusionDirective(
@@ -102,10 +101,9 @@ void RestrictedIncludesPPCallbacks::EndOfMainFile() {
}
void RestrictSystemIncludesCheck::registerPPCallbacks(
- CompilerInstance &Compiler) {
- Compiler.getPreprocessor().addPPCallbacks(
- llvm::make_unique<RestrictedIncludesPPCallbacks>(
- *this, Compiler.getSourceManager()));
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ PP->addPPCallbacks(
+ llvm::make_unique<RestrictedIncludesPPCallbacks>(*this, SM));
}
void RestrictSystemIncludesCheck::storeOptions(
diff --git a/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h b/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h
index d4e5ac1e..0539b73b 100644
--- a/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h
+++ b/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h
@@ -1,16 +1,15 @@
//===--- RestrictSystemIncludesCheck.h - clang-tidy---------- ----*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_FUCHSIA_RESTRICTINCLUDESSCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_RESTRICTINCLUDESSCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "../ClangTidyDiagnosticConsumer.h"
#include "../utils/OptionsUtils.h"
@@ -30,7 +29,8 @@ public:
AllowedIncludes(Options.get("Includes", "*")),
AllowedIncludesGlobList(AllowedIncludes) {}
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
bool contains(StringRef FileName) {
return AllowedIncludesGlobList.contains(FileName);
diff --git a/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp b/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp
index c8ffd2e5..cd6de922 100644
--- a/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp
+++ b/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp
@@ -1,9 +1,8 @@
//===--- StaticallyConstructedObjectsCheck.cpp - clang-tidy----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.h b/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.h
index 6df9b1c2..adf48aaa 100644
--- a/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.h
+++ b/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.h
@@ -1,16 +1,15 @@
//===--- StaticallyConstructedObjectsCheck.h - clang-tidy--------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_FUCHSIA_STATICALLY_CONSTRUCTED_OBJECTS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_STATICALLY_CONSTRUCTED_OBJECTS_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/fuchsia/TrailingReturnCheck.cpp b/clang-tidy/fuchsia/TrailingReturnCheck.cpp
index 71dc4724..a1da0db6 100644
--- a/clang-tidy/fuchsia/TrailingReturnCheck.cpp
+++ b/clang-tidy/fuchsia/TrailingReturnCheck.cpp
@@ -1,9 +1,8 @@
//===--- TrailingReturnCheck.cpp - clang-tidy------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/fuchsia/TrailingReturnCheck.h b/clang-tidy/fuchsia/TrailingReturnCheck.h
index 4a16c4e4..e0aab1f4 100644
--- a/clang-tidy/fuchsia/TrailingReturnCheck.h
+++ b/clang-tidy/fuchsia/TrailingReturnCheck.h
@@ -1,16 +1,15 @@
//===--- TrailingReturnCheck.h - clang-tidy----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_FUCHSIA_TRAILING_RETURN_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_TRAILING_RETURN_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/fuchsia/VirtualInheritanceCheck.cpp b/clang-tidy/fuchsia/VirtualInheritanceCheck.cpp
index 82f44103..54a4d73c 100644
--- a/clang-tidy/fuchsia/VirtualInheritanceCheck.cpp
+++ b/clang-tidy/fuchsia/VirtualInheritanceCheck.cpp
@@ -1,9 +1,8 @@
//===--- VirtualInheritanceCheck.cpp - clang-tidy--------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/fuchsia/VirtualInheritanceCheck.h b/clang-tidy/fuchsia/VirtualInheritanceCheck.h
index b2c84c41..88ff0dc9 100644
--- a/clang-tidy/fuchsia/VirtualInheritanceCheck.h
+++ b/clang-tidy/fuchsia/VirtualInheritanceCheck.h
@@ -1,16 +1,15 @@
//===--- VirtualInheritanceCheck.h - clang-tidy------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_FUCHSIA_VIRTUAL_INHERITANCE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_VIRTUAL_INHERITANCE_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/google/AvoidCStyleCastsCheck.cpp b/clang-tidy/google/AvoidCStyleCastsCheck.cpp
index d6ea7e00..6a16d884 100644
--- a/clang-tidy/google/AvoidCStyleCastsCheck.cpp
+++ b/clang-tidy/google/AvoidCStyleCastsCheck.cpp
@@ -1,9 +1,8 @@
//===--- AvoidCStyleCastsCheck.cpp - clang-tidy -----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/AvoidCStyleCastsCheck.h b/clang-tidy/google/AvoidCStyleCastsCheck.h
index ea7e34ca..72f96d09 100644
--- a/clang-tidy/google/AvoidCStyleCastsCheck.h
+++ b/clang-tidy/google/AvoidCStyleCastsCheck.h
@@ -1,16 +1,15 @@
//===--- AvoidCStyleCastsCheck.h - clang-tidy -------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_GOOGLE_AVOIDCSTYLECASTSCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDCSTYLECASTSCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp b/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp
index ad74181b..bfc34672 100644
--- a/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp
+++ b/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp
@@ -1,9 +1,8 @@
//===--- AvoidThrowingObjCExceptionCheck.cpp - clang-tidy------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/AvoidThrowingObjCExceptionCheck.h b/clang-tidy/google/AvoidThrowingObjCExceptionCheck.h
index 9498226d..692a37f1 100644
--- a/clang-tidy/google/AvoidThrowingObjCExceptionCheck.h
+++ b/clang-tidy/google/AvoidThrowingObjCExceptionCheck.h
@@ -1,16 +1,15 @@
//===--- AvoidThrowingObjCExceptionCheck.h - clang-tidy----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_GOOGLE_OBJC_AVOID_THROWING_EXCEPTION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_AVOID_THROWING_EXCEPTION_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp b/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp
new file mode 100644
index 00000000..d279343e
--- /dev/null
+++ b/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp
@@ -0,0 +1,88 @@
+//===--- AvoidUnderscoreInGoogletestNameCheck.cpp - 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
+//
+//===----------------------------------------------------------------------===//
+
+#include <string>
+
+#include "AvoidUnderscoreInGoogletestNameCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/MacroArgs.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace readability {
+
+constexpr llvm::StringLiteral kDisabledTestPrefix = "DISABLED_";
+
+// Determines whether the macro is a Googletest test macro.
+static bool isGoogletestTestMacro(StringRef MacroName) {
+ static const llvm::StringSet<> MacroNames = {"TEST", "TEST_F", "TEST_P",
+ "TYPED_TEST", "TYPED_TEST_P"};
+ return MacroNames.find(MacroName) != MacroNames.end();
+}
+
+namespace {
+
+class AvoidUnderscoreInGoogletestNameCallback : public PPCallbacks {
+public:
+ AvoidUnderscoreInGoogletestNameCallback(
+ Preprocessor *PP, AvoidUnderscoreInGoogletestNameCheck *Check)
+ : PP(PP), Check(Check) {}
+
+ // Detects expansions of the TEST, TEST_F, TEST_P, TYPED_TEST, TYPED_TEST_P
+ // macros and checks that their arguments do not have any underscores.
+ void MacroExpands(const Token &MacroNameToken,
+ const MacroDefinition &MacroDefinition, SourceRange Range,
+ const MacroArgs *Args) override {
+ IdentifierInfo *NameIdentifierInfo = MacroNameToken.getIdentifierInfo();
+ if (!NameIdentifierInfo)
+ return;
+ StringRef MacroName = NameIdentifierInfo->getName();
+ if (!isGoogletestTestMacro(MacroName) || !Args ||
+ Args->getNumMacroArguments() < 2)
+ return;
+ const Token *TestCaseNameToken = Args->getUnexpArgument(0);
+ const Token *TestNameToken = Args->getUnexpArgument(1);
+ if (!TestCaseNameToken || !TestNameToken)
+ return;
+ std::string TestCaseName = PP->getSpelling(*TestCaseNameToken);
+ if (TestCaseName.find('_') != std::string::npos)
+ Check->diag(TestCaseNameToken->getLocation(),
+ "avoid using \"_\" in test case name \"%0\" according to "
+ "Googletest FAQ")
+ << TestCaseName;
+
+ std::string TestNameMaybeDisabled = PP->getSpelling(*TestNameToken);
+ StringRef TestName = TestNameMaybeDisabled;
+ TestName.consume_front(kDisabledTestPrefix);
+ if (TestName.contains('_'))
+ Check->diag(TestNameToken->getLocation(),
+ "avoid using \"_\" in test name \"%0\" according to "
+ "Googletest FAQ")
+ << TestName;
+ }
+
+private:
+ Preprocessor *PP;
+ AvoidUnderscoreInGoogletestNameCheck *Check;
+};
+
+} // namespace
+
+void AvoidUnderscoreInGoogletestNameCheck::registerPPCallbacks(
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ PP->addPPCallbacks(
+ llvm::make_unique<AvoidUnderscoreInGoogletestNameCallback>(PP, this));
+}
+
+} // namespace readability
+} // namespace google
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h b/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h
new file mode 100644
index 00000000..6a690f60
--- /dev/null
+++ b/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h
@@ -0,0 +1,34 @@
+//===--- AvoidUnderscoreInGoogletestNameCheck.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_GOOGLE_AVOIDUNDERSCOREINGOOGLETESTNAMECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDUNDERSCOREINGOOGLETESTNAMECHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace readability {
+
+// Check for underscores in the names of googletest tests, per
+// https://github.com/google/googletest/blob/master/googletest/docs/faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore
+class AvoidUnderscoreInGoogletestNameCheck : public ClangTidyCheck {
+public:
+ using ClangTidyCheck::ClangTidyCheck;
+
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
+};
+
+} // namespace readability
+} // namespace google
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDUNDERSCOREINGOOGLETESTNAMECHECK_H
diff --git a/clang-tidy/google/CMakeLists.txt b/clang-tidy/google/CMakeLists.txt
index 2ded4aab..4d0a326f 100644
--- a/clang-tidy/google/CMakeLists.txt
+++ b/clang-tidy/google/CMakeLists.txt
@@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyGoogleModule
AvoidCStyleCastsCheck.cpp
AvoidThrowingObjCExceptionCheck.cpp
+ AvoidUnderscoreInGoogletestNameCheck.cpp
DefaultArgumentsCheck.cpp
ExplicitConstructorCheck.cpp
ExplicitMakePairCheck.cpp
diff --git a/clang-tidy/google/DefaultArgumentsCheck.cpp b/clang-tidy/google/DefaultArgumentsCheck.cpp
index ccbd870a..1ec2924d 100644
--- a/clang-tidy/google/DefaultArgumentsCheck.cpp
+++ b/clang-tidy/google/DefaultArgumentsCheck.cpp
@@ -1,9 +1,8 @@
//===--- DefaultArgumentsCheck.cpp - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/DefaultArgumentsCheck.h b/clang-tidy/google/DefaultArgumentsCheck.h
index 1457a093..574965dc 100644
--- a/clang-tidy/google/DefaultArgumentsCheck.h
+++ b/clang-tidy/google/DefaultArgumentsCheck.h
@@ -1,16 +1,15 @@
//===--- DefaultArgumentsCheck.h - clang-tidy--------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_GOOGLE_DEFAULT_ARGUMENTS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_DEFAULT_ARGUMENTS_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/google/ExplicitConstructorCheck.cpp b/clang-tidy/google/ExplicitConstructorCheck.cpp
index 778ce890..69731c26 100644
--- a/clang-tidy/google/ExplicitConstructorCheck.cpp
+++ b/clang-tidy/google/ExplicitConstructorCheck.cpp
@@ -1,9 +1,8 @@
//===--- ExplicitConstructorCheck.cpp - clang-tidy ------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/ExplicitConstructorCheck.h b/clang-tidy/google/ExplicitConstructorCheck.h
index 81e66790..b6a76f63 100644
--- a/clang-tidy/google/ExplicitConstructorCheck.h
+++ b/clang-tidy/google/ExplicitConstructorCheck.h
@@ -1,16 +1,15 @@
//===--- ExplicitConstructorCheck.h - clang-tidy ----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_GOOGLE_EXPLICITCONSTRUCTORCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_EXPLICITCONSTRUCTORCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/google/ExplicitMakePairCheck.cpp b/clang-tidy/google/ExplicitMakePairCheck.cpp
index 7e827514..51df3a8f 100644
--- a/clang-tidy/google/ExplicitMakePairCheck.cpp
+++ b/clang-tidy/google/ExplicitMakePairCheck.cpp
@@ -1,9 +1,8 @@
//===--- ExplicitMakePairCheck.cpp - clang-tidy -----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/ExplicitMakePairCheck.h b/clang-tidy/google/ExplicitMakePairCheck.h
index a29825f3..8029384f 100644
--- a/clang-tidy/google/ExplicitMakePairCheck.h
+++ b/clang-tidy/google/ExplicitMakePairCheck.h
@@ -1,16 +1,15 @@
//===--- ExplicitMakePairCheck.h - clang-tidy -------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_GOOGLE_EXPLICITMAKEPAIRCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_EXPLICITMAKEPAIRCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/google/FunctionNamingCheck.cpp b/clang-tidy/google/FunctionNamingCheck.cpp
index f7064708..8096d65d 100644
--- a/clang-tidy/google/FunctionNamingCheck.cpp
+++ b/clang-tidy/google/FunctionNamingCheck.cpp
@@ -1,9 +1,8 @@
//===--- FunctionNamingCheck.cpp - clang-tidy -----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -94,12 +93,16 @@ void FunctionNamingCheck::registerMatchers(MatchFinder *Finder) {
if (!getLangOpts().ObjC)
return;
- // Match function declarations that are not in system headers and are not
- // main.
+ // Enforce Objective-C function naming conventions on all functions except:
+ // • Functions defined in system headers.
+ // • C++ member functions.
+ // • Namespaced functions.
+ // • Implicitly defined functions.
+ // • The main function.
Finder->addMatcher(
functionDecl(
unless(anyOf(isExpansionInSystemHeader(), cxxMethodDecl(),
- hasAncestor(namespaceDecl()), isMain(),
+ hasAncestor(namespaceDecl()), isMain(), isImplicit(),
matchesName(validFunctionNameRegex(true)),
allOf(isStaticStorageClass(),
matchesName(validFunctionNameRegex(false))))))
diff --git a/clang-tidy/google/FunctionNamingCheck.h b/clang-tidy/google/FunctionNamingCheck.h
index 46499e90..c45f87d5 100644
--- a/clang-tidy/google/FunctionNamingCheck.h
+++ b/clang-tidy/google/FunctionNamingCheck.h
@@ -1,16 +1,15 @@
//===--- FunctionNamingCheck.h - clang-tidy ---------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_GOOGLE_OBJC_FUNCTION_NAMING_CHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_FUNCTION_NAMING_CHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "llvm/ADT/StringRef.h"
namespace clang {
diff --git a/clang-tidy/google/GlobalNamesInHeadersCheck.cpp b/clang-tidy/google/GlobalNamesInHeadersCheck.cpp
index 9f03f7d5..a83e636a 100644
--- a/clang-tidy/google/GlobalNamesInHeadersCheck.cpp
+++ b/clang-tidy/google/GlobalNamesInHeadersCheck.cpp
@@ -1,9 +1,8 @@
//===--- GlobalNamesInHeadersCheck.cpp - clang-tidy -----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/GlobalNamesInHeadersCheck.h b/clang-tidy/google/GlobalNamesInHeadersCheck.h
index 79a6e285..730ef60c 100644
--- a/clang-tidy/google/GlobalNamesInHeadersCheck.h
+++ b/clang-tidy/google/GlobalNamesInHeadersCheck.h
@@ -1,16 +1,15 @@
//===--- GlobalNamesInHeadersCheck.h - clang-tidy ---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_GOOGLE_GLOBALNAMESINHEADERSCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_GLOBALNAMESINHEADERSCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "../utils/HeaderFileExtensionsUtils.h"
namespace clang {
diff --git a/clang-tidy/google/GlobalVariableDeclarationCheck.cpp b/clang-tidy/google/GlobalVariableDeclarationCheck.cpp
index 63885237..ce833906 100644
--- a/clang-tidy/google/GlobalVariableDeclarationCheck.cpp
+++ b/clang-tidy/google/GlobalVariableDeclarationCheck.cpp
@@ -1,9 +1,8 @@
//===--- GlobalVariableDeclarationCheck.cpp - clang-tidy-------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -80,12 +79,16 @@ void GlobalVariableDeclarationCheck::registerMatchers(MatchFinder *Finder) {
void GlobalVariableDeclarationCheck::check(
const MatchFinder::MatchResult &Result) {
if (const auto *Decl = Result.Nodes.getNodeAs<VarDecl>("global_var")) {
+ if (Decl->isStaticDataMember())
+ return;
diag(Decl->getLocation(),
"non-const global variable '%0' must have a name which starts with "
"'g[A-Z]'")
<< Decl->getName() << generateFixItHint(Decl, false);
}
if (const auto *Decl = Result.Nodes.getNodeAs<VarDecl>("global_const")) {
+ if (Decl->isStaticDataMember())
+ return;
diag(Decl->getLocation(),
"const global variable '%0' must have a name which starts with "
"an appropriate prefix")
diff --git a/clang-tidy/google/GlobalVariableDeclarationCheck.h b/clang-tidy/google/GlobalVariableDeclarationCheck.h
index ed0352bb..9ea0136d 100644
--- a/clang-tidy/google/GlobalVariableDeclarationCheck.h
+++ b/clang-tidy/google/GlobalVariableDeclarationCheck.h
@@ -1,16 +1,15 @@
//===--- GlobalVariableDeclarationCheck.h - clang-tidy-----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_GOOGLE_OBJC_GLOBAL_VARIABLE_DECLARATION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_GLOBAL_VARIABLE_DECLARATION_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/google/GoogleTidyModule.cpp b/clang-tidy/google/GoogleTidyModule.cpp
index 7996cfc8..c2a9ec5e 100644
--- a/clang-tidy/google/GoogleTidyModule.cpp
+++ b/clang-tidy/google/GoogleTidyModule.cpp
@@ -1,9 +1,8 @@
//===--- GoogleTidyModule.cpp - clang-tidy --------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -15,6 +14,7 @@
#include "../readability/NamespaceCommentCheck.h"
#include "AvoidCStyleCastsCheck.h"
#include "AvoidThrowingObjCExceptionCheck.h"
+#include "AvoidUnderscoreInGoogletestNameCheck.h"
#include "DefaultArgumentsCheck.h"
#include "ExplicitConstructorCheck.h"
#include "ExplicitMakePairCheck.h"
@@ -61,6 +61,9 @@ class GoogleModule : public ClangTidyModule {
"google-runtime-operator");
CheckFactories.registerCheck<runtime::NonConstReferences>(
"google-runtime-references");
+ CheckFactories
+ .registerCheck<readability::AvoidUnderscoreInGoogletestNameCheck>(
+ "google-readability-avoid-underscore-in-googletest-name");
CheckFactories.registerCheck<readability::AvoidCStyleCastsCheck>(
"google-readability-casting");
CheckFactories.registerCheck<readability::TodoCommentCheck>(
diff --git a/clang-tidy/google/IntegerTypesCheck.cpp b/clang-tidy/google/IntegerTypesCheck.cpp
index 07ee081a..fb6fd3be 100644
--- a/clang-tidy/google/IntegerTypesCheck.cpp
+++ b/clang-tidy/google/IntegerTypesCheck.cpp
@@ -1,9 +1,8 @@
//===--- IntegerTypesCheck.cpp - clang-tidy -------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -55,7 +54,9 @@ void IntegerTypesCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
void IntegerTypesCheck::registerMatchers(MatchFinder *Finder) {
// Find all TypeLocs. The relevant Style Guide rule only applies to C++.
- if (!getLangOpts().CPlusPlus)
+ // This check is also not applied in Objective-C++ sources as Objective-C
+ // often uses built-in integer types other than `int`.
+ if (!getLangOpts().CPlusPlus || getLangOpts().ObjC)
return;
// Match any integer types, unless they are passed to a printf-based API:
//
diff --git a/clang-tidy/google/IntegerTypesCheck.h b/clang-tidy/google/IntegerTypesCheck.h
index 8d8f9038..518e31ef 100644
--- a/clang-tidy/google/IntegerTypesCheck.h
+++ b/clang-tidy/google/IntegerTypesCheck.h
@@ -1,16 +1,15 @@
//===--- IntegerTypesCheck.h - clang-tidy -----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_GOOGLE_INTEGERTYPESCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_INTEGERTYPESCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include <memory>
diff --git a/clang-tidy/google/NonConstReferences.cpp b/clang-tidy/google/NonConstReferences.cpp
index 856bc5bc..6e0fcfe5 100644
--- a/clang-tidy/google/NonConstReferences.cpp
+++ b/clang-tidy/google/NonConstReferences.cpp
@@ -1,9 +1,8 @@
//===--- NonConstReferences.cpp - clang-tidy --------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/NonConstReferences.h b/clang-tidy/google/NonConstReferences.h
index a665813f..548448b1 100644
--- a/clang-tidy/google/NonConstReferences.h
+++ b/clang-tidy/google/NonConstReferences.h
@@ -1,16 +1,15 @@
//===--- NonConstReferences.h - clang-tidy ----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_GOOGLE_NON_CONST_REFERENCES_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_NON_CONST_REFERENCES_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/google/OverloadedUnaryAndCheck.cpp b/clang-tidy/google/OverloadedUnaryAndCheck.cpp
index 57702c76..1d4d1049 100644
--- a/clang-tidy/google/OverloadedUnaryAndCheck.cpp
+++ b/clang-tidy/google/OverloadedUnaryAndCheck.cpp
@@ -1,9 +1,8 @@
//===--- OverloadedUnaryAndCheck.cpp - clang-tidy ---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/OverloadedUnaryAndCheck.h b/clang-tidy/google/OverloadedUnaryAndCheck.h
index 5492eba2..bafbd29a 100644
--- a/clang-tidy/google/OverloadedUnaryAndCheck.h
+++ b/clang-tidy/google/OverloadedUnaryAndCheck.h
@@ -1,16 +1,15 @@
//===--- OverloadedUnaryAndCheck.h - clang-tidy -----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_GOOGLE_OVERLOADEDUNARYANDCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OVERLOADEDUNARYANDCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/google/TodoCommentCheck.cpp b/clang-tidy/google/TodoCommentCheck.cpp
index f1c79ce6..40d65a65 100644
--- a/clang-tidy/google/TodoCommentCheck.cpp
+++ b/clang-tidy/google/TodoCommentCheck.cpp
@@ -1,9 +1,8 @@
//===--- TodoCommentCheck.cpp - clang-tidy --------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -56,8 +55,10 @@ TodoCommentCheck::TodoCommentCheck(StringRef Name, ClangTidyContext *Context)
Handler(llvm::make_unique<TodoCommentHandler>(
*this, Context->getOptions().User)) {}
-void TodoCommentCheck::registerPPCallbacks(CompilerInstance &Compiler) {
- Compiler.getPreprocessor().addCommentHandler(Handler.get());
+void TodoCommentCheck::registerPPCallbacks(const SourceManager &SM,
+ Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) {
+ PP->addCommentHandler(Handler.get());
}
} // namespace readability
diff --git a/clang-tidy/google/TodoCommentCheck.h b/clang-tidy/google/TodoCommentCheck.h
index dbdc3668..d1343b74 100644
--- a/clang-tidy/google/TodoCommentCheck.h
+++ b/clang-tidy/google/TodoCommentCheck.h
@@ -1,16 +1,15 @@
//===--- TodoCommentCheck.h - clang-tidy ------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_GOOGLE_TODOCOMMENTCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_TODOCOMMENTCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
@@ -23,7 +22,8 @@ namespace readability {
class TodoCommentCheck : public ClangTidyCheck {
public:
TodoCommentCheck(StringRef Name, ClangTidyContext *Context);
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
private:
class TodoCommentHandler;
diff --git a/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp b/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp
index 94e1729b..cdb6149c 100644
--- a/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp
+++ b/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp
@@ -1,9 +1,8 @@
//===--- UnnamedNamespaceInHeaderCheck.cpp - clang-tidy ---------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h b/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h
index 4d310f57..517ff8bc 100644
--- a/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h
+++ b/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h
@@ -1,16 +1,15 @@
//===--- UnnamedNamespaceInHeaderCheck.h - clang-tidy -----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_GOOGLE_UNNAMEDNAMESPACEINHEADERCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_UNNAMEDNAMESPACEINHEADERCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "../utils/HeaderFileExtensionsUtils.h"
namespace clang {
diff --git a/clang-tidy/google/UsingNamespaceDirectiveCheck.cpp b/clang-tidy/google/UsingNamespaceDirectiveCheck.cpp
index 7490f022..f11a7d1c 100644
--- a/clang-tidy/google/UsingNamespaceDirectiveCheck.cpp
+++ b/clang-tidy/google/UsingNamespaceDirectiveCheck.cpp
@@ -1,9 +1,8 @@
//===--- UsingNamespaceDirectiveCheck.cpp - clang-tidy ----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/UsingNamespaceDirectiveCheck.h b/clang-tidy/google/UsingNamespaceDirectiveCheck.h
index 2be65c16..c9bcf48c 100644
--- a/clang-tidy/google/UsingNamespaceDirectiveCheck.h
+++ b/clang-tidy/google/UsingNamespaceDirectiveCheck.h
@@ -1,16 +1,15 @@
//===--- UsingNamespaceDirectiveCheck.h - clang-tidy ------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_GOOGLE_USINGNAMESPACEDIRECTIVECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_USINGNAMESPACEDIRECTIVECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp b/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
index 890a56f7..a5884286 100644
--- a/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
+++ b/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
@@ -1,9 +1,8 @@
//===--- ExceptionBaseclassCheck.cpp - clang-tidy--------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/hicpp/ExceptionBaseclassCheck.h b/clang-tidy/hicpp/ExceptionBaseclassCheck.h
index 778979dd..10220139 100644
--- a/clang-tidy/hicpp/ExceptionBaseclassCheck.h
+++ b/clang-tidy/hicpp/ExceptionBaseclassCheck.h
@@ -1,9 +1,8 @@
//===--- ExceptionBaseclassCheck.h - clang-tidy------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/hicpp/HICPPTidyModule.cpp b/clang-tidy/hicpp/HICPPTidyModule.cpp
index 5b5f4518..ad367dcf 100644
--- a/clang-tidy/hicpp/HICPPTidyModule.cpp
+++ b/clang-tidy/hicpp/HICPPTidyModule.cpp
@@ -1,9 +1,8 @@
//===------- HICPPTidyModule.cpp - clang-tidy -----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/hicpp/LICENSE.TXT b/clang-tidy/hicpp/LICENSE.TXT
index fb8f513e..b432d4ea 100644
--- a/clang-tidy/hicpp/LICENSE.TXT
+++ b/clang-tidy/hicpp/LICENSE.TXT
@@ -1,8 +1,8 @@
------------------------------------------------------------------------------
clang-tidy High-Integrity C++ Files
------------------------------------------------------------------------------
-All clang-tidy files are licensed under the LLVM license with the following
-additions:
+All clang-tidy files are licensed under the same terms as the rest of the LLVM
+project with the following additions:
Any file referencing a High-Integrity C++ Coding guideline:
diff --git a/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp b/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp
index 03f4edba..e30b4f12 100644
--- a/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp
+++ b/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp
@@ -1,9 +1,8 @@
//===--- MultiwayPathsCoveredCheck.cpp - clang-tidy------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/hicpp/MultiwayPathsCoveredCheck.h b/clang-tidy/hicpp/MultiwayPathsCoveredCheck.h
index 498dad65..d21afbb5 100644
--- a/clang-tidy/hicpp/MultiwayPathsCoveredCheck.h
+++ b/clang-tidy/hicpp/MultiwayPathsCoveredCheck.h
@@ -1,9 +1,8 @@
//===--- MultiwayPathsCoveredCheck.h - clang-tidy----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/hicpp/NoAssemblerCheck.cpp b/clang-tidy/hicpp/NoAssemblerCheck.cpp
index 06969a87..af5a1cb0 100644
--- a/clang-tidy/hicpp/NoAssemblerCheck.cpp
+++ b/clang-tidy/hicpp/NoAssemblerCheck.cpp
@@ -1,9 +1,8 @@
//===--- NoAssemblerCheck.cpp - clang-tidy---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/hicpp/NoAssemblerCheck.h b/clang-tidy/hicpp/NoAssemblerCheck.h
index 416ccb06..d91c5de2 100644
--- a/clang-tidy/hicpp/NoAssemblerCheck.h
+++ b/clang-tidy/hicpp/NoAssemblerCheck.h
@@ -1,9 +1,8 @@
//===--- NoAssemblerCheck.h - clang-tidy-------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/hicpp/SignedBitwiseCheck.cpp b/clang-tidy/hicpp/SignedBitwiseCheck.cpp
index 97383693..781a4430 100644
--- a/clang-tidy/hicpp/SignedBitwiseCheck.cpp
+++ b/clang-tidy/hicpp/SignedBitwiseCheck.cpp
@@ -1,9 +1,8 @@
//===--- SignedBitwiseCheck.cpp - clang-tidy-------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/hicpp/SignedBitwiseCheck.h b/clang-tidy/hicpp/SignedBitwiseCheck.h
index 24338ad9..34d5f096 100644
--- a/clang-tidy/hicpp/SignedBitwiseCheck.h
+++ b/clang-tidy/hicpp/SignedBitwiseCheck.h
@@ -1,9 +1,8 @@
//===--- SignedBitwiseCheck.h - clang-tidy-----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/llvm/CMakeLists.txt b/clang-tidy/llvm/CMakeLists.txt
index ce69c05f..085fb856 100644
--- a/clang-tidy/llvm/CMakeLists.txt
+++ b/clang-tidy/llvm/CMakeLists.txt
@@ -4,6 +4,7 @@ add_clang_library(clangTidyLLVMModule
HeaderGuardCheck.cpp
IncludeOrderCheck.cpp
LLVMTidyModule.cpp
+ PreferIsaOrDynCastInConditionalsCheck.cpp
TwineLocalCheck.cpp
LINK_LIBS
diff --git a/clang-tidy/llvm/HeaderGuardCheck.cpp b/clang-tidy/llvm/HeaderGuardCheck.cpp
index c0e449ed..bde460ca 100644
--- a/clang-tidy/llvm/HeaderGuardCheck.cpp
+++ b/clang-tidy/llvm/HeaderGuardCheck.cpp
@@ -1,9 +1,8 @@
//===--- HeaderGuardCheck.cpp - clang-tidy --------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/llvm/HeaderGuardCheck.h b/clang-tidy/llvm/HeaderGuardCheck.h
index ca2d7efd..46021e28 100644
--- a/clang-tidy/llvm/HeaderGuardCheck.h
+++ b/clang-tidy/llvm/HeaderGuardCheck.h
@@ -1,9 +1,8 @@
//===--- HeaderGuardCheck.h - clang-tidy ------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/llvm/IncludeOrderCheck.cpp b/clang-tidy/llvm/IncludeOrderCheck.cpp
index f1fdb39c..9c3ab0b7 100644
--- a/clang-tidy/llvm/IncludeOrderCheck.cpp
+++ b/clang-tidy/llvm/IncludeOrderCheck.cpp
@@ -1,9 +1,8 @@
//===--- IncludeOrderCheck.cpp - clang-tidy -------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -21,7 +20,8 @@ namespace llvm {
namespace {
class IncludeOrderPPCallbacks : public PPCallbacks {
public:
- explicit IncludeOrderPPCallbacks(ClangTidyCheck &Check, SourceManager &SM)
+ explicit IncludeOrderPPCallbacks(ClangTidyCheck &Check,
+ const SourceManager &SM)
: LookForMainModule(true), Check(Check), SM(SM) {}
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
@@ -46,14 +46,14 @@ private:
bool LookForMainModule;
ClangTidyCheck &Check;
- SourceManager &SM;
+ const SourceManager &SM;
};
} // namespace
-void IncludeOrderCheck::registerPPCallbacks(CompilerInstance &Compiler) {
- Compiler.getPreprocessor().addPPCallbacks(
- ::llvm::make_unique<IncludeOrderPPCallbacks>(
- *this, Compiler.getSourceManager()));
+void IncludeOrderCheck::registerPPCallbacks(const SourceManager &SM,
+ Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) {
+ PP->addPPCallbacks(::llvm::make_unique<IncludeOrderPPCallbacks>(*this, SM));
}
static int getPriority(StringRef Filename, bool IsAngled, bool IsMainModule) {
diff --git a/clang-tidy/llvm/IncludeOrderCheck.h b/clang-tidy/llvm/IncludeOrderCheck.h
index ad876b95..b95c3800 100644
--- a/clang-tidy/llvm/IncludeOrderCheck.h
+++ b/clang-tidy/llvm/IncludeOrderCheck.h
@@ -1,16 +1,15 @@
//===--- IncludeOrderCheck.h - clang-tidy -----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_INCLUDE_ORDER_CHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_INCLUDE_ORDER_CHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
@@ -23,7 +22,8 @@ class IncludeOrderCheck : public ClangTidyCheck {
public:
IncludeOrderCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
};
} // namespace llvm
diff --git a/clang-tidy/llvm/LLVMTidyModule.cpp b/clang-tidy/llvm/LLVMTidyModule.cpp
index ea46ca93..fb7b52a3 100644
--- a/clang-tidy/llvm/LLVMTidyModule.cpp
+++ b/clang-tidy/llvm/LLVMTidyModule.cpp
@@ -1,9 +1,8 @@
//===--- LLVMTidyModule.cpp - clang-tidy ----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -13,6 +12,7 @@
#include "../readability/NamespaceCommentCheck.h"
#include "HeaderGuardCheck.h"
#include "IncludeOrderCheck.h"
+#include "PreferIsaOrDynCastInConditionalsCheck.h"
#include "TwineLocalCheck.h"
namespace clang {
@@ -26,6 +26,8 @@ public:
CheckFactories.registerCheck<IncludeOrderCheck>("llvm-include-order");
CheckFactories.registerCheck<readability::NamespaceCommentCheck>(
"llvm-namespace-comment");
+ CheckFactories.registerCheck<PreferIsaOrDynCastInConditionalsCheck>(
+ "llvm-prefer-isa-or-dyn-cast-in-conditionals");
CheckFactories.registerCheck<TwineLocalCheck>("llvm-twine-local");
}
};
diff --git a/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp b/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp
new file mode 100644
index 00000000..252ef3bf
--- /dev/null
+++ b/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp
@@ -0,0 +1,135 @@
+//===--- PreferIsaOrDynCastInConditionalsCheck.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 "PreferIsaOrDynCastInConditionalsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace ast_matchers {
+AST_MATCHER(Expr, isMacroID) { return Node.getExprLoc().isMacroID(); }
+} // namespace ast_matchers
+
+namespace tidy {
+namespace llvm {
+
+void PreferIsaOrDynCastInConditionalsCheck::registerMatchers(
+ MatchFinder *Finder) {
+ if (!getLangOpts().CPlusPlus)
+ return;
+
+ auto Condition = hasCondition(implicitCastExpr(has(
+ callExpr(
+ allOf(unless(isMacroID()), unless(cxxMemberCallExpr()),
+ anyOf(callee(namedDecl(hasName("cast"))),
+ callee(namedDecl(hasName("dyn_cast")).bind("dyn_cast")))))
+ .bind("call"))));
+
+ auto Any = anyOf(
+ has(declStmt(containsDeclaration(
+ 0,
+ varDecl(hasInitializer(
+ callExpr(allOf(unless(isMacroID()), unless(cxxMemberCallExpr()),
+ callee(namedDecl(hasName("cast")))))
+ .bind("assign")))))),
+ Condition);
+
+ auto CallExpression =
+ callExpr(
+ allOf(unless(isMacroID()), unless(cxxMemberCallExpr()),
+ allOf(callee(namedDecl(anyOf(hasName("isa"), hasName("cast"),
+ hasName("cast_or_null"),
+ hasName("dyn_cast"),
+ hasName("dyn_cast_or_null")))
+ .bind("func")),
+ hasArgument(0, anyOf(declRefExpr().bind("arg"),
+ cxxMemberCallExpr().bind("arg"))))))
+ .bind("rhs");
+
+ Finder->addMatcher(
+ stmt(anyOf(ifStmt(Any), whileStmt(Any), doStmt(Condition),
+ binaryOperator(
+ allOf(unless(isExpansionInFileMatching(
+ "llvm/include/llvm/Support/Casting.h")),
+ hasOperatorName("&&"),
+ hasLHS(implicitCastExpr().bind("lhs")),
+ hasRHS(anyOf(implicitCastExpr(has(CallExpression)),
+ CallExpression))))
+ .bind("and"))),
+ this);
+}
+
+void PreferIsaOrDynCastInConditionalsCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ if (const auto *MatchedDecl = Result.Nodes.getNodeAs<CallExpr>("assign")) {
+ SourceLocation StartLoc = MatchedDecl->getCallee()->getExprLoc();
+ SourceLocation EndLoc =
+ StartLoc.getLocWithOffset(StringRef("cast").size() - 1);
+
+ diag(MatchedDecl->getBeginLoc(),
+ "cast<> in conditional will assert rather than return a null pointer")
+ << FixItHint::CreateReplacement(SourceRange(StartLoc, EndLoc),
+ "dyn_cast");
+ } else if (const auto *MatchedDecl =
+ Result.Nodes.getNodeAs<CallExpr>("call")) {
+ SourceLocation StartLoc = MatchedDecl->getCallee()->getExprLoc();
+ SourceLocation EndLoc =
+ StartLoc.getLocWithOffset(StringRef("cast").size() - 1);
+
+ StringRef Message =
+ "cast<> in conditional will assert rather than return a null pointer";
+ if (Result.Nodes.getNodeAs<NamedDecl>("dyn_cast"))
+ Message = "return value from dyn_cast<> not used";
+
+ diag(MatchedDecl->getBeginLoc(), Message)
+ << FixItHint::CreateReplacement(SourceRange(StartLoc, EndLoc), "isa");
+ } else if (const auto *MatchedDecl =
+ Result.Nodes.getNodeAs<BinaryOperator>("and")) {
+ const auto *LHS = Result.Nodes.getNodeAs<ImplicitCastExpr>("lhs");
+ const auto *RHS = Result.Nodes.getNodeAs<CallExpr>("rhs");
+ const auto *Arg = Result.Nodes.getNodeAs<Expr>("arg");
+ const auto *Func = Result.Nodes.getNodeAs<NamedDecl>("func");
+
+ assert(LHS && "LHS is null");
+ assert(RHS && "RHS is null");
+ assert(Arg && "Arg is null");
+ assert(Func && "Func is null");
+
+ StringRef LHSString(Lexer::getSourceText(
+ CharSourceRange::getTokenRange(LHS->getSourceRange()),
+ *Result.SourceManager, getLangOpts()));
+
+ StringRef ArgString(Lexer::getSourceText(
+ CharSourceRange::getTokenRange(Arg->getSourceRange()),
+ *Result.SourceManager, getLangOpts()));
+
+ if (ArgString != LHSString)
+ return;
+
+ StringRef RHSString(Lexer::getSourceText(
+ CharSourceRange::getTokenRange(RHS->getSourceRange()),
+ *Result.SourceManager, getLangOpts()));
+
+ std::string Replacement("isa_and_nonnull");
+ Replacement += RHSString.substr(Func->getName().size());
+
+ diag(MatchedDecl->getBeginLoc(),
+ "isa_and_nonnull<> is preferred over an explicit test for null "
+ "followed by calling isa<>")
+ << FixItHint::CreateReplacement(SourceRange(MatchedDecl->getBeginLoc(),
+ MatchedDecl->getEndLoc()),
+ Replacement);
+ }
+}
+
+} // namespace llvm
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.h b/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.h
new file mode 100644
index 00000000..354693c1
--- /dev/null
+++ b/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.h
@@ -0,0 +1,64 @@
+//===--- PreferIsaOrDynCastInConditionalsCheck.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_AVOIDCASTINCONDITIONALCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_AVOIDCASTINCONDITIONALCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace llvm {
+
+/// \brief Looks at conditionals and finds and replaces cases of ``cast<>``, which will
+/// assert rather than return a null pointer, and ``dyn_cast<>`` where
+/// the return value is not captured. Additionally, finds and replaces cases that match the
+/// pattern ``var && isa<X>(var)``, where ``var`` is evaluated twice.
+///
+/// Finds cases like these:
+/// \code
+/// if (auto x = cast<X>(y)) {}
+/// // is replaced by:
+/// if (auto x = dyn_cast<X>(y)) {}
+///
+/// if (cast<X>(y)) {}
+/// // is replaced by:
+/// if (isa<X>(y)) {}
+///
+/// if (dyn_cast<X>(y)) {}
+/// // is replaced by:
+/// if (isa<X>(y)) {}
+///
+/// if (var && isa<T>(var)) {}
+/// // is replaced by:
+/// if (isa_and_nonnull<T>(var.foo())) {}
+/// \endcode
+///
+/// // Other cases are ignored, e.g.:
+/// \code
+/// if (auto f = cast<Z>(y)->foo()) {}
+/// if (cast<Z>(y)->foo()) {}
+/// if (X.cast(y)) {}
+/// \endcode
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/llvm-prefer-isa-or-dyn-cast-in-conditionals.html
+class PreferIsaOrDynCastInConditionalsCheck : public ClangTidyCheck {
+public:
+ PreferIsaOrDynCastInConditionalsCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace llvm
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_AVOIDCASTINCONDITIONALCHECK_H
diff --git a/clang-tidy/llvm/TwineLocalCheck.cpp b/clang-tidy/llvm/TwineLocalCheck.cpp
index 744ddd9d..2fddf6d2 100644
--- a/clang-tidy/llvm/TwineLocalCheck.cpp
+++ b/clang-tidy/llvm/TwineLocalCheck.cpp
@@ -1,9 +1,8 @@
//===--- TwineLocalCheck.cpp - clang-tidy ---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/llvm/TwineLocalCheck.h b/clang-tidy/llvm/TwineLocalCheck.h
index 9f7979b4..0cb655a8 100644
--- a/clang-tidy/llvm/TwineLocalCheck.h
+++ b/clang-tidy/llvm/TwineLocalCheck.h
@@ -1,16 +1,15 @@
//===--- TwineLocalCheck.h - clang-tidy -------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_TWINE_LOCAL_CHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_TWINE_LOCAL_CHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/misc/DefinitionsInHeadersCheck.cpp b/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
index f4dab397..a36f307b 100644
--- a/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
+++ b/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
@@ -1,9 +1,8 @@
//===--- DefinitionsInHeadersCheck.cpp - clang-tidy------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/misc/DefinitionsInHeadersCheck.h b/clang-tidy/misc/DefinitionsInHeadersCheck.h
index 428b05cd..dda6d69e 100644
--- a/clang-tidy/misc/DefinitionsInHeadersCheck.h
+++ b/clang-tidy/misc/DefinitionsInHeadersCheck.h
@@ -1,16 +1,15 @@
//===--- DefinitionsInHeadersCheck.h - clang-tidy----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISC_DEFINITIONS_IN_HEADERS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_DEFINITIONS_IN_HEADERS_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "../utils/HeaderFileExtensionsUtils.h"
namespace clang {
diff --git a/clang-tidy/misc/MiscTidyModule.cpp b/clang-tidy/misc/MiscTidyModule.cpp
index dd9061a4..ba160d1d 100644
--- a/clang-tidy/misc/MiscTidyModule.cpp
+++ b/clang-tidy/misc/MiscTidyModule.cpp
@@ -1,9 +1,8 @@
//===--- MiscTidyModule.cpp - clang-tidy ----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/misc/MisplacedConstCheck.cpp b/clang-tidy/misc/MisplacedConstCheck.cpp
index 515b22c0..1e1b2b0d 100644
--- a/clang-tidy/misc/MisplacedConstCheck.cpp
+++ b/clang-tidy/misc/MisplacedConstCheck.cpp
@@ -1,9 +1,8 @@
//===--- MisplacedConstCheck.cpp - clang-tidy------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/misc/MisplacedConstCheck.h b/clang-tidy/misc/MisplacedConstCheck.h
index 410edf7b..55803b40 100644
--- a/clang-tidy/misc/MisplacedConstCheck.h
+++ b/clang-tidy/misc/MisplacedConstCheck.h
@@ -1,16 +1,15 @@
//===--- MisplacedConstCheck.h - clang-tidy----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISC_MISPLACED_CONST_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MISPLACED_CONST_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/misc/NewDeleteOverloadsCheck.cpp b/clang-tidy/misc/NewDeleteOverloadsCheck.cpp
index 5e291195..a96d1904 100644
--- a/clang-tidy/misc/NewDeleteOverloadsCheck.cpp
+++ b/clang-tidy/misc/NewDeleteOverloadsCheck.cpp
@@ -1,9 +1,8 @@
//===--- NewDeleteOverloadsCheck.cpp - clang-tidy--------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/misc/NewDeleteOverloadsCheck.h b/clang-tidy/misc/NewDeleteOverloadsCheck.h
index 3e99892b..cd23a746 100644
--- a/clang-tidy/misc/NewDeleteOverloadsCheck.h
+++ b/clang-tidy/misc/NewDeleteOverloadsCheck.h
@@ -1,16 +1,15 @@
//===--- NewDeleteOverloadsCheck.h - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISC_NEWDELETEOVERLOADS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_NEWDELETEOVERLOADS_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "llvm/ADT/SmallVector.h"
#include <map>
diff --git a/clang-tidy/misc/NonCopyableObjects.cpp b/clang-tidy/misc/NonCopyableObjects.cpp
index de152754..53cc2734 100644
--- a/clang-tidy/misc/NonCopyableObjects.cpp
+++ b/clang-tidy/misc/NonCopyableObjects.cpp
@@ -1,9 +1,8 @@
//===--- NonCopyableObjects.cpp - clang-tidy-------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/misc/NonCopyableObjects.h b/clang-tidy/misc/NonCopyableObjects.h
index 38a45fd5..6529fddf 100644
--- a/clang-tidy/misc/NonCopyableObjects.h
+++ b/clang-tidy/misc/NonCopyableObjects.h
@@ -1,16 +1,15 @@
//===--- NonCopyableObjects.h - clang-tidy-----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISC_NONCOPYABLEOBJECTS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_NONCOPYABLEOBJECTS_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.cpp b/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.cpp
index c0bdbfbf..7f57fecd 100644
--- a/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.cpp
+++ b/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.cpp
@@ -1,9 +1,8 @@
//===--- NonPrivateMemberVariablesInClassesCheck.cpp - clang-tidy ---------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -23,8 +22,8 @@ AST_MATCHER(CXXRecordDecl, hasMethods) {
return std::distance(Node.method_begin(), Node.method_end()) != 0;
}
-AST_MATCHER(CXXRecordDecl, hasNonStaticMethod) {
- return hasMethod(unless(isStaticStorageClass()))
+AST_MATCHER(CXXRecordDecl, hasNonStaticNonImplicitMethod) {
+ return hasMethod(unless(anyOf(isStaticStorageClass(), isImplicit())))
.matches(Node, Finder, Builder);
}
@@ -67,10 +66,11 @@ void NonPrivateMemberVariablesInClassesCheck::registerMatchers(
IgnorePublicMemberVariables ? isProtected() : unless(isPrivate()));
// We only want the records that not only contain the mutable data (non-static
- // member variables), but also have some logic (non-static member functions).
- // We may optionally ignore records where all the member variables are public.
+ // member variables), but also have some logic (non-static, non-implicit
+ // member functions). We may optionally ignore records where all the member
+ // variables are public.
Finder->addMatcher(cxxRecordDecl(anyOf(isStruct(), isClass()), hasMethods(),
- hasNonStaticMethod(),
+ hasNonStaticNonImplicitMethod(),
unless(ShouldIgnoreRecord),
forEach(InterestingField.bind("field")))
.bind("record"),
diff --git a/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.h b/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.h
index c39e356c..7bc44250 100644
--- a/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.h
+++ b/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.h
@@ -1,16 +1,15 @@
//===--- NonPrivateMemberVariablesInClassesCheck.h - clang-tidy -*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISC_NONPRIVATEMEMBERVARIABLESINCLASSESCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_NONPRIVATEMEMBERVARIABLESINCLASSESCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tidy/misc/RedundantExpressionCheck.cpp
index e9b0f4d0..33a8b9a4 100644
--- a/clang-tidy/misc/RedundantExpressionCheck.cpp
+++ b/clang-tidy/misc/RedundantExpressionCheck.cpp
@@ -1,9 +1,8 @@
//===--- RedundantExpressionCheck.cpp - clang-tidy-------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/misc/RedundantExpressionCheck.h b/clang-tidy/misc/RedundantExpressionCheck.h
index c0f8bf5e..d07e2b70 100644
--- a/clang-tidy/misc/RedundantExpressionCheck.h
+++ b/clang-tidy/misc/RedundantExpressionCheck.h
@@ -1,16 +1,15 @@
//===--- RedundantExpressionCheck.h - clang-tidy-----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISC_REDUNDANT_EXPRESSION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANT_EXPRESSION_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/misc/StaticAssertCheck.cpp b/clang-tidy/misc/StaticAssertCheck.cpp
index 583ed7ad..a2f31797 100644
--- a/clang-tidy/misc/StaticAssertCheck.cpp
+++ b/clang-tidy/misc/StaticAssertCheck.cpp
@@ -1,9 +1,8 @@
//===--- StaticAssertCheck.cpp - clang-tidy -------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -146,7 +145,7 @@ SourceLocation StaticAssertCheck::getLastParenLoc(const ASTContext *ASTCtx,
const LangOptions &Opts = ASTCtx->getLangOpts();
const SourceManager &SM = ASTCtx->getSourceManager();
- llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getFileID(AssertLoc));
+ const llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getFileID(AssertLoc));
if (!Buffer)
return SourceLocation();
diff --git a/clang-tidy/misc/StaticAssertCheck.h b/clang-tidy/misc/StaticAssertCheck.h
index faefce17..b6d7211b 100644
--- a/clang-tidy/misc/StaticAssertCheck.h
+++ b/clang-tidy/misc/StaticAssertCheck.h
@@ -1,16 +1,15 @@
//===--- StaticAssertCheck.h - clang-tidy -----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISC_STATICASSERTCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_STATICASSERTCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "llvm/ADT/StringRef.h"
#include <string>
diff --git a/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.cpp b/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.cpp
index 759c3f0e..b7077a12 100644
--- a/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.cpp
+++ b/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.cpp
@@ -1,9 +1,8 @@
//===--- ThrowByValueCatchByReferenceCheck.cpp - clang-tidy----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h b/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h
index a2e7df73..b3c89350 100644
--- a/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h
+++ b/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h
@@ -1,16 +1,15 @@
//===--- ThrowByValueCatchByReferenceCheck.h - clang-tidy--------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISC_THROW_BY_VALUE_CATCH_BY_REFERENCE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_THROW_BY_VALUE_CATCH_BY_REFERENCE_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp b/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp
index 84dd410d..8c87dae9 100644
--- a/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp
+++ b/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp
@@ -1,9 +1,8 @@
//===--- UnconventionalAssignOperatorCheck.cpp - clang-tidy -----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/misc/UnconventionalAssignOperatorCheck.h b/clang-tidy/misc/UnconventionalAssignOperatorCheck.h
index ee91dcaa..86e09388 100644
--- a/clang-tidy/misc/UnconventionalAssignOperatorCheck.h
+++ b/clang-tidy/misc/UnconventionalAssignOperatorCheck.h
@@ -1,16 +1,15 @@
//===--- UnconventionalAssignOperatorCheck.h - clang-tidy -------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISC_ASSIGNOPERATORSIGNATURECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_ASSIGNOPERATORSIGNATURECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/misc/UniqueptrResetReleaseCheck.cpp b/clang-tidy/misc/UniqueptrResetReleaseCheck.cpp
index 99758d33..9363fa90 100644
--- a/clang-tidy/misc/UniqueptrResetReleaseCheck.cpp
+++ b/clang-tidy/misc/UniqueptrResetReleaseCheck.cpp
@@ -1,9 +1,8 @@
//===--- UniqueptrResetReleaseCheck.cpp - clang-tidy ----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/misc/UniqueptrResetReleaseCheck.h b/clang-tidy/misc/UniqueptrResetReleaseCheck.h
index cf18a5a5..b302f156 100644
--- a/clang-tidy/misc/UniqueptrResetReleaseCheck.h
+++ b/clang-tidy/misc/UniqueptrResetReleaseCheck.h
@@ -1,16 +1,15 @@
//===--- UniqueptrResetReleaseCheck.h - clang-tidy --------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISC_UNIQUEPTRRESETRELEASECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNIQUEPTRRESETRELEASECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/misc/UnusedAliasDeclsCheck.cpp b/clang-tidy/misc/UnusedAliasDeclsCheck.cpp
index 4beb4320..c301aeab 100644
--- a/clang-tidy/misc/UnusedAliasDeclsCheck.cpp
+++ b/clang-tidy/misc/UnusedAliasDeclsCheck.cpp
@@ -1,9 +1,8 @@
//===--- UnusedAliasDeclsCheck.cpp - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/misc/UnusedAliasDeclsCheck.h b/clang-tidy/misc/UnusedAliasDeclsCheck.h
index 8cce3756..f25e8d8d 100644
--- a/clang-tidy/misc/UnusedAliasDeclsCheck.h
+++ b/clang-tidy/misc/UnusedAliasDeclsCheck.h
@@ -1,16 +1,15 @@
//===--- UnusedAliasDeclsCheck.h - clang-tidy--------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISC_UNUSED_ALIAS_DECLS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNUSED_ALIAS_DECLS_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "llvm/ADT/DenseMap.h"
namespace clang {
diff --git a/clang-tidy/misc/UnusedParametersCheck.cpp b/clang-tidy/misc/UnusedParametersCheck.cpp
index cee09150..01dce8fa 100644
--- a/clang-tidy/misc/UnusedParametersCheck.cpp
+++ b/clang-tidy/misc/UnusedParametersCheck.cpp
@@ -1,9 +1,8 @@
//===--- UnusedParametersCheck.cpp - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/misc/UnusedParametersCheck.h b/clang-tidy/misc/UnusedParametersCheck.h
index b9bae26f..7e9b8c96 100644
--- a/clang-tidy/misc/UnusedParametersCheck.h
+++ b/clang-tidy/misc/UnusedParametersCheck.h
@@ -1,16 +1,15 @@
//===--- UnusedParametersCheck.h - clang-tidy--------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISC_UNUSED_PARAMETERS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNUSED_PARAMETERS_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/misc/UnusedUsingDeclsCheck.cpp b/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
index 48009b5a..3dabca91 100644
--- a/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
+++ b/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
@@ -1,9 +1,8 @@
//===--- UnusedUsingDeclsCheck.cpp - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -155,7 +154,10 @@ void UnusedUsingDeclsCheck::onEndOfTranslationUnit() {
for (const auto &Context : Contexts) {
if (!Context.IsUsed) {
diag(Context.FoundUsingDecl->getLocation(), "using decl %0 is unused")
- << Context.FoundUsingDecl
+ << Context.FoundUsingDecl;
+ // Emit a fix and a fix description of the check;
+ diag(Context.FoundUsingDecl->getLocation(),
+ /*FixDescription=*/"remove the using", DiagnosticIDs::Note)
<< FixItHint::CreateRemoval(Context.UsingDeclRange);
}
}
diff --git a/clang-tidy/misc/UnusedUsingDeclsCheck.h b/clang-tidy/misc/UnusedUsingDeclsCheck.h
index 2a41a8f6..2e46f3c1 100644
--- a/clang-tidy/misc/UnusedUsingDeclsCheck.h
+++ b/clang-tidy/misc/UnusedUsingDeclsCheck.h
@@ -1,16 +1,15 @@
//===--- UnusedUsingDeclsCheck.h - clang-tidy--------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISC_UNUSED_USING_DECLS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNUSED_USING_DECLS_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "llvm/ADT/SmallPtrSet.h"
#include <vector>
diff --git a/clang-tidy/modernize/AvoidBindCheck.cpp b/clang-tidy/modernize/AvoidBindCheck.cpp
index bd477026..c51b6e86 100644
--- a/clang-tidy/modernize/AvoidBindCheck.cpp
+++ b/clang-tidy/modernize/AvoidBindCheck.cpp
@@ -1,9 +1,8 @@
//===--- AvoidBindCheck.cpp - clang-tidy-----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -170,7 +169,7 @@ void AvoidBindCheck::check(const MatchFinder::MatchResult &Result) {
Ref->printPretty(Stream, nullptr, Result.Context->getPrintingPolicy());
Stream << "(";
addFunctionCallArgs(Args, Stream);
- Stream << "); };";
+ Stream << "); }";
Diag << FixItHint::CreateReplacement(MatchedDecl->getSourceRange(),
Stream.str());
diff --git a/clang-tidy/modernize/AvoidBindCheck.h b/clang-tidy/modernize/AvoidBindCheck.h
index 5ae0241f..4b393303 100644
--- a/clang-tidy/modernize/AvoidBindCheck.h
+++ b/clang-tidy/modernize/AvoidBindCheck.h
@@ -1,16 +1,15 @@
//===--- AvoidBindCheck.h - clang-tidy---------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_AVOID_BIND_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_AVOID_BIND_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/AvoidCArraysCheck.cpp b/clang-tidy/modernize/AvoidCArraysCheck.cpp
index dd194832..e3dffd06 100644
--- a/clang-tidy/modernize/AvoidCArraysCheck.cpp
+++ b/clang-tidy/modernize/AvoidCArraysCheck.cpp
@@ -1,9 +1,8 @@
//===--- AvoidCArraysCheck.cpp - clang-tidy -------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -31,6 +30,12 @@ AST_MATCHER(clang::RecordDecl, isExternCContext) {
return Node.isExternCContext();
}
+AST_MATCHER(clang::ParmVarDecl, isArgvOfMain) {
+ const clang::DeclContext *DC = Node.getDeclContext();
+ const auto *FD = llvm::dyn_cast<clang::FunctionDecl>(DC);
+ return FD ? FD->isMain() : false;
+}
+
} // namespace
namespace clang {
@@ -44,7 +49,8 @@ void AvoidCArraysCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
typeLoc(hasValidBeginLoc(), hasType(arrayType()),
- unless(anyOf(hasParent(varDecl(isExternC())),
+ unless(anyOf(hasParent(parmVarDecl(isArgvOfMain())),
+ hasParent(varDecl(isExternC())),
hasParent(fieldDecl(
hasParent(recordDecl(isExternCContext())))),
hasAncestor(functionDecl(isExternC())))))
diff --git a/clang-tidy/modernize/AvoidCArraysCheck.h b/clang-tidy/modernize/AvoidCArraysCheck.h
index afef8848..48e38bfb 100644
--- a/clang-tidy/modernize/AvoidCArraysCheck.h
+++ b/clang-tidy/modernize/AvoidCArraysCheck.h
@@ -1,16 +1,15 @@
//===--- AvoidCArraysCheck.h - clang-tidy -----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_AVOIDCARRAYSCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_AVOIDCARRAYSCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/ConcatNestedNamespacesCheck.cpp b/clang-tidy/modernize/ConcatNestedNamespacesCheck.cpp
index bef85f7b..c1539bfd 100644
--- a/clang-tidy/modernize/ConcatNestedNamespacesCheck.cpp
+++ b/clang-tidy/modernize/ConcatNestedNamespacesCheck.cpp
@@ -1,9 +1,8 @@
//===--- ConcatNestedNamespacesCheck.cpp - clang-tidy----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -40,6 +39,7 @@ static bool alreadyConcatenated(std::size_t NumCandidates,
const SourceRange &ReplacementRange,
const SourceManager &Sources,
const LangOptions &LangOpts) {
+ // FIXME: This logic breaks when there is a comment with ':'s in the middle.
CharSourceRange TextRange =
Lexer::getAsCharRange(ReplacementRange, Sources, LangOpts);
StringRef CurrentNamespacesText =
diff --git a/clang-tidy/modernize/ConcatNestedNamespacesCheck.h b/clang-tidy/modernize/ConcatNestedNamespacesCheck.h
index 547690d2..2c589fca 100644
--- a/clang-tidy/modernize/ConcatNestedNamespacesCheck.h
+++ b/clang-tidy/modernize/ConcatNestedNamespacesCheck.h
@@ -1,16 +1,15 @@
//===--- ConcatNestedNamespacesCheck.h - clang-tidy--------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_CONCATNESTEDNAMESPACESCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_CONCATNESTEDNAMESPACESCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
diff --git a/clang-tidy/modernize/DeprecatedHeadersCheck.cpp b/clang-tidy/modernize/DeprecatedHeadersCheck.cpp
index 1ff3f898..af4d47c0 100644
--- a/clang-tidy/modernize/DeprecatedHeadersCheck.cpp
+++ b/clang-tidy/modernize/DeprecatedHeadersCheck.cpp
@@ -1,9 +1,8 @@
//===--- DeprecatedHeadersCheck.cpp - clang-tidy---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -41,11 +40,11 @@ private:
};
} // namespace
-void DeprecatedHeadersCheck::registerPPCallbacks(CompilerInstance &Compiler) {
- if (this->getLangOpts().CPlusPlus) {
- Compiler.getPreprocessor().addPPCallbacks(
- ::llvm::make_unique<IncludeModernizePPCallbacks>(*this,
- this->getLangOpts()));
+void DeprecatedHeadersCheck::registerPPCallbacks(
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ if (getLangOpts().CPlusPlus) {
+ PP->addPPCallbacks(
+ ::llvm::make_unique<IncludeModernizePPCallbacks>(*this, getLangOpts()));
}
}
diff --git a/clang-tidy/modernize/DeprecatedHeadersCheck.h b/clang-tidy/modernize/DeprecatedHeadersCheck.h
index ee7254e3..dfe6b850 100644
--- a/clang-tidy/modernize/DeprecatedHeadersCheck.h
+++ b/clang-tidy/modernize/DeprecatedHeadersCheck.h
@@ -1,16 +1,15 @@
//===--- DeprecatedHeadersCheck.h - clang-tidy-------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_C_HEADERS_TO_CXX_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_C_HEADERS_TO_CXX_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
@@ -37,7 +36,8 @@ class DeprecatedHeadersCheck : public ClangTidyCheck {
public:
DeprecatedHeadersCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
};
} // namespace modernize
diff --git a/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp b/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp
index c9f0649a..cd094219 100644
--- a/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp
+++ b/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp
@@ -1,9 +1,8 @@
//===--- DeprecatedIosBaseAliasesCheck.cpp - clang-tidy--------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.h b/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.h
index bbccd413..55c1d42c 100644
--- a/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.h
+++ b/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.h
@@ -1,16 +1,15 @@
//===--- DeprecatedIosBaseAliasesCheck.h - clang-tidy------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_DEPRECATEDIOSBASEALIASESCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_DEPRECATEDIOSBASEALIASESCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tidy/modernize/LoopConvertCheck.cpp
index aa11b71a..f9e941c2 100644
--- a/clang-tidy/modernize/LoopConvertCheck.cpp
+++ b/clang-tidy/modernize/LoopConvertCheck.cpp
@@ -1,9 +1,8 @@
//===--- LoopConvertCheck.cpp - clang-tidy---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/LoopConvertCheck.h b/clang-tidy/modernize/LoopConvertCheck.h
index 75ab25aa..1806572b 100644
--- a/clang-tidy/modernize/LoopConvertCheck.h
+++ b/clang-tidy/modernize/LoopConvertCheck.h
@@ -1,16 +1,15 @@
//===--- LoopConvertCheck.h - clang-tidy-------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_LOOP_CONVERT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_LOOP_CONVERT_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "LoopConvertUtils.h"
namespace clang {
diff --git a/clang-tidy/modernize/LoopConvertUtils.cpp b/clang-tidy/modernize/LoopConvertUtils.cpp
index f65f7a16..80d80a79 100644
--- a/clang-tidy/modernize/LoopConvertUtils.cpp
+++ b/clang-tidy/modernize/LoopConvertUtils.cpp
@@ -1,9 +1,8 @@
//===--- LoopConvertUtils.cpp - clang-tidy --------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/LoopConvertUtils.h b/clang-tidy/modernize/LoopConvertUtils.h
index f0fa11a8..3cead294 100644
--- a/clang-tidy/modernize/LoopConvertUtils.h
+++ b/clang-tidy/modernize/LoopConvertUtils.h
@@ -1,9 +1,8 @@
//===--- LoopConvertUtils.h - clang-tidy ------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/MakeSharedCheck.cpp b/clang-tidy/modernize/MakeSharedCheck.cpp
index 541c2cb5..11d24432 100644
--- a/clang-tidy/modernize/MakeSharedCheck.cpp
+++ b/clang-tidy/modernize/MakeSharedCheck.cpp
@@ -1,9 +1,8 @@
//===--- MakeSharedCheck.cpp - clang-tidy----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/MakeSharedCheck.h b/clang-tidy/modernize/MakeSharedCheck.h
index cf014462..95bf6b7c 100644
--- a/clang-tidy/modernize/MakeSharedCheck.h
+++ b/clang-tidy/modernize/MakeSharedCheck.h
@@ -1,9 +1,8 @@
//===--- MakeSharedCheck.h - clang-tidy--------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/MakeSmartPtrCheck.cpp b/clang-tidy/modernize/MakeSmartPtrCheck.cpp
index 15b88b8b..b371345c 100644
--- a/clang-tidy/modernize/MakeSmartPtrCheck.cpp
+++ b/clang-tidy/modernize/MakeSmartPtrCheck.cpp
@@ -1,9 +1,8 @@
//===--- MakeSmartPtrCheck.cpp - clang-tidy--------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -66,11 +65,13 @@ bool MakeSmartPtrCheck::isLanguageVersionSupported(
return LangOpts.CPlusPlus11;
}
-void MakeSmartPtrCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+void MakeSmartPtrCheck::registerPPCallbacks(const SourceManager &SM,
+ Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) {
if (isLanguageVersionSupported(getLangOpts())) {
- Inserter = llvm::make_unique<utils::IncludeInserter>(
- Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle);
- Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+ Inserter = llvm::make_unique<utils::IncludeInserter>(SM, getLangOpts(),
+ IncludeStyle);
+ PP->addPPCallbacks(Inserter->CreatePPCallbacks());
}
}
@@ -277,7 +278,7 @@ bool MakeSmartPtrCheck::replaceNew(DiagnosticBuilder &Diag,
return false;
std::string ArraySizeExpr;
- if (const auto* ArraySize = New->getArraySize()) {
+ if (const auto* ArraySize = New->getArraySize().getValueOr(nullptr)) {
ArraySizeExpr = Lexer::getSourceText(CharSourceRange::getTokenRange(
ArraySize->getSourceRange()),
SM, getLangOpts())
diff --git a/clang-tidy/modernize/MakeSmartPtrCheck.h b/clang-tidy/modernize/MakeSmartPtrCheck.h
index 02428d7a..30fdab8e 100644
--- a/clang-tidy/modernize/MakeSmartPtrCheck.h
+++ b/clang-tidy/modernize/MakeSmartPtrCheck.h
@@ -1,16 +1,15 @@
//===--- MakeSmartPtrCheck.h - clang-tidy------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_MAKE_SMART_PTR_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKE_SMART_PTR_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "../utils/IncludeInserter.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
@@ -27,7 +26,8 @@ public:
MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context,
StringRef MakeSmartPtrFunctionName);
void registerMatchers(ast_matchers::MatchFinder *Finder) final;
- void registerPPCallbacks(clang::CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) final;
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
diff --git a/clang-tidy/modernize/MakeUniqueCheck.cpp b/clang-tidy/modernize/MakeUniqueCheck.cpp
index 3ebbb071..1ee4fd70 100644
--- a/clang-tidy/modernize/MakeUniqueCheck.cpp
+++ b/clang-tidy/modernize/MakeUniqueCheck.cpp
@@ -1,9 +1,8 @@
//===--- MakeUniqueCheck.cpp - clang-tidy----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/MakeUniqueCheck.h b/clang-tidy/modernize/MakeUniqueCheck.h
index 587b41e0..113c3294 100644
--- a/clang-tidy/modernize/MakeUniqueCheck.h
+++ b/clang-tidy/modernize/MakeUniqueCheck.h
@@ -1,9 +1,8 @@
//===--- MakeUniqueCheck.h - clang-tidy--------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tidy/modernize/ModernizeTidyModule.cpp
index fcf535b7..45ecdf93 100644
--- a/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -1,9 +1,8 @@
//===--- ModernizeTidyModule.cpp - clang-tidy -----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/PassByValueCheck.cpp b/clang-tidy/modernize/PassByValueCheck.cpp
index f54c5754..a83e54a1 100644
--- a/clang-tidy/modernize/PassByValueCheck.cpp
+++ b/clang-tidy/modernize/PassByValueCheck.cpp
@@ -1,9 +1,8 @@
//===--- PassByValueCheck.cpp - clang-tidy---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -165,14 +164,16 @@ void PassByValueCheck::registerMatchers(MatchFinder *Finder) {
this);
}
-void PassByValueCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+void PassByValueCheck::registerPPCallbacks(const SourceManager &SM,
+ Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) {
// Only register the preprocessor callbacks for C++; the functionality
// currently does not provide any benefit to other languages, despite being
// benign.
if (getLangOpts().CPlusPlus) {
- Inserter.reset(new utils::IncludeInserter(
- Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle));
- Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+ Inserter = llvm::make_unique<utils::IncludeInserter>(SM, getLangOpts(),
+ IncludeStyle);
+ PP->addPPCallbacks(Inserter->CreatePPCallbacks());
}
}
diff --git a/clang-tidy/modernize/PassByValueCheck.h b/clang-tidy/modernize/PassByValueCheck.h
index 37deb3f7..7c741956 100644
--- a/clang-tidy/modernize/PassByValueCheck.h
+++ b/clang-tidy/modernize/PassByValueCheck.h
@@ -1,16 +1,15 @@
//===--- PassByValueCheck.h - clang-tidy-------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_PASS_BY_VALUE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_PASS_BY_VALUE_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "../utils/IncludeInserter.h"
#include <memory>
@@ -23,7 +22,8 @@ class PassByValueCheck : public ClangTidyCheck {
public:
PassByValueCheck(StringRef Name, ClangTidyContext *Context);
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
- void registerPPCallbacks(clang::CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
diff --git a/clang-tidy/modernize/RawStringLiteralCheck.cpp b/clang-tidy/modernize/RawStringLiteralCheck.cpp
index a4aef41f..415010bc 100644
--- a/clang-tidy/modernize/RawStringLiteralCheck.cpp
+++ b/clang-tidy/modernize/RawStringLiteralCheck.cpp
@@ -1,9 +1,8 @@
//===--- RawStringLiteralCheck.cpp - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/RawStringLiteralCheck.h b/clang-tidy/modernize/RawStringLiteralCheck.h
index f7721f6a..fd38dc27 100644
--- a/clang-tidy/modernize/RawStringLiteralCheck.h
+++ b/clang-tidy/modernize/RawStringLiteralCheck.h
@@ -1,16 +1,15 @@
//===--- RawStringLiteralCheck.h - clang-tidy--------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_RAW_STRING_LITERAL_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_RAW_STRING_LITERAL_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include <bitset>
namespace clang {
diff --git a/clang-tidy/modernize/RedundantVoidArgCheck.cpp b/clang-tidy/modernize/RedundantVoidArgCheck.cpp
index ea49ab7b..46de805e 100644
--- a/clang-tidy/modernize/RedundantVoidArgCheck.cpp
+++ b/clang-tidy/modernize/RedundantVoidArgCheck.cpp
@@ -1,9 +1,8 @@
//===- RedundantVoidArgCheck.cpp - clang-tidy -----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -102,10 +101,15 @@ void RedundantVoidArgCheck::check(const MatchFinder::MatchResult &Result) {
void RedundantVoidArgCheck::processFunctionDecl(
const MatchFinder::MatchResult &Result, const FunctionDecl *Function) {
if (Function->isThisDeclarationADefinition()) {
- const Stmt *Body = Function->getBody();
SourceLocation Start = Function->getBeginLoc();
- SourceLocation End =
- Body ? Body->getBeginLoc().getLocWithOffset(-1) : Function->getEndLoc();
+ SourceLocation End = Function->getEndLoc();
+ if (const Stmt *Body = Function->getBody()) {
+ End = Body->getBeginLoc();
+ if (End.isMacroID() &&
+ Result.SourceManager->isAtStartOfImmediateMacroExpansion(End))
+ End = Result.SourceManager->getExpansionLoc(End);
+ End = End.getLocWithOffset(-1);
+ }
removeVoidArgumentTokens(Result, SourceRange(Start, End),
"function definition");
} else {
@@ -173,10 +177,8 @@ void RedundantVoidArgCheck::removeVoidArgumentTokens(
void RedundantVoidArgCheck::removeVoidToken(Token VoidToken,
StringRef Diagnostic) {
- SourceLocation VoidLoc(VoidToken.getLocation());
- auto VoidRange =
- CharSourceRange::getTokenRange(VoidLoc, VoidLoc.getLocWithOffset(3));
- diag(VoidLoc, Diagnostic) << FixItHint::CreateRemoval(VoidRange);
+ SourceLocation VoidLoc = VoidToken.getLocation();
+ diag(VoidLoc, Diagnostic) << FixItHint::CreateRemoval(VoidLoc);
}
void RedundantVoidArgCheck::processTypedefNameDecl(
diff --git a/clang-tidy/modernize/RedundantVoidArgCheck.h b/clang-tidy/modernize/RedundantVoidArgCheck.h
index c990ef46..eca7085f 100644
--- a/clang-tidy/modernize/RedundantVoidArgCheck.h
+++ b/clang-tidy/modernize/RedundantVoidArgCheck.h
@@ -1,16 +1,15 @@
//===--- RedundantVoidArgCheck.h - clang-tidy --------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_REDUNDANT_VOID_ARG_CHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REDUNDANT_VOID_ARG_CHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "clang/Lex/Token.h"
#include <string>
diff --git a/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp b/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
index 3281ef66..c1c22359 100644
--- a/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
+++ b/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
@@ -1,9 +1,8 @@
//===--- ReplaceAutoPtrCheck.cpp - clang-tidy------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -133,15 +132,17 @@ void ReplaceAutoPtrCheck::registerMatchers(MatchFinder *Finder) {
this);
}
-void ReplaceAutoPtrCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+void ReplaceAutoPtrCheck::registerPPCallbacks(const SourceManager &SM,
+ Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) {
// Only register the preprocessor callbacks for C++; the functionality
// currently does not provide any benefit to other languages, despite being
// benign.
if (!getLangOpts().CPlusPlus)
return;
- Inserter.reset(new utils::IncludeInserter(
- Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle));
- Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+ Inserter = llvm::make_unique<utils::IncludeInserter>(SM, getLangOpts(),
+ IncludeStyle);
+ PP->addPPCallbacks(Inserter->CreatePPCallbacks());
}
void ReplaceAutoPtrCheck::check(const MatchFinder::MatchResult &Result) {
diff --git a/clang-tidy/modernize/ReplaceAutoPtrCheck.h b/clang-tidy/modernize/ReplaceAutoPtrCheck.h
index 5b73d51b..d1c66fca 100644
--- a/clang-tidy/modernize/ReplaceAutoPtrCheck.h
+++ b/clang-tidy/modernize/ReplaceAutoPtrCheck.h
@@ -1,16 +1,15 @@
//===--- ReplaceAutoPtrCheck.h - clang-tidy----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_REPLACE_AUTO_PTR_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REPLACE_AUTO_PTR_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "../utils/IncludeInserter.h"
namespace clang {
@@ -46,7 +45,8 @@ public:
ReplaceAutoPtrCheck(StringRef Name, ClangTidyContext *Context);
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
private:
diff --git a/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp b/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp
index 9a715693..44c108c8 100644
--- a/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp
+++ b/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp
@@ -1,9 +1,8 @@
//===--- ReplaceRandomShuffleCheck.cpp - clang-tidy------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -44,11 +43,10 @@ void ReplaceRandomShuffleCheck::registerMatchers(MatchFinder *Finder) {
}
void ReplaceRandomShuffleCheck::registerPPCallbacks(
- CompilerInstance &Compiler) {
- IncludeInserter = llvm::make_unique<utils::IncludeInserter>(
- Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle);
- Compiler.getPreprocessor().addPPCallbacks(
- IncludeInserter->CreatePPCallbacks());
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ IncludeInserter = llvm::make_unique<utils::IncludeInserter>(SM, getLangOpts(),
+ IncludeStyle);
+ PP->addPPCallbacks(IncludeInserter->CreatePPCallbacks());
}
void ReplaceRandomShuffleCheck::storeOptions(
diff --git a/clang-tidy/modernize/ReplaceRandomShuffleCheck.h b/clang-tidy/modernize/ReplaceRandomShuffleCheck.h
index 050d7401..3c5f6624 100644
--- a/clang-tidy/modernize/ReplaceRandomShuffleCheck.h
+++ b/clang-tidy/modernize/ReplaceRandomShuffleCheck.h
@@ -1,16 +1,15 @@
//===--- ReplaceRandomShuffleCheck.h - clang-tidy----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_REPLACE_RANDOM_SHUFFLE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REPLACE_RANDOM_SHUFFLE_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "../utils/IncludeInserter.h"
namespace clang {
@@ -25,7 +24,8 @@ namespace modernize {
class ReplaceRandomShuffleCheck : public ClangTidyCheck {
public:
ReplaceRandomShuffleCheck(StringRef Name, ClangTidyContext *Context);
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
diff --git a/clang-tidy/modernize/ReturnBracedInitListCheck.cpp b/clang-tidy/modernize/ReturnBracedInitListCheck.cpp
index e5857f76..f7e27172 100644
--- a/clang-tidy/modernize/ReturnBracedInitListCheck.cpp
+++ b/clang-tidy/modernize/ReturnBracedInitListCheck.cpp
@@ -1,9 +1,8 @@
//===--- ReturnBracedInitListCheck.cpp - clang-tidy------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/ReturnBracedInitListCheck.h b/clang-tidy/modernize/ReturnBracedInitListCheck.h
index eda982a8..553a042c 100644
--- a/clang-tidy/modernize/ReturnBracedInitListCheck.h
+++ b/clang-tidy/modernize/ReturnBracedInitListCheck.h
@@ -1,16 +1,15 @@
//===--- ReturnBracedInitListCheck.h - clang-tidy----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_RETURN_BRACED_INIT_LIST_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_RETURN_BRACED_INIT_LIST_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/ShrinkToFitCheck.cpp b/clang-tidy/modernize/ShrinkToFitCheck.cpp
index bc0749b9..607dc5fa 100644
--- a/clang-tidy/modernize/ShrinkToFitCheck.cpp
+++ b/clang-tidy/modernize/ShrinkToFitCheck.cpp
@@ -1,9 +1,8 @@
//===--- ShrinkToFitCheck.cpp - clang-tidy---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/ShrinkToFitCheck.h b/clang-tidy/modernize/ShrinkToFitCheck.h
index 1e3745cd..7d589b2c 100644
--- a/clang-tidy/modernize/ShrinkToFitCheck.h
+++ b/clang-tidy/modernize/ShrinkToFitCheck.h
@@ -1,16 +1,15 @@
//===--- ShrinkToFitCheck.h - clang-tidy-------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_SHRINKTOFITCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_SHRINKTOFITCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/UnaryStaticAssertCheck.cpp b/clang-tidy/modernize/UnaryStaticAssertCheck.cpp
index 5ddbb933..d93a0248 100644
--- a/clang-tidy/modernize/UnaryStaticAssertCheck.cpp
+++ b/clang-tidy/modernize/UnaryStaticAssertCheck.cpp
@@ -1,9 +1,8 @@
//===--- UnaryStaticAssertCheck.cpp - clang-tidy---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/UnaryStaticAssertCheck.h b/clang-tidy/modernize/UnaryStaticAssertCheck.h
index b83c2c43..f43dd5ac 100644
--- a/clang-tidy/modernize/UnaryStaticAssertCheck.h
+++ b/clang-tidy/modernize/UnaryStaticAssertCheck.h
@@ -1,16 +1,15 @@
//===--- UnaryStaticAssertCheck.h - clang-tidy-------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_UNARY_STATIC_ASSERT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_UNARY_STATIC_ASSERT_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/UseAutoCheck.cpp b/clang-tidy/modernize/UseAutoCheck.cpp
index 0fecd24a..e9f54f81 100644
--- a/clang-tidy/modernize/UseAutoCheck.cpp
+++ b/clang-tidy/modernize/UseAutoCheck.cpp
@@ -1,9 +1,8 @@
//===--- UseAutoCheck.cpp - clang-tidy-------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/UseAutoCheck.h b/clang-tidy/modernize/UseAutoCheck.h
index a061c5ff..600de1ef 100644
--- a/clang-tidy/modernize/UseAutoCheck.h
+++ b/clang-tidy/modernize/UseAutoCheck.h
@@ -1,16 +1,15 @@
//===--- UseAutoCheck.h - clang-tidy-----------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_USE_AUTO_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_AUTO_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/UseBoolLiteralsCheck.cpp b/clang-tidy/modernize/UseBoolLiteralsCheck.cpp
index 13afbb43..011837e0 100644
--- a/clang-tidy/modernize/UseBoolLiteralsCheck.cpp
+++ b/clang-tidy/modernize/UseBoolLiteralsCheck.cpp
@@ -1,9 +1,8 @@
//===--- UseBoolLiteralsCheck.cpp - clang-tidy-----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/UseBoolLiteralsCheck.h b/clang-tidy/modernize/UseBoolLiteralsCheck.h
index c9c73634..7368588e 100644
--- a/clang-tidy/modernize/UseBoolLiteralsCheck.h
+++ b/clang-tidy/modernize/UseBoolLiteralsCheck.h
@@ -1,16 +1,15 @@
//===--- UseBoolLiteralsCheck.h - clang-tidy---------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_USE_BOOL_LITERALS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_BOOL_LITERALS_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp b/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
index 23a3e1fa..3c2e0e90 100644
--- a/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
+++ b/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
@@ -1,9 +1,8 @@
//===--- UseDefaultMemberInitCheck.cpp - clang-tidy------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -256,17 +255,20 @@ void UseDefaultMemberInitCheck::checkDefaultInit(
CharSourceRange InitRange =
CharSourceRange::getCharRange(LParenEnd, Init->getRParenLoc());
+ bool ValueInit = isa<ImplicitValueInitExpr>(Init->getInit());
+ bool CanAssign = UseAssignment && (!ValueInit || !Init->getInit()->getType()->isEnumeralType());
+
auto Diag =
diag(Field->getLocation(), "use default member initializer for %0")
<< Field
- << FixItHint::CreateInsertion(FieldEnd, UseAssignment ? " = " : "{")
+ << FixItHint::CreateInsertion(FieldEnd, CanAssign ? " = " : "{")
<< FixItHint::CreateInsertionFromRange(FieldEnd, InitRange);
- if (UseAssignment && isa<ImplicitValueInitExpr>(Init->getInit()))
+ if (CanAssign && ValueInit)
Diag << FixItHint::CreateInsertion(
FieldEnd, getValueOfValueInit(Init->getInit()->getType()));
- if (!UseAssignment)
+ if (!CanAssign)
Diag << FixItHint::CreateInsertion(FieldEnd, "}");
Diag << FixItHint::CreateRemoval(Init->getSourceRange());
@@ -274,7 +276,7 @@ void UseDefaultMemberInitCheck::checkDefaultInit(
void UseDefaultMemberInitCheck::checkExistingInit(
const MatchFinder::MatchResult &Result, const CXXCtorInitializer *Init) {
- const FieldDecl *Field = Init->getMember();
+ const FieldDecl *Field = Init->getAnyMember();
if (!sameValue(Field->getInClassInitializer(), Init->getInit()))
return;
diff --git a/clang-tidy/modernize/UseDefaultMemberInitCheck.h b/clang-tidy/modernize/UseDefaultMemberInitCheck.h
index d8887a02..f1e62228 100644
--- a/clang-tidy/modernize/UseDefaultMemberInitCheck.h
+++ b/clang-tidy/modernize/UseDefaultMemberInitCheck.h
@@ -1,16 +1,15 @@
//===--- UseDefaultMemberInitCheck.h - clang-tidy----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_USE_DEFAULT_MEMBER_INIT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_DEFAULT_MEMBER_INIT_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/UseEmplaceCheck.cpp b/clang-tidy/modernize/UseEmplaceCheck.cpp
index b6c142d1..786bb5a9 100644
--- a/clang-tidy/modernize/UseEmplaceCheck.cpp
+++ b/clang-tidy/modernize/UseEmplaceCheck.cpp
@@ -1,9 +1,8 @@
//===--- UseEmplaceCheck.cpp - clang-tidy----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/UseEmplaceCheck.h b/clang-tidy/modernize/UseEmplaceCheck.h
index 2efb2129..5382eb69 100644
--- a/clang-tidy/modernize/UseEmplaceCheck.h
+++ b/clang-tidy/modernize/UseEmplaceCheck.h
@@ -1,16 +1,15 @@
//===--- UseEmplaceCheck.h - clang-tidy--------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_USE_EMPLACE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_EMPLACE_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include <string>
#include <vector>
diff --git a/clang-tidy/modernize/UseEqualsDefaultCheck.cpp b/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
index 4245bfea..ae6f91c8 100644
--- a/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
+++ b/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
@@ -1,9 +1,8 @@
//===--- UseEqualsDefaultCheck.cpp - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/UseEqualsDefaultCheck.h b/clang-tidy/modernize/UseEqualsDefaultCheck.h
index a55c222d..014b90c9 100644
--- a/clang-tidy/modernize/UseEqualsDefaultCheck.h
+++ b/clang-tidy/modernize/UseEqualsDefaultCheck.h
@@ -1,16 +1,15 @@
//===--- UseEqualsDefaultCheck.h - clang-tidy--------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_USE_EQUALS_DEFAULT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_EQUALS_DEFAULT_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/UseEqualsDeleteCheck.cpp b/clang-tidy/modernize/UseEqualsDeleteCheck.cpp
index fc8425d9..4c366b4c 100644
--- a/clang-tidy/modernize/UseEqualsDeleteCheck.cpp
+++ b/clang-tidy/modernize/UseEqualsDeleteCheck.cpp
@@ -1,9 +1,8 @@
//===--- UseEqualsDeleteCheck.cpp - clang-tidy-----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/UseEqualsDeleteCheck.h b/clang-tidy/modernize/UseEqualsDeleteCheck.h
index 716f045d..b6cd010b 100644
--- a/clang-tidy/modernize/UseEqualsDeleteCheck.h
+++ b/clang-tidy/modernize/UseEqualsDeleteCheck.h
@@ -1,16 +1,15 @@
//===--- UseEqualsDeleteCheck.h - clang-tidy---------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_USE_EQUALS_DELETE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_EQUALS_DELETE_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/UseNodiscardCheck.cpp b/clang-tidy/modernize/UseNodiscardCheck.cpp
index f655515b..d2ac7d52 100644
--- a/clang-tidy/modernize/UseNodiscardCheck.cpp
+++ b/clang-tidy/modernize/UseNodiscardCheck.cpp
@@ -1,9 +1,8 @@
//===--- UseNodiscardCheck.cpp - clang-tidy -------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/UseNodiscardCheck.h b/clang-tidy/modernize/UseNodiscardCheck.h
index 00563e7f..325e5f88 100644
--- a/clang-tidy/modernize/UseNodiscardCheck.h
+++ b/clang-tidy/modernize/UseNodiscardCheck.h
@@ -1,16 +1,15 @@
//===--- UseNodiscardCheck.h - clang-tidy -----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_USENODISCARDCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USENODISCARDCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/UseNoexceptCheck.cpp b/clang-tidy/modernize/UseNoexceptCheck.cpp
index 869381ab..4b9c4984 100644
--- a/clang-tidy/modernize/UseNoexceptCheck.cpp
+++ b/clang-tidy/modernize/UseNoexceptCheck.cpp
@@ -1,9 +1,8 @@
//===--- UseNoexceptCheck.cpp - clang-tidy---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/UseNoexceptCheck.h b/clang-tidy/modernize/UseNoexceptCheck.h
index a15867bd..828eb572 100644
--- a/clang-tidy/modernize/UseNoexceptCheck.h
+++ b/clang-tidy/modernize/UseNoexceptCheck.h
@@ -1,16 +1,15 @@
//===--- UseNoexceptCheck.h - clang-tidy-------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_USE_NOEXCEPT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_NOEXCEPT_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tidy/modernize/UseNullptrCheck.cpp
index 3bf09c1f..45e59c3e 100644
--- a/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -1,9 +1,8 @@
//===--- UseNullptrCheck.cpp - clang-tidy----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/UseNullptrCheck.h b/clang-tidy/modernize/UseNullptrCheck.h
index 4b33f1ee..dab6ca95 100644
--- a/clang-tidy/modernize/UseNullptrCheck.h
+++ b/clang-tidy/modernize/UseNullptrCheck.h
@@ -1,16 +1,15 @@
//===--- UseNullptrCheck.h - clang-tidy--------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_USE_NULLPTR_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_NULLPTR_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/UseOverrideCheck.cpp b/clang-tidy/modernize/UseOverrideCheck.cpp
index 9429eb2c..2f15213d 100644
--- a/clang-tidy/modernize/UseOverrideCheck.cpp
+++ b/clang-tidy/modernize/UseOverrideCheck.cpp
@@ -1,9 +1,8 @@
//===--- UseOverrideCheck.cpp - clang-tidy --------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -18,9 +17,28 @@ namespace clang {
namespace tidy {
namespace modernize {
+UseOverrideCheck::UseOverrideCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ IgnoreDestructors(Options.get("IgnoreDestructors", false)),
+ OverrideSpelling(Options.get("OverrideSpelling", "override")),
+ FinalSpelling(Options.get("FinalSpelling", "final")) {}
+
+void UseOverrideCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "IgnoreDestructors", IgnoreDestructors);
+ Options.store(Opts, "OverrideSpelling", OverrideSpelling);
+ Options.store(Opts, "FinalSpelling", FinalSpelling);
+}
+
void UseOverrideCheck::registerMatchers(MatchFinder *Finder) {
// Only register the matcher for C++11.
- if (getLangOpts().CPlusPlus11)
+ if (!getLangOpts().CPlusPlus11)
+ return;
+
+ if (IgnoreDestructors)
+ Finder->addMatcher(
+ cxxMethodDecl(isOverride(), unless(cxxDestructorDecl())).bind("method"),
+ this);
+ else
Finder->addMatcher(cxxMethodDecl(isOverride()).bind("method"), this);
}
@@ -68,6 +86,8 @@ void UseOverrideCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Method = Result.Nodes.getNodeAs<FunctionDecl>("method");
const SourceManager &Sources = *Result.SourceManager;
+ ASTContext &Context = *Result.Context;
+
assert(Method != nullptr);
if (Method->getInstantiatedFromMemberFunction() != nullptr)
Method = Method->getInstantiatedFromMemberFunction();
@@ -87,25 +107,24 @@ void UseOverrideCheck::check(const MatchFinder::MatchResult &Result) {
return; // Nothing to do.
std::string Message;
-
if (OnlyVirtualSpecified) {
- Message =
- "prefer using 'override' or (rarely) 'final' instead of 'virtual'";
+ Message = "prefer using '%0' or (rarely) '%1' instead of 'virtual'";
} else if (KeywordCount == 0) {
- Message = "annotate this function with 'override' or (rarely) 'final'";
+ Message = "annotate this function with '%0' or (rarely) '%1'";
} else {
StringRef Redundant =
- HasVirtual ? (HasOverride && HasFinal ? "'virtual' and 'override' are"
+ HasVirtual ? (HasOverride && HasFinal ? "'virtual' and '%0' are"
: "'virtual' is")
- : "'override' is";
- StringRef Correct = HasFinal ? "'final'" : "'override'";
+ : "'%0' is";
+ StringRef Correct = HasFinal ? "'%1'" : "'%0'";
Message = (llvm::Twine(Redundant) +
" redundant since the function is already declared " + Correct)
.str();
}
- DiagnosticBuilder Diag = diag(Method->getLocation(), Message);
+ auto Diag = diag(Method->getLocation(), Message)
+ << OverrideSpelling << FinalSpelling;
CharSourceRange FileRange = Lexer::makeFileCharRange(
CharSourceRange::getTokenRange(Method->getSourceRange()), Sources,
@@ -122,7 +141,7 @@ void UseOverrideCheck::check(const MatchFinder::MatchResult &Result) {
// Add 'override' on inline declarations that don't already have it.
if (!HasFinal && !HasOverride) {
SourceLocation InsertLoc;
- StringRef ReplacementText = "override ";
+ std::string ReplacementText = OverrideSpelling + " ";
SourceLocation MethodLoc = Method->getLocation();
for (Token T : Tokens) {
@@ -152,7 +171,7 @@ void UseOverrideCheck::check(const MatchFinder::MatchResult &Result) {
// end of the declaration of the function, but prefer to put it on the
// same line as the declaration if the beginning brace for the start of
// the body falls on the next line.
- ReplacementText = " override";
+ ReplacementText = " " + OverrideSpelling;
auto LastTokenIter = std::prev(Tokens.end());
// When try statement is used instead of compound statement as
// method body - insert override keyword before it.
@@ -165,23 +184,30 @@ void UseOverrideCheck::check(const MatchFinder::MatchResult &Result) {
// For declarations marked with "= 0" or "= [default|delete]", the end
// location will point until after those markings. Therefore, the override
// keyword shouldn't be inserted at the end, but before the '='.
- if (Tokens.size() > 2 && (GetText(Tokens.back(), Sources) == "0" ||
- Tokens.back().is(tok::kw_default) ||
- Tokens.back().is(tok::kw_delete)) &&
+ if (Tokens.size() > 2 &&
+ (GetText(Tokens.back(), Sources) == "0" ||
+ Tokens.back().is(tok::kw_default) ||
+ Tokens.back().is(tok::kw_delete)) &&
GetText(Tokens[Tokens.size() - 2], Sources) == "=") {
InsertLoc = Tokens[Tokens.size() - 2].getLocation();
// Check if we need to insert a space.
if ((Tokens[Tokens.size() - 2].getFlags() & Token::LeadingSpace) == 0)
- ReplacementText = " override ";
- } else if (GetText(Tokens.back(), Sources) == "ABSTRACT") {
+ ReplacementText = " " + OverrideSpelling + " ";
+ } else if (GetText(Tokens.back(), Sources) == "ABSTRACT")
InsertLoc = Tokens.back().getLocation();
- }
}
if (!InsertLoc.isValid()) {
InsertLoc = FileRange.getEnd();
- ReplacementText = " override";
+ ReplacementText = " " + OverrideSpelling;
}
+
+ // If the override macro has been specified just ensure it exists,
+ // if not don't apply a fixit but keep the warning.
+ if (OverrideSpelling != "override" &&
+ !Context.Idents.get(OverrideSpelling).hasMacroDefinition())
+ return;
+
Diag << FixItHint::CreateInsertion(InsertLoc, ReplacementText);
}
diff --git a/clang-tidy/modernize/UseOverrideCheck.h b/clang-tidy/modernize/UseOverrideCheck.h
index 83ce7da7..ed163956 100644
--- a/clang-tidy/modernize/UseOverrideCheck.h
+++ b/clang-tidy/modernize/UseOverrideCheck.h
@@ -1,16 +1,15 @@
//===--- UseOverrideCheck.h - clang-tidy ------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_USEOVERRIDECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USEOVERRIDECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
@@ -19,10 +18,16 @@ namespace modernize {
/// Use C++11's `override` and remove `virtual` where applicable.
class UseOverrideCheck : public ClangTidyCheck {
public:
- UseOverrideCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context) {}
+ UseOverrideCheck(StringRef Name, ClangTidyContext *Context);
+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+ const bool IgnoreDestructors;
+ const std::string OverrideSpelling;
+ const std::string FinalSpelling;
};
} // namespace modernize
diff --git a/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp b/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp
index 74f050ba..6490f027 100644
--- a/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp
+++ b/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp
@@ -1,9 +1,8 @@
//===--- UseTransparentFunctorsCheck.cpp - clang-tidy----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/UseTransparentFunctorsCheck.h b/clang-tidy/modernize/UseTransparentFunctorsCheck.h
index 4bdce766..dce4e99a 100644
--- a/clang-tidy/modernize/UseTransparentFunctorsCheck.h
+++ b/clang-tidy/modernize/UseTransparentFunctorsCheck.h
@@ -1,16 +1,15 @@
//===--- UseTransparentFunctorsCheck.h - clang-tidy--------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_USE_TRANSPARENT_FUNCTORS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_TRANSPARENT_FUNCTORS_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp b/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
index 05b2dd82..cb3f5513 100644
--- a/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
+++ b/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
@@ -1,9 +1,8 @@
//===--- UseUncaughtExceptionsCheck.cpp - clang-tidy--------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/UseUncaughtExceptionsCheck.h b/clang-tidy/modernize/UseUncaughtExceptionsCheck.h
index 2b9660c7..2c4386e6 100644
--- a/clang-tidy/modernize/UseUncaughtExceptionsCheck.h
+++ b/clang-tidy/modernize/UseUncaughtExceptionsCheck.h
@@ -1,16 +1,15 @@
//===--- UseUncaughtExceptionsCheck.h - clang-tidy------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_USE_UNCAUGHT_EXCEPTIONS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_UNCAUGHT_EXCEPTIONS_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/modernize/UseUsingCheck.cpp b/clang-tidy/modernize/UseUsingCheck.cpp
index a690e447..bd234623 100644
--- a/clang-tidy/modernize/UseUsingCheck.cpp
+++ b/clang-tidy/modernize/UseUsingCheck.cpp
@@ -1,9 +1,8 @@
//===--- UseUsingCheck.cpp - clang-tidy------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/UseUsingCheck.h b/clang-tidy/modernize/UseUsingCheck.h
index 022eef08..ea11609d 100644
--- a/clang-tidy/modernize/UseUsingCheck.h
+++ b/clang-tidy/modernize/UseUsingCheck.h
@@ -1,16 +1,15 @@
//===--- UseUsingCheck.h - clang-tidy----------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MODERNIZE_USE_USING_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_USING_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/mpi/BufferDerefCheck.cpp b/clang-tidy/mpi/BufferDerefCheck.cpp
index 8e2c0e34..8ababfe4 100644
--- a/clang-tidy/mpi/BufferDerefCheck.cpp
+++ b/clang-tidy/mpi/BufferDerefCheck.cpp
@@ -1,9 +1,8 @@
//===--- BufferDerefCheck.cpp - clang-tidy---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/mpi/BufferDerefCheck.h b/clang-tidy/mpi/BufferDerefCheck.h
index 8490fa1c..040e3f79 100644
--- a/clang-tidy/mpi/BufferDerefCheck.h
+++ b/clang-tidy/mpi/BufferDerefCheck.h
@@ -1,16 +1,15 @@
//===--- BufferDerefCheck.h - clang-tidy-------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MPI_BUFFER_DEREF_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MPI_BUFFER_DEREF_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/mpi/MPITidyModule.cpp b/clang-tidy/mpi/MPITidyModule.cpp
index 55e187db..b295d5ff 100644
--- a/clang-tidy/mpi/MPITidyModule.cpp
+++ b/clang-tidy/mpi/MPITidyModule.cpp
@@ -1,9 +1,8 @@
//===--- MPITidyModule.cpp - clang-tidy -----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/mpi/TypeMismatchCheck.cpp b/clang-tidy/mpi/TypeMismatchCheck.cpp
index a1f92b8f..a9661e0e 100644
--- a/clang-tidy/mpi/TypeMismatchCheck.cpp
+++ b/clang-tidy/mpi/TypeMismatchCheck.cpp
@@ -1,9 +1,8 @@
//===--- TypeMismatchCheck.cpp - clang-tidy--------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/mpi/TypeMismatchCheck.h b/clang-tidy/mpi/TypeMismatchCheck.h
index dd56c465..a563e295 100644
--- a/clang-tidy/mpi/TypeMismatchCheck.h
+++ b/clang-tidy/mpi/TypeMismatchCheck.h
@@ -1,16 +1,15 @@
//===--- TypeMismatchCheck.h - clang-tidy------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MPI_TYPE_MISMATCH_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MPI_TYPE_MISMATCH_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
namespace clang {
diff --git a/clang-tidy/objc/AvoidNSErrorInitCheck.cpp b/clang-tidy/objc/AvoidNSErrorInitCheck.cpp
index d5e2027a..eb18dcd2 100644
--- a/clang-tidy/objc/AvoidNSErrorInitCheck.cpp
+++ b/clang-tidy/objc/AvoidNSErrorInitCheck.cpp
@@ -1,9 +1,8 @@
//===--- AvoidNSErrorInitCheck.cpp - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/objc/AvoidNSErrorInitCheck.h b/clang-tidy/objc/AvoidNSErrorInitCheck.h
index 379b8a2a..030a532e 100644
--- a/clang-tidy/objc/AvoidNSErrorInitCheck.h
+++ b/clang-tidy/objc/AvoidNSErrorInitCheck.h
@@ -1,16 +1,15 @@
//===--- AvoidNSErrorInitCheck.h - clang-tidy--------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_OBJC_AVOIDNSERRORINITCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_AVOIDNSERRORINITCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/objc/AvoidSpinlockCheck.cpp b/clang-tidy/objc/AvoidSpinlockCheck.cpp
index 319d9456..ac3d2b28 100644
--- a/clang-tidy/objc/AvoidSpinlockCheck.cpp
+++ b/clang-tidy/objc/AvoidSpinlockCheck.cpp
@@ -1,9 +1,8 @@
//===--- AvoidSpinlockCheck.cpp - clang-tidy-------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/objc/AvoidSpinlockCheck.h b/clang-tidy/objc/AvoidSpinlockCheck.h
index d9dbf8cb..dd409625 100644
--- a/clang-tidy/objc/AvoidSpinlockCheck.h
+++ b/clang-tidy/objc/AvoidSpinlockCheck.h
@@ -1,16 +1,15 @@
//===--- AvoidSpinlockCheck.h - clang-tidy-----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_OBJC_AVOID_SPINLOCK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_AVOID_SPINLOCK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/objc/CMakeLists.txt b/clang-tidy/objc/CMakeLists.txt
index 4063bba1..4eeb1484 100644
--- a/clang-tidy/objc/CMakeLists.txt
+++ b/clang-tidy/objc/CMakeLists.txt
@@ -6,6 +6,7 @@ add_clang_library(clangTidyObjCModule
ForbiddenSubclassingCheck.cpp
ObjCTidyModule.cpp
PropertyDeclarationCheck.cpp
+ SuperSelfCheck.cpp
LINK_LIBS
clangAST
diff --git a/clang-tidy/objc/ForbiddenSubclassingCheck.cpp b/clang-tidy/objc/ForbiddenSubclassingCheck.cpp
index 0599b21d..6b8e7951 100644
--- a/clang-tidy/objc/ForbiddenSubclassingCheck.cpp
+++ b/clang-tidy/objc/ForbiddenSubclassingCheck.cpp
@@ -1,9 +1,8 @@
//===--- ForbiddenSubclassingCheck.cpp - clang-tidy -----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/objc/ForbiddenSubclassingCheck.h b/clang-tidy/objc/ForbiddenSubclassingCheck.h
index 6c7e08b3..c05ba084 100644
--- a/clang-tidy/objc/ForbiddenSubclassingCheck.h
+++ b/clang-tidy/objc/ForbiddenSubclassingCheck.h
@@ -1,16 +1,15 @@
//===--- ForbiddenSubclassingCheck.h - clang-tidy ---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_OBJC_FORBIDDEN_SUBCLASSING_CHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_FORBIDDEN_SUBCLASSING_CHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "llvm/ADT/StringRef.h"
#include <string>
#include <vector>
diff --git a/clang-tidy/objc/ObjCTidyModule.cpp b/clang-tidy/objc/ObjCTidyModule.cpp
index 19152c21..636e2c02 100644
--- a/clang-tidy/objc/ObjCTidyModule.cpp
+++ b/clang-tidy/objc/ObjCTidyModule.cpp
@@ -1,9 +1,8 @@
//===--- ObjCTidyModule.cpp - clang-tidy --------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -14,6 +13,7 @@
#include "AvoidSpinlockCheck.h"
#include "ForbiddenSubclassingCheck.h"
#include "PropertyDeclarationCheck.h"
+#include "SuperSelfCheck.h"
using namespace clang::ast_matchers;
@@ -32,6 +32,8 @@ public:
"objc-forbidden-subclassing");
CheckFactories.registerCheck<PropertyDeclarationCheck>(
"objc-property-declaration");
+ CheckFactories.registerCheck<SuperSelfCheck>(
+ "objc-super-self");
}
};
diff --git a/clang-tidy/objc/PropertyDeclarationCheck.cpp b/clang-tidy/objc/PropertyDeclarationCheck.cpp
index 94b82f00..094c193c 100644
--- a/clang-tidy/objc/PropertyDeclarationCheck.cpp
+++ b/clang-tidy/objc/PropertyDeclarationCheck.cpp
@@ -1,9 +1,8 @@
//===--- PropertyDeclarationCheck.cpp - clang-tidy-------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -81,7 +80,8 @@ std::string validPropertyNameRegex(bool UsedInMatcher) {
}
bool hasCategoryPropertyPrefix(llvm::StringRef PropertyName) {
- auto RegexExp = llvm::Regex("^[a-zA-Z]+_[a-zA-Z0-9][a-zA-Z0-9_]+$");
+ auto RegexExp =
+ llvm::Regex("^[a-zA-Z][a-zA-Z0-9]*_[a-zA-Z0-9][a-zA-Z0-9_]+$");
return RegexExp.match(PropertyName);
}
@@ -92,31 +92,21 @@ bool prefixedPropertyNameValid(llvm::StringRef PropertyName) {
if (Prefix.lower() != Prefix) {
return false;
}
- auto RegexExp =
- llvm::Regex(llvm::StringRef(validPropertyNameRegex(false)));
+ auto RegexExp = llvm::Regex(llvm::StringRef(validPropertyNameRegex(false)));
return RegexExp.match(PropertyName.substr(Start + 1));
}
} // namespace
-PropertyDeclarationCheck::PropertyDeclarationCheck(StringRef Name,
- ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context),
- SpecialAcronyms(
- utils::options::parseStringList(Options.get("Acronyms", ""))),
- IncludeDefaultAcronyms(Options.get("IncludeDefaultAcronyms", true)),
- EscapedAcronyms() {}
-
void PropertyDeclarationCheck::registerMatchers(MatchFinder *Finder) {
// this check should only be applied to ObjC sources.
if (!getLangOpts().ObjC) return;
- Finder->addMatcher(
- objcPropertyDecl(
- // the property name should be in Lower Camel Case like
- // 'lowerCamelCase'
- unless(matchesName(validPropertyNameRegex(true))))
- .bind("property"),
- this);
+ Finder->addMatcher(objcPropertyDecl(
+ // the property name should be in Lower Camel Case like
+ // 'lowerCamelCase'
+ unless(matchesName(validPropertyNameRegex(true))))
+ .bind("property"),
+ this);
}
void PropertyDeclarationCheck::check(const MatchFinder::MatchResult &Result) {
@@ -146,12 +136,6 @@ void PropertyDeclarationCheck::check(const MatchFinder::MatchResult &Result) {
<< generateFixItHint(MatchedDecl, StandardProperty);
}
-void PropertyDeclarationCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
- Options.store(Opts, "Acronyms",
- utils::options::serializeStringList(SpecialAcronyms));
- Options.store(Opts, "IncludeDefaultAcronyms", IncludeDefaultAcronyms);
-}
-
} // namespace objc
} // namespace tidy
} // namespace clang
diff --git a/clang-tidy/objc/PropertyDeclarationCheck.h b/clang-tidy/objc/PropertyDeclarationCheck.h
index b2683bae..769f0c4c 100644
--- a/clang-tidy/objc/PropertyDeclarationCheck.h
+++ b/clang-tidy/objc/PropertyDeclarationCheck.h
@@ -1,18 +1,15 @@
//===--- PropertyDeclarationCheck.h - clang-tidy-----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_OBJC_PROPERTY_DECLARATION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_PROPERTY_DECLARATION_H
-#include "../ClangTidy.h"
-#include <string>
-#include <vector>
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
@@ -28,15 +25,10 @@ namespace objc {
/// http://clang.llvm.org/extra/clang-tidy/checks/objc-property-declaration.html
class PropertyDeclarationCheck : public ClangTidyCheck {
public:
- PropertyDeclarationCheck(StringRef Name, ClangTidyContext *Context);
+ PropertyDeclarationCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
- void storeOptions(ClangTidyOptions::OptionMap &Options) override;
-
-private:
- const std::vector<std::string> SpecialAcronyms;
- const bool IncludeDefaultAcronyms;
- std::vector<std::string> EscapedAcronyms;
};
} // namespace objc
diff --git a/clang-tidy/objc/SuperSelfCheck.cpp b/clang-tidy/objc/SuperSelfCheck.cpp
new file mode 100644
index 00000000..7aafd66a
--- /dev/null
+++ b/clang-tidy/objc/SuperSelfCheck.cpp
@@ -0,0 +1,127 @@
+//===--- SuperSelfCheck.cpp - clang-tidy ----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperSelfCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace objc {
+
+namespace {
+
+/// \brief Matches Objective-C methods in the initializer family.
+///
+/// Example matches -init and -initWithInt:.
+/// (matcher = objcMethodDecl(isInitializer()))
+/// \code
+/// @interface Foo
+/// - (instancetype)init;
+/// - (instancetype)initWithInt:(int)i;
+/// + (instancetype)init;
+/// - (void)bar;
+/// @end
+/// \endcode
+AST_MATCHER(ObjCMethodDecl, isInitializer) {
+ return Node.getMethodFamily() == OMF_init;
+}
+
+/// \brief Matches Objective-C implementations of classes that directly or
+/// indirectly have a superclass matching \c InterfaceDecl.
+///
+/// Note that a class is not considered to be a subclass of itself.
+///
+/// Example matches implementation declarations for Y and Z.
+/// (matcher = objcInterfaceDecl(isSubclassOf(hasName("X"))))
+/// \code
+/// @interface X
+/// @end
+/// @interface Y : X
+/// @end
+/// @implementation Y // directly derived
+/// @end
+/// @interface Z : Y
+/// @end
+/// @implementation Z // indirectly derived
+/// @end
+/// \endcode
+AST_MATCHER_P(ObjCImplementationDecl, isSubclassOf,
+ ast_matchers::internal::Matcher<ObjCInterfaceDecl>,
+ InterfaceDecl) {
+ // Check if any of the superclasses of the class match.
+ for (const ObjCInterfaceDecl *SuperClass =
+ Node.getClassInterface()->getSuperClass();
+ SuperClass != nullptr; SuperClass = SuperClass->getSuperClass()) {
+ if (InterfaceDecl.matches(*SuperClass, Finder, Builder))
+ return true;
+ }
+
+ // No matches found.
+ return false;
+}
+
+/// \brief Matches Objective-C message expressions where the receiver is the
+/// super instance.
+///
+/// Example matches the invocations of -banana and -orange.
+/// (matcher = objcMessageExpr(isMessagingSuperInstance()))
+/// \code
+/// - (void)banana {
+/// [self apple]
+/// [super banana];
+/// [super orange];
+/// }
+/// \endcode
+AST_MATCHER(ObjCMessageExpr, isMessagingSuperInstance) {
+ return Node.getReceiverKind() == ObjCMessageExpr::SuperInstance;
+}
+
+} // namespace
+
+void SuperSelfCheck::registerMatchers(MatchFinder *Finder) {
+ // This check should only be applied to Objective-C sources.
+ if (!getLangOpts().ObjC)
+ return;
+
+ Finder->addMatcher(
+ objcMessageExpr(
+ hasSelector("self"), isMessagingSuperInstance(),
+ hasAncestor(objcMethodDecl(isInitializer(),
+ hasDeclContext(objcImplementationDecl(
+ isSubclassOf(hasName("NSObject")))))))
+ .bind("message"),
+ this);
+}
+
+void SuperSelfCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *Message = Result.Nodes.getNodeAs<ObjCMessageExpr>("message");
+
+ auto Diag = diag(Message->getExprLoc(), "suspicious invocation of %0 in "
+ "initializer; did you mean to "
+ "invoke a superclass initializer?")
+ << Message->getMethodDecl();
+
+ SourceLocation ReceiverLoc = Message->getReceiverRange().getBegin();
+ if (ReceiverLoc.isMacroID() || ReceiverLoc.isInvalid())
+ return;
+
+ SourceLocation SelectorLoc = Message->getSelectorStartLoc();
+ if (SelectorLoc.isMacroID() || SelectorLoc.isInvalid())
+ return;
+
+ Diag << FixItHint::CreateReplacement(Message->getSourceRange(),
+ StringRef("[super init]"));
+}
+
+} // namespace objc
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/objc/SuperSelfCheck.h b/clang-tidy/objc/SuperSelfCheck.h
new file mode 100644
index 00000000..ed5d1cd0
--- /dev/null
+++ b/clang-tidy/objc/SuperSelfCheck.h
@@ -0,0 +1,36 @@
+//===--- SuperSelfCheck.h - clang-tidy --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_SUPERSELFCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_SUPERSELFCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace objc {
+
+/// Finds invocations of -self on super instances in initializers of subclasses
+/// of NSObject and recommends calling a superclass initializer instead.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/objc-super-self.html
+class SuperSelfCheck : public ClangTidyCheck {
+public:
+ SuperSelfCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace objc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_SUPERSELFCHECK_H
diff --git a/clang-tidy/openmp/CMakeLists.txt b/clang-tidy/openmp/CMakeLists.txt
new file mode 100644
index 00000000..bbd65f29
--- /dev/null
+++ b/clang-tidy/openmp/CMakeLists.txt
@@ -0,0 +1,14 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyOpenMPModule
+ ExceptionEscapeCheck.cpp
+ OpenMPTidyModule.cpp
+ UseDefaultNoneCheck.cpp
+
+ LINK_LIBS
+ clangAST
+ clangASTMatchers
+ clangBasic
+ clangTidy
+ clangTidyUtils
+ )
diff --git a/clang-tidy/openmp/ExceptionEscapeCheck.cpp b/clang-tidy/openmp/ExceptionEscapeCheck.cpp
new file mode 100644
index 00000000..c3894a6c
--- /dev/null
+++ b/clang-tidy/openmp/ExceptionEscapeCheck.cpp
@@ -0,0 +1,84 @@
+//===--- ExceptionEscapeCheck.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 "ExceptionEscapeCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/OpenMPClause.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtOpenMP.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchersMacros.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace openmp {
+
+ExceptionEscapeCheck::ExceptionEscapeCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ RawIgnoredExceptions(Options.get("IgnoredExceptions", "")) {
+ llvm::SmallVector<StringRef, 8> FunctionsThatShouldNotThrowVec,
+ IgnoredExceptionsVec;
+
+ llvm::StringSet<> IgnoredExceptions;
+ StringRef(RawIgnoredExceptions).split(IgnoredExceptionsVec, ",", -1, false);
+ llvm::transform(IgnoredExceptionsVec, IgnoredExceptionsVec.begin(),
+ [](StringRef S) { return S.trim(); });
+ IgnoredExceptions.insert(IgnoredExceptionsVec.begin(),
+ IgnoredExceptionsVec.end());
+ Tracer.ignoreExceptions(std::move(IgnoredExceptions));
+ Tracer.ignoreBadAlloc(true);
+}
+
+void ExceptionEscapeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "IgnoredExceptions", RawIgnoredExceptions);
+}
+
+void ExceptionEscapeCheck::registerMatchers(MatchFinder *Finder) {
+ // Don't register the check if OpenMP is not enabled; the OpenMP pragmas are
+ // completely ignored then, so no OpenMP entires will be present in the AST.
+ if (!getLangOpts().OpenMP)
+ return;
+ // Similarly, if C++ Exceptions are not enabled, nothing to do.
+ if (!getLangOpts().CPlusPlus || !getLangOpts().CXXExceptions)
+ return;
+
+ Finder->addMatcher(ompExecutableDirective(
+ unless(isStandaloneDirective()),
+ hasStructuredBlock(stmt().bind("structured-block")))
+ .bind("directive"),
+ this);
+}
+
+void ExceptionEscapeCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *Directive =
+ Result.Nodes.getNodeAs<OMPExecutableDirective>("directive");
+ assert(Directive && "Expected to match some OpenMP Executable directive.");
+ const auto *StructuredBlock =
+ Result.Nodes.getNodeAs<Stmt>("structured-block");
+ assert(StructuredBlock && "Expected to get some OpenMP Structured Block.");
+
+ if (Tracer.analyze(StructuredBlock).getBehaviour() !=
+ utils::ExceptionAnalyzer::State::Throwing)
+ return; // No exceptions have been proven to escape out of the struc. block.
+
+ // FIXME: We should provide more information about the exact location where
+ // the exception is thrown, maybe the full path the exception escapes.
+
+ diag(StructuredBlock->getBeginLoc(),
+ "an exception thrown inside of the OpenMP '%0' region is not caught in "
+ "that same region")
+ << getOpenMPDirectiveName(Directive->getDirectiveKind());
+}
+
+} // namespace openmp
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/openmp/ExceptionEscapeCheck.h b/clang-tidy/openmp/ExceptionEscapeCheck.h
new file mode 100644
index 00000000..bcbeccd5
--- /dev/null
+++ b/clang-tidy/openmp/ExceptionEscapeCheck.h
@@ -0,0 +1,41 @@
+//===--- ExceptionEscapeCheck.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_OPENMP_EXCEPTIONESCAPECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OPENMP_EXCEPTIONESCAPECHECK_H
+
+#include "../ClangTidy.h"
+#include "../utils/ExceptionAnalyzer.h"
+
+namespace clang {
+namespace tidy {
+namespace openmp {
+
+/// Analyzes OpenMP Structured Blocks and checks that no exception escapes
+/// out of the Structured Block it was thrown in.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/openmp-exception-escape.html
+class ExceptionEscapeCheck : public ClangTidyCheck {
+public:
+ ExceptionEscapeCheck(StringRef Name, ClangTidyContext *Context);
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ std::string RawIgnoredExceptions;
+
+ utils::ExceptionAnalyzer Tracer;
+};
+
+} // namespace openmp
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OPENMP_EXCEPTIONESCAPECHECK_H
diff --git a/clang-tidy/openmp/OpenMPTidyModule.cpp b/clang-tidy/openmp/OpenMPTidyModule.cpp
new file mode 100644
index 00000000..cb0e247e
--- /dev/null
+++ b/clang-tidy/openmp/OpenMPTidyModule.cpp
@@ -0,0 +1,41 @@
+//===--- OpenMPTidyModule.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 "../ClangTidy.h"
+#include "../ClangTidyModule.h"
+#include "../ClangTidyModuleRegistry.h"
+#include "ExceptionEscapeCheck.h"
+#include "UseDefaultNoneCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace openmp {
+
+/// This module is for OpenMP-specific checks.
+class OpenMPModule : public ClangTidyModule {
+public:
+ void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+ CheckFactories.registerCheck<ExceptionEscapeCheck>(
+ "openmp-exception-escape");
+ CheckFactories.registerCheck<UseDefaultNoneCheck>(
+ "openmp-use-default-none");
+ }
+};
+
+// Register the OpenMPTidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<OpenMPModule>
+ X("openmp-module", "Adds OpenMP-specific checks.");
+
+} // namespace openmp
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the OpenMPModule.
+volatile int OpenMPModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/openmp/UseDefaultNoneCheck.cpp b/clang-tidy/openmp/UseDefaultNoneCheck.cpp
new file mode 100644
index 00000000..d25498d5
--- /dev/null
+++ b/clang-tidy/openmp/UseDefaultNoneCheck.cpp
@@ -0,0 +1,65 @@
+//===--- UseDefaultNoneCheck.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 "UseDefaultNoneCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/OpenMPClause.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtOpenMP.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchersMacros.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace openmp {
+
+void UseDefaultNoneCheck::registerMatchers(MatchFinder *Finder) {
+ // Don't register the check if OpenMP is not enabled; the OpenMP pragmas are
+ // completely ignored then, so no OpenMP entires will be present in the AST.
+ if (!getLangOpts().OpenMP)
+ return;
+
+ Finder->addMatcher(
+ ompExecutableDirective(
+ allOf(isAllowedToContainClauseKind(OMPC_default),
+ anyOf(unless(hasAnyClause(ompDefaultClause())),
+ hasAnyClause(ompDefaultClause(unless(isNoneKind()))
+ .bind("clause")))))
+ .bind("directive"),
+ this);
+}
+
+void UseDefaultNoneCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *Directive =
+ Result.Nodes.getNodeAs<OMPExecutableDirective>("directive");
+ assert(Directive != nullptr && "Expected to match some directive.");
+
+ if (const auto *Clause = Result.Nodes.getNodeAs<OMPDefaultClause>("clause")) {
+ diag(Directive->getBeginLoc(),
+ "OpenMP directive '%0' specifies 'default(%1)' clause, consider using "
+ "'default(none)' clause instead")
+ << getOpenMPDirectiveName(Directive->getDirectiveKind())
+ << getOpenMPSimpleClauseTypeName(Clause->getClauseKind(),
+ Clause->getDefaultKind());
+ diag(Clause->getBeginLoc(), "existing 'default' clause specified here",
+ DiagnosticIDs::Note);
+ return;
+ }
+
+ diag(Directive->getBeginLoc(),
+ "OpenMP directive '%0' does not specify 'default' clause, consider "
+ "specifying 'default(none)' clause")
+ << getOpenMPDirectiveName(Directive->getDirectiveKind());
+}
+
+} // namespace openmp
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/openmp/UseDefaultNoneCheck.h b/clang-tidy/openmp/UseDefaultNoneCheck.h
new file mode 100644
index 00000000..c5ff8829
--- /dev/null
+++ b/clang-tidy/openmp/UseDefaultNoneCheck.h
@@ -0,0 +1,36 @@
+//===--- UseDefaultNoneCheck.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_OPENMP_USEDEFAULTNONECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OPENMP_USEDEFAULTNONECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace openmp {
+
+/// Finds OpenMP directives that are allowed to contain a ``default`` clause,
+/// but either don't specify it or the clause is specified but with the kind
+/// other than ``none``, and suggests to use the ``default(none)`` clause.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/openmp-use-default-none.html
+class UseDefaultNoneCheck : public ClangTidyCheck {
+public:
+ UseDefaultNoneCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace openmp
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OPENMP_USEDEFAULTNONECHECK_H
diff --git a/clang-tidy/performance/FasterStringFindCheck.cpp b/clang-tidy/performance/FasterStringFindCheck.cpp
index 0c3d249f..bb0a02f0 100644
--- a/clang-tidy/performance/FasterStringFindCheck.cpp
+++ b/clang-tidy/performance/FasterStringFindCheck.cpp
@@ -1,9 +1,8 @@
//===--- FasterStringFindCheck.cpp - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/FasterStringFindCheck.h b/clang-tidy/performance/FasterStringFindCheck.h
index ff666f2f..7d46d06c 100644
--- a/clang-tidy/performance/FasterStringFindCheck.h
+++ b/clang-tidy/performance/FasterStringFindCheck.h
@@ -1,16 +1,15 @@
//===--- FasterStringFindCheck.h - clang-tidy--------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_PERFORMANCE_FASTER_STRING_FIND_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_FASTER_STRING_FIND_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include <string>
#include <vector>
diff --git a/clang-tidy/performance/ForRangeCopyCheck.cpp b/clang-tidy/performance/ForRangeCopyCheck.cpp
index 4b90df43..e0040094 100644
--- a/clang-tidy/performance/ForRangeCopyCheck.cpp
+++ b/clang-tidy/performance/ForRangeCopyCheck.cpp
@@ -1,9 +1,8 @@
//===--- ForRangeCopyCheck.cpp - clang-tidy--------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/ForRangeCopyCheck.h b/clang-tidy/performance/ForRangeCopyCheck.h
index de8b2c91..3745c7bb 100644
--- a/clang-tidy/performance/ForRangeCopyCheck.h
+++ b/clang-tidy/performance/ForRangeCopyCheck.h
@@ -1,16 +1,15 @@
//===--- ForRangeCopyCheck.h - clang-tidy------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_PERFORMANCE_FORRANGECOPYCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_FORRANGECOPYCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp b/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp
index 6e731190..e3b90d3b 100644
--- a/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp
+++ b/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp
@@ -1,9 +1,8 @@
//===--- ImplicitConversionInLoopCheck.cpp - clang-tidy--------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/ImplicitConversionInLoopCheck.h b/clang-tidy/performance/ImplicitConversionInLoopCheck.h
index 55cb84c3..b372003a 100644
--- a/clang-tidy/performance/ImplicitConversionInLoopCheck.h
+++ b/clang-tidy/performance/ImplicitConversionInLoopCheck.h
@@ -1,16 +1,15 @@
//===--- ImplicitConversionInLoopCheck.h - clang-tidy------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_PERFORMANCE_IMPLICIT_CONVERSION_IN_LOOP_CHECK_H_
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CONVERSION_IN_LOOP_CHECK_H_
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/performance/InefficientAlgorithmCheck.cpp b/clang-tidy/performance/InefficientAlgorithmCheck.cpp
index 8cee2817..5ce5ffa0 100644
--- a/clang-tidy/performance/InefficientAlgorithmCheck.cpp
+++ b/clang-tidy/performance/InefficientAlgorithmCheck.cpp
@@ -1,9 +1,8 @@
//===--- InefficientAlgorithmCheck.cpp - clang-tidy------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/InefficientAlgorithmCheck.h b/clang-tidy/performance/InefficientAlgorithmCheck.h
index 72506cf7..b8a6d49e 100644
--- a/clang-tidy/performance/InefficientAlgorithmCheck.h
+++ b/clang-tidy/performance/InefficientAlgorithmCheck.h
@@ -1,16 +1,15 @@
//===--- InefficientAlgorithmCheck.h - clang-tidy----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_PERFORMANCE_INEFFICIENTALGORITHMCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_INEFFICIENTALGORITHMCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/performance/InefficientStringConcatenationCheck.cpp b/clang-tidy/performance/InefficientStringConcatenationCheck.cpp
index a17916d9..fe4b5a9e 100644
--- a/clang-tidy/performance/InefficientStringConcatenationCheck.cpp
+++ b/clang-tidy/performance/InefficientStringConcatenationCheck.cpp
@@ -1,9 +1,8 @@
//===--- InefficientStringConcatenationCheck.cpp - clang-tidy--------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/InefficientStringConcatenationCheck.h b/clang-tidy/performance/InefficientStringConcatenationCheck.h
index 12a154c2..83f27bb2 100644
--- a/clang-tidy/performance/InefficientStringConcatenationCheck.h
+++ b/clang-tidy/performance/InefficientStringConcatenationCheck.h
@@ -1,17 +1,16 @@
//===--- InefficientStringConcatenationCheck.h - clang-tidy-----------*- C++
//-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_PERFORMANCE_INEFFICIENTSTRINGCONCATENATION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_INEFFICIENTSTRINGCONCATENATION_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/performance/InefficientVectorOperationCheck.cpp b/clang-tidy/performance/InefficientVectorOperationCheck.cpp
index 5b083761..622649ac 100644
--- a/clang-tidy/performance/InefficientVectorOperationCheck.cpp
+++ b/clang-tidy/performance/InefficientVectorOperationCheck.cpp
@@ -1,9 +1,8 @@
//===--- InefficientVectorOperationCheck.cpp - clang-tidy------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/InefficientVectorOperationCheck.h b/clang-tidy/performance/InefficientVectorOperationCheck.h
index 1427ff13..bfd84d10 100644
--- a/clang-tidy/performance/InefficientVectorOperationCheck.h
+++ b/clang-tidy/performance/InefficientVectorOperationCheck.h
@@ -1,16 +1,15 @@
//===--- InefficientVectorOperationCheck.h - clang-tidy----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_PERFORMANCE_INEFFICIENT_VECTOR_OPERATION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_INEFFICIENT_VECTOR_OPERATION_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/performance/MoveConstArgCheck.cpp b/clang-tidy/performance/MoveConstArgCheck.cpp
index c64769f6..8b5838f9 100644
--- a/clang-tidy/performance/MoveConstArgCheck.cpp
+++ b/clang-tidy/performance/MoveConstArgCheck.cpp
@@ -1,9 +1,8 @@
//===--- MoveConstArgCheck.cpp - clang-tidy -----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/MoveConstArgCheck.h b/clang-tidy/performance/MoveConstArgCheck.h
index 13ed9aee..7fc10adb 100644
--- a/clang-tidy/performance/MoveConstArgCheck.h
+++ b/clang-tidy/performance/MoveConstArgCheck.h
@@ -1,16 +1,15 @@
//===--- MoveConstArgCheck.h - clang-tidy -------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_MISC_MOVECONSTANTARGUMENTCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MOVECONSTANTARGUMENTCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/performance/MoveConstructorInitCheck.cpp b/clang-tidy/performance/MoveConstructorInitCheck.cpp
index 52283fb2..aa5c8199 100644
--- a/clang-tidy/performance/MoveConstructorInitCheck.cpp
+++ b/clang-tidy/performance/MoveConstructorInitCheck.cpp
@@ -1,9 +1,8 @@
//===--- MoveConstructorInitCheck.cpp - clang-tidy-------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -92,10 +91,11 @@ void MoveConstructorInitCheck::check(const MatchFinder::MatchResult &Result) {
}
}
-void MoveConstructorInitCheck::registerPPCallbacks(CompilerInstance &Compiler) {
- Inserter.reset(new utils::IncludeInserter(
- Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle));
- Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+void MoveConstructorInitCheck::registerPPCallbacks(
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ Inserter = llvm::make_unique<utils::IncludeInserter>(SM, getLangOpts(),
+ IncludeStyle);
+ PP->addPPCallbacks(Inserter->CreatePPCallbacks());
}
void MoveConstructorInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
diff --git a/clang-tidy/performance/MoveConstructorInitCheck.h b/clang-tidy/performance/MoveConstructorInitCheck.h
index 3b7dda06..a84d0526 100644
--- a/clang-tidy/performance/MoveConstructorInitCheck.h
+++ b/clang-tidy/performance/MoveConstructorInitCheck.h
@@ -1,16 +1,15 @@
//===--- MoveConstructorInitCheck.h - clang-tidy-----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_PERFORMANCE_MOVECONSTRUCTORINITCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_MOVECONSTRUCTORINITCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "../utils/IncludeInserter.h"
#include <memory>
@@ -29,7 +28,8 @@ public:
MoveConstructorInitCheck(StringRef Name, ClangTidyContext *Context);
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
- void registerPPCallbacks(clang::CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
private:
diff --git a/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp b/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp
index adc5910b..0f9f8cba 100644
--- a/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp
+++ b/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp
@@ -1,9 +1,8 @@
//===--- NoexceptMoveConstructorCheck.cpp - clang-tidy---------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/NoexceptMoveConstructorCheck.h b/clang-tidy/performance/NoexceptMoveConstructorCheck.h
index 9687ab1f..bf000bd4 100644
--- a/clang-tidy/performance/NoexceptMoveConstructorCheck.h
+++ b/clang-tidy/performance/NoexceptMoveConstructorCheck.h
@@ -1,16 +1,15 @@
//===--- NoexceptMoveConstructorCheck.h - clang-tidy-------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_PERFORMANCE_NOEXCEPTMOVECONSTRUCTORCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_NOEXCEPTMOVECONSTRUCTORCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/performance/PerformanceTidyModule.cpp b/clang-tidy/performance/PerformanceTidyModule.cpp
index 646c6595..f4b620a1 100644
--- a/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -1,9 +1,8 @@
-//===--- PeformanceTidyModule.cpp - clang-tidy ----------------------------===//
+//===-- PerformanceTidyModule.cpp - clang-tidy ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/TypePromotionInMathFnCheck.cpp b/clang-tidy/performance/TypePromotionInMathFnCheck.cpp
index 8ff31a06..652a6f9e 100644
--- a/clang-tidy/performance/TypePromotionInMathFnCheck.cpp
+++ b/clang-tidy/performance/TypePromotionInMathFnCheck.cpp
@@ -1,9 +1,8 @@
//===--- TypePromotionInMathFnCheck.cpp - clang-tidy-----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -36,11 +35,10 @@ TypePromotionInMathFnCheck::TypePromotionInMathFnCheck(
Options.getLocalOrGlobal("IncludeStyle", "llvm"))) {}
void TypePromotionInMathFnCheck::registerPPCallbacks(
- CompilerInstance &Compiler) {
- IncludeInserter = llvm::make_unique<utils::IncludeInserter>(
- Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle);
- Compiler.getPreprocessor().addPPCallbacks(
- IncludeInserter->CreatePPCallbacks());
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ IncludeInserter = llvm::make_unique<utils::IncludeInserter>(SM, getLangOpts(),
+ IncludeStyle);
+ PP->addPPCallbacks(IncludeInserter->CreatePPCallbacks());
}
void TypePromotionInMathFnCheck::storeOptions(
diff --git a/clang-tidy/performance/TypePromotionInMathFnCheck.h b/clang-tidy/performance/TypePromotionInMathFnCheck.h
index 22429570..d1cc042c 100644
--- a/clang-tidy/performance/TypePromotionInMathFnCheck.h
+++ b/clang-tidy/performance/TypePromotionInMathFnCheck.h
@@ -1,16 +1,15 @@
//===--- TypePromotionInMathFnCheck.h - clang-tidy---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_PERFORMANCE_TYPE_PROMOTION_IN_MATH_FN_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_TYPE_PROMOTION_IN_MATH_FN_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "../utils/IncludeInserter.h"
namespace clang {
@@ -30,7 +29,8 @@ class TypePromotionInMathFnCheck : public ClangTidyCheck {
public:
TypePromotionInMathFnCheck(StringRef Name, ClangTidyContext *Context);
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
diff --git a/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
index 6f310573..7e36b374 100644
--- a/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ b/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -1,9 +1,8 @@
//===--- UnnecessaryCopyInitialization.cpp - clang-tidy--------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/UnnecessaryCopyInitialization.h b/clang-tidy/performance/UnnecessaryCopyInitialization.h
index 1844aa4b..0a530e37 100644
--- a/clang-tidy/performance/UnnecessaryCopyInitialization.h
+++ b/clang-tidy/performance/UnnecessaryCopyInitialization.h
@@ -1,16 +1,15 @@
//===--- UnnecessaryCopyInitialization.h - clang-tidy------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_PERFORMANCE_UNNECESSARY_COPY_INITIALIZATION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_UNNECESSARY_COPY_INITIALIZATION_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/performance/UnnecessaryValueParamCheck.cpp b/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
index ff3674fe..cf660815 100644
--- a/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ b/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -1,9 +1,8 @@
//===--- UnnecessaryValueParamCheck.cpp - clang-tidy-----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -169,10 +168,10 @@ void UnnecessaryValueParamCheck::check(const MatchFinder::MatchResult &Result) {
}
void UnnecessaryValueParamCheck::registerPPCallbacks(
- CompilerInstance &Compiler) {
- Inserter.reset(new utils::IncludeInserter(
- Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle));
- Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ Inserter = llvm::make_unique<utils::IncludeInserter>(SM, getLangOpts(),
+ IncludeStyle);
+ PP->addPPCallbacks(Inserter->CreatePPCallbacks());
}
void UnnecessaryValueParamCheck::storeOptions(
diff --git a/clang-tidy/performance/UnnecessaryValueParamCheck.h b/clang-tidy/performance/UnnecessaryValueParamCheck.h
index a1d65869..c9d22e6c 100644
--- a/clang-tidy/performance/UnnecessaryValueParamCheck.h
+++ b/clang-tidy/performance/UnnecessaryValueParamCheck.h
@@ -1,16 +1,15 @@
//===--- UnnecessaryValueParamCheck.h - clang-tidy---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_PERFORMANCE_UNNECESSARY_VALUE_PARAM_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_UNNECESSARY_VALUE_PARAM_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "../utils/IncludeInserter.h"
#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h"
@@ -28,7 +27,8 @@ public:
UnnecessaryValueParamCheck(StringRef Name, ClangTidyContext *Context);
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void onEndOfTranslationUnit() override;
diff --git a/clang-tidy/plugin/CMakeLists.txt b/clang-tidy/plugin/CMakeLists.txt
index 7a12d7fd..25b094f6 100644
--- a/clang-tidy/plugin/CMakeLists.txt
+++ b/clang-tidy/plugin/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPlugin
clangTidyMiscModule
clangTidyModernizeModule
clangTidyObjCModule
+ clangTidyOpenMPModule
clangTidyPerformanceModule
clangTidyPortabilityModule
clangTidyReadabilityModule
diff --git a/clang-tidy/plugin/ClangTidyPlugin.cpp b/clang-tidy/plugin/ClangTidyPlugin.cpp
index 561dc82d..80208c78 100644
--- a/clang-tidy/plugin/ClangTidyPlugin.cpp
+++ b/clang-tidy/plugin/ClangTidyPlugin.cpp
@@ -1,9 +1,8 @@
//===- ClangTidyPlugin.cpp - clang-tidy as a clang plugin -----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/portability/PortabilityTidyModule.cpp b/clang-tidy/portability/PortabilityTidyModule.cpp
index 013cbcfe..e12821e3 100644
--- a/clang-tidy/portability/PortabilityTidyModule.cpp
+++ b/clang-tidy/portability/PortabilityTidyModule.cpp
@@ -1,9 +1,8 @@
//===--- PortabilityTidyModule.cpp - clang-tidy ---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/portability/SIMDIntrinsicsCheck.cpp b/clang-tidy/portability/SIMDIntrinsicsCheck.cpp
index e104368f..d9e3d263 100644
--- a/clang-tidy/portability/SIMDIntrinsicsCheck.cpp
+++ b/clang-tidy/portability/SIMDIntrinsicsCheck.cpp
@@ -1,9 +1,8 @@
//===--- SIMDIntrinsicsCheck.cpp - clang-tidy------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/portability/SIMDIntrinsicsCheck.h b/clang-tidy/portability/SIMDIntrinsicsCheck.h
index ebcc8554..8f3a9902 100644
--- a/clang-tidy/portability/SIMDIntrinsicsCheck.h
+++ b/clang-tidy/portability/SIMDIntrinsicsCheck.h
@@ -1,16 +1,15 @@
//===--- SIMDIntrinsicsCheck.h - clang-tidy----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_SIMD_INTRINSICS_CHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SIMD_INTRINSICS_CHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "llvm/ADT/SmallString.h"
diff --git a/clang-tidy/readability/AvoidConstParamsInDecls.cpp b/clang-tidy/readability/AvoidConstParamsInDecls.cpp
index 51fc4895..91e1495e 100644
--- a/clang-tidy/readability/AvoidConstParamsInDecls.cpp
+++ b/clang-tidy/readability/AvoidConstParamsInDecls.cpp
@@ -1,9 +1,8 @@
//===--- AvoidConstParamsInDecls.cpp - clang-tidy--------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/AvoidConstParamsInDecls.h b/clang-tidy/readability/AvoidConstParamsInDecls.h
index f2d91e82..08aac949 100644
--- a/clang-tidy/readability/AvoidConstParamsInDecls.h
+++ b/clang-tidy/readability/AvoidConstParamsInDecls.h
@@ -1,16 +1,15 @@
//===--- AvoidConstParamsInDecls.h - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_AVOID_CONST_PARAMS_IN_DECLS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_AVOID_CONST_PARAMS_IN_DECLS_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/BracesAroundStatementsCheck.cpp b/clang-tidy/readability/BracesAroundStatementsCheck.cpp
index 5f5294c2..117ef36d 100644
--- a/clang-tidy/readability/BracesAroundStatementsCheck.cpp
+++ b/clang-tidy/readability/BracesAroundStatementsCheck.cpp
@@ -1,9 +1,8 @@
//===--- BracesAroundStatementsCheck.cpp - clang-tidy ---------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/BracesAroundStatementsCheck.h b/clang-tidy/readability/BracesAroundStatementsCheck.h
index 919ca463..7c019c6c 100644
--- a/clang-tidy/readability/BracesAroundStatementsCheck.h
+++ b/clang-tidy/readability/BracesAroundStatementsCheck.h
@@ -1,16 +1,15 @@
//===--- BracesAroundStatementsCheck.h - clang-tidy -------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_BRACESAROUNDSTATEMENTSCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_BRACESAROUNDSTATEMENTSCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/ConstReturnTypeCheck.cpp b/clang-tidy/readability/ConstReturnTypeCheck.cpp
index d9654df4..0f237ec8 100644
--- a/clang-tidy/readability/ConstReturnTypeCheck.cpp
+++ b/clang-tidy/readability/ConstReturnTypeCheck.cpp
@@ -1,9 +1,8 @@
//===--- ConstReturnTypeCheck.cpp - clang-tidy ---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -23,8 +22,8 @@ namespace readability {
// Finds the location of the qualifying `const` token in the `FunctionDecl`'s
// return type. Returns `None` when the return type is not `const`-qualified or
-// `const` does not appear in `Def`'s source like when the type is an alias or a
-// macro.
+// `const` does not appear in `Def`'s source, like when the type is an alias or
+// a macro.
static llvm::Optional<Token>
findConstToRemove(const FunctionDecl *Def,
const MatchFinder::MatchResult &Result) {
diff --git a/clang-tidy/readability/ConstReturnTypeCheck.h b/clang-tidy/readability/ConstReturnTypeCheck.h
index 2c7e94de..3a5fb08e 100644
--- a/clang-tidy/readability/ConstReturnTypeCheck.h
+++ b/clang-tidy/readability/ConstReturnTypeCheck.h
@@ -1,16 +1,15 @@
//===--- ConstReturnTypeCheck.h - clang-tidy --------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_CONSTRETURNTYPECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_CONSTRETURNTYPECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/ContainerSizeEmptyCheck.cpp b/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
index 97f9eb71..fe0e1c0a 100644
--- a/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
+++ b/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
@@ -1,9 +1,8 @@
//===--- ContainerSizeEmptyCheck.cpp - clang-tidy -------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "ContainerSizeEmptyCheck.h"
diff --git a/clang-tidy/readability/ContainerSizeEmptyCheck.h b/clang-tidy/readability/ContainerSizeEmptyCheck.h
index bde83f88..26a6b9ee 100644
--- a/clang-tidy/readability/ContainerSizeEmptyCheck.h
+++ b/clang-tidy/readability/ContainerSizeEmptyCheck.h
@@ -1,16 +1,15 @@
//===--- ContainerSizeEmptyCheck.h - clang-tidy -----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_CONTAINERSIZEEMPTYCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_CONTAINERSIZEEMPTYCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/DeleteNullPointerCheck.cpp b/clang-tidy/readability/DeleteNullPointerCheck.cpp
index 02b9bbe8..0c5eacef 100644
--- a/clang-tidy/readability/DeleteNullPointerCheck.cpp
+++ b/clang-tidy/readability/DeleteNullPointerCheck.cpp
@@ -1,9 +1,8 @@
//===--- DeleteNullPointerCheck.cpp - clang-tidy---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/DeleteNullPointerCheck.h b/clang-tidy/readability/DeleteNullPointerCheck.h
index 501f6f7d..0e310f79 100644
--- a/clang-tidy/readability/DeleteNullPointerCheck.h
+++ b/clang-tidy/readability/DeleteNullPointerCheck.h
@@ -1,16 +1,15 @@
//===--- DeleteNullPointerCheck.h - clang-tidy-------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_DELETE_NULL_POINTER_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DELETE_NULL_POINTER_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/DeletedDefaultCheck.cpp b/clang-tidy/readability/DeletedDefaultCheck.cpp
index e99ca837..ff2f00b9 100644
--- a/clang-tidy/readability/DeletedDefaultCheck.cpp
+++ b/clang-tidy/readability/DeletedDefaultCheck.cpp
@@ -1,9 +1,8 @@
//===--- DeletedDefaultCheck.cpp - clang-tidy------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/DeletedDefaultCheck.h b/clang-tidy/readability/DeletedDefaultCheck.h
index 0608b07b..ab7f1414 100644
--- a/clang-tidy/readability/DeletedDefaultCheck.h
+++ b/clang-tidy/readability/DeletedDefaultCheck.h
@@ -1,16 +1,15 @@
//===--- DeletedDefaultCheck.h - clang-tidy----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_DELETED_DEFAULT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DELETED_DEFAULT_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/ElseAfterReturnCheck.cpp b/clang-tidy/readability/ElseAfterReturnCheck.cpp
index be8de252..520586df 100644
--- a/clang-tidy/readability/ElseAfterReturnCheck.cpp
+++ b/clang-tidy/readability/ElseAfterReturnCheck.cpp
@@ -1,58 +1,63 @@
-//===--- ElseAfterReturnCheck.cpp - clang-tidy-----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ElseAfterReturnCheck.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Tooling/FixIt.h"
-
-using namespace clang::ast_matchers;
-
-namespace clang {
-namespace tidy {
-namespace readability {
-
-void ElseAfterReturnCheck::registerMatchers(MatchFinder *Finder) {
- const auto ControlFlowInterruptorMatcher =
- stmt(anyOf(returnStmt().bind("return"), continueStmt().bind("continue"),
- breakStmt().bind("break"),
- expr(ignoringImplicit(cxxThrowExpr().bind("throw")))));
- Finder->addMatcher(
- compoundStmt(forEach(
- ifStmt(unless(isConstexpr()),
- hasThen(stmt(
- anyOf(ControlFlowInterruptorMatcher,
- compoundStmt(has(ControlFlowInterruptorMatcher))))),
- hasElse(stmt().bind("else")))
- .bind("if"))),
- this);
-}
-
-void ElseAfterReturnCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
- SourceLocation ElseLoc = If->getElseLoc();
- std::string ControlFlowInterruptor;
- for (const auto *BindingName : {"return", "continue", "break", "throw"})
- if (Result.Nodes.getNodeAs<Stmt>(BindingName))
- ControlFlowInterruptor = BindingName;
-
- DiagnosticBuilder Diag = diag(ElseLoc, "do not use 'else' after '%0'")
- << ControlFlowInterruptor;
- Diag << tooling::fixit::createRemoval(ElseLoc);
-
- // FIXME: Removing the braces isn't always safe. Do a more careful analysis.
- // FIXME: Change clang-format to correctly un-indent the code.
- if (const auto *CS = Result.Nodes.getNodeAs<CompoundStmt>("else"))
- Diag << tooling::fixit::createRemoval(CS->getLBracLoc())
- << tooling::fixit::createRemoval(CS->getRBracLoc());
-}
-
-} // namespace readability
-} // namespace tidy
-} // namespace clang
+//===--- ElseAfterReturnCheck.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 "ElseAfterReturnCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void ElseAfterReturnCheck::registerMatchers(MatchFinder *Finder) {
+ const auto InterruptsControlFlow =
+ stmt(anyOf(returnStmt().bind("return"), continueStmt().bind("continue"),
+ breakStmt().bind("break"),
+ expr(ignoringImplicit(cxxThrowExpr().bind("throw")))));
+ Finder->addMatcher(
+ compoundStmt(forEach(
+ ifStmt(unless(isConstexpr()),
+ // FIXME: Explore alternatives for the
+ // `if (T x = ...) {... return; } else { <use x> }`
+ // pattern:
+ // * warn, but don't fix;
+ // * fix by pulling out the variable declaration out of
+ // the condition.
+ unless(hasConditionVariableStatement(anything())),
+ hasThen(stmt(anyOf(InterruptsControlFlow,
+ compoundStmt(has(InterruptsControlFlow))))),
+ hasElse(stmt().bind("else")))
+ .bind("if"))),
+ this);
+}
+
+void ElseAfterReturnCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
+ SourceLocation ElseLoc = If->getElseLoc();
+ std::string ControlFlowInterruptor;
+ for (const auto *BindingName : {"return", "continue", "break", "throw"})
+ if (Result.Nodes.getNodeAs<Stmt>(BindingName))
+ ControlFlowInterruptor = BindingName;
+
+ DiagnosticBuilder Diag = diag(ElseLoc, "do not use 'else' after '%0'")
+ << ControlFlowInterruptor;
+ Diag << tooling::fixit::createRemoval(ElseLoc);
+
+ // FIXME: Removing the braces isn't always safe. Do a more careful analysis.
+ // FIXME: Change clang-format to correctly un-indent the code.
+ if (const auto *CS = Result.Nodes.getNodeAs<CompoundStmt>("else"))
+ Diag << tooling::fixit::createRemoval(CS->getLBracLoc())
+ << tooling::fixit::createRemoval(CS->getRBracLoc());
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/readability/ElseAfterReturnCheck.h b/clang-tidy/readability/ElseAfterReturnCheck.h
index 8479ab50..0aa47b51 100644
--- a/clang-tidy/readability/ElseAfterReturnCheck.h
+++ b/clang-tidy/readability/ElseAfterReturnCheck.h
@@ -1,16 +1,15 @@
//===--- ElseAfterReturnCheck.h - clang-tidy---------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_ELSEAFTERRETURNCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_ELSEAFTERRETURNCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/FunctionSizeCheck.cpp b/clang-tidy/readability/FunctionSizeCheck.cpp
index 4d91f2e7..d98bec2e 100644
--- a/clang-tidy/readability/FunctionSizeCheck.cpp
+++ b/clang-tidy/readability/FunctionSizeCheck.cpp
@@ -1,9 +1,8 @@
-//===--- FunctionSize.cpp - clang-tidy ------------------------------------===//
+//===-- FunctionSizeCheck.cpp - clang-tidy --------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/FunctionSizeCheck.h b/clang-tidy/readability/FunctionSizeCheck.h
index 7defccdb..d85dbc92 100644
--- a/clang-tidy/readability/FunctionSizeCheck.h
+++ b/clang-tidy/readability/FunctionSizeCheck.h
@@ -1,16 +1,15 @@
//===--- FunctionSizeCheck.h - clang-tidy -----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_FUNCTIONSIZECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_FUNCTIONSIZECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tidy/readability/IdentifierNamingCheck.cpp
index fb3c02e1..7e56fe16 100644
--- a/clang-tidy/readability/IdentifierNamingCheck.cpp
+++ b/clang-tidy/readability/IdentifierNamingCheck.cpp
@@ -1,9 +1,8 @@
//===--- IdentifierNamingCheck.cpp - clang-tidy ---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -241,10 +240,11 @@ void IdentifierNamingCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(nestedNameSpecifierLoc().bind("nestedNameLoc"), this);
}
-void IdentifierNamingCheck::registerPPCallbacks(CompilerInstance &Compiler) {
- Compiler.getPreprocessor().addPPCallbacks(
- llvm::make_unique<IdentifierNamingCheckPPCallbacks>(
- &Compiler.getPreprocessor(), this));
+void IdentifierNamingCheck::registerPPCallbacks(
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ ModuleExpanderPP->addPPCallbacks(
+ llvm::make_unique<IdentifierNamingCheckPPCallbacks>(ModuleExpanderPP,
+ this));
}
static bool matchesStyle(StringRef Name,
diff --git a/clang-tidy/readability/IdentifierNamingCheck.h b/clang-tidy/readability/IdentifierNamingCheck.h
index c236ad52..b7487e00 100644
--- a/clang-tidy/readability/IdentifierNamingCheck.h
+++ b/clang-tidy/readability/IdentifierNamingCheck.h
@@ -1,16 +1,15 @@
//===--- IdentifierNamingCheck.h - clang-tidy -------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_IDENTIFIERNAMINGCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERNAMINGCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
@@ -39,7 +38,8 @@ public:
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
void onEndOfTranslationUnit() override;
enum CaseType {
diff --git a/clang-tidy/readability/ImplicitBoolConversionCheck.cpp b/clang-tidy/readability/ImplicitBoolConversionCheck.cpp
index b8ae224b..aae5bcff 100644
--- a/clang-tidy/readability/ImplicitBoolConversionCheck.cpp
+++ b/clang-tidy/readability/ImplicitBoolConversionCheck.cpp
@@ -1,9 +1,8 @@
//===--- ImplicitBoolConversionCheck.cpp - clang-tidy----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/ImplicitBoolConversionCheck.h b/clang-tidy/readability/ImplicitBoolConversionCheck.h
index bb062e02..db3dc20e 100644
--- a/clang-tidy/readability/ImplicitBoolConversionCheck.h
+++ b/clang-tidy/readability/ImplicitBoolConversionCheck.h
@@ -1,16 +1,15 @@
//===--- ImplicitBoolConversionCheck.h - clang-tidy--------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_IMPLICIT_BOOL_CONVERSION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CONVERSION_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.cpp b/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.cpp
index 280c354f..64a955f6 100644
--- a/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.cpp
+++ b/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.cpp
@@ -1,9 +1,8 @@
//===--- InconsistentDeclarationParameterNameCheck.cpp - clang-tidy-------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.h b/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.h
index 602856fa..94b48caa 100644
--- a/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.h
+++ b/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.h
@@ -1,16 +1,15 @@
//===- InconsistentDeclarationParameterNameCheck.h - clang-tidy-*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_INCONSISTENT_DECLARATION_PARAMETER_NAME_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_INCONSISTENT_DECLARATION_PARAMETER_NAME_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "llvm/ADT/DenseSet.h"
diff --git a/clang-tidy/readability/IsolateDeclarationCheck.cpp b/clang-tidy/readability/IsolateDeclarationCheck.cpp
index e9ccb17b..32177adf 100644
--- a/clang-tidy/readability/IsolateDeclarationCheck.cpp
+++ b/clang-tidy/readability/IsolateDeclarationCheck.cpp
@@ -1,9 +1,8 @@
//===--- IsolateDeclarationCheck.cpp - clang-tidy -------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/IsolateDeclarationCheck.h b/clang-tidy/readability/IsolateDeclarationCheck.h
index b7f4793d..29f547e5 100644
--- a/clang-tidy/readability/IsolateDeclarationCheck.h
+++ b/clang-tidy/readability/IsolateDeclarationCheck.h
@@ -1,16 +1,15 @@
//===--- IsolateDeclarationCheck.h - clang-tidy -----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_ISOLATEDECLCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_ISOLATEDECLCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/MagicNumbersCheck.cpp b/clang-tidy/readability/MagicNumbersCheck.cpp
index 0a087219..39aaf899 100644
--- a/clang-tidy/readability/MagicNumbersCheck.cpp
+++ b/clang-tidy/readability/MagicNumbersCheck.cpp
@@ -1,9 +1,8 @@
//===--- MagicNumbersCheck.cpp - clang-tidy-------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clang-tidy/readability/MagicNumbersCheck.h b/clang-tidy/readability/MagicNumbersCheck.h
index db4cc886..e59ca175 100644
--- a/clang-tidy/readability/MagicNumbersCheck.h
+++ b/clang-tidy/readability/MagicNumbersCheck.h
@@ -1,16 +1,15 @@
//===--- MagicNumbersCheck.h - clang-tidy-----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_MAGICNUMBERSCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MAGICNUMBERSCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include <llvm/ADT/APFloat.h>
#include <llvm/ADT/SmallVector.h>
#include <vector>
diff --git a/clang-tidy/readability/MisleadingIndentationCheck.cpp b/clang-tidy/readability/MisleadingIndentationCheck.cpp
index 9791531f..0fd5c1fc 100644
--- a/clang-tidy/readability/MisleadingIndentationCheck.cpp
+++ b/clang-tidy/readability/MisleadingIndentationCheck.cpp
@@ -1,9 +1,8 @@
//===--- MisleadingIndentationCheck.cpp - clang-tidy-----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -82,6 +81,10 @@ void MisleadingIndentationCheck::missingBracesCheck(const SourceManager &SM,
SourceLocation InnerLoc = Inner->getBeginLoc();
SourceLocation OuterLoc = CurrentStmt->getBeginLoc();
+ if (InnerLoc.isInvalid() || InnerLoc.isMacroID() || OuterLoc.isInvalid() ||
+ OuterLoc.isMacroID())
+ continue;
+
if (SM.getExpansionLineNumber(InnerLoc) ==
SM.getExpansionLineNumber(OuterLoc))
continue;
@@ -89,7 +92,7 @@ void MisleadingIndentationCheck::missingBracesCheck(const SourceManager &SM,
const Stmt *NextStmt = CStmt->body_begin()[i + 1];
SourceLocation NextLoc = NextStmt->getBeginLoc();
- if (InnerLoc.isMacroID() || OuterLoc.isMacroID() || NextLoc.isMacroID())
+ if (NextLoc.isInvalid() || NextLoc.isMacroID())
continue;
if (SM.getExpansionColumnNumber(InnerLoc) ==
diff --git a/clang-tidy/readability/MisleadingIndentationCheck.h b/clang-tidy/readability/MisleadingIndentationCheck.h
index 0ca50bb0..ed5ba5ba 100644
--- a/clang-tidy/readability/MisleadingIndentationCheck.h
+++ b/clang-tidy/readability/MisleadingIndentationCheck.h
@@ -1,16 +1,15 @@
//===--- MisleadingIndentationCheck.h - clang-tidy---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_MISLEADING_INDENTATION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MISLEADING_INDENTATION_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/MisplacedArrayIndexCheck.cpp b/clang-tidy/readability/MisplacedArrayIndexCheck.cpp
index 3d1971be..7b39012b 100644
--- a/clang-tidy/readability/MisplacedArrayIndexCheck.cpp
+++ b/clang-tidy/readability/MisplacedArrayIndexCheck.cpp
@@ -1,9 +1,8 @@
//===--- MisplacedArrayIndexCheck.cpp - clang-tidy-------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/MisplacedArrayIndexCheck.h b/clang-tidy/readability/MisplacedArrayIndexCheck.h
index e9a22314..e4256b53 100644
--- a/clang-tidy/readability/MisplacedArrayIndexCheck.h
+++ b/clang-tidy/readability/MisplacedArrayIndexCheck.h
@@ -1,16 +1,15 @@
//===--- MisplacedArrayIndexCheck.h - clang-tidy-----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_MISPLACED_ARRAY_INDEX_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MISPLACED_ARRAY_INDEX_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/NamedParameterCheck.cpp b/clang-tidy/readability/NamedParameterCheck.cpp
index 6fa9e68f..09b03fe7 100644
--- a/clang-tidy/readability/NamedParameterCheck.cpp
+++ b/clang-tidy/readability/NamedParameterCheck.cpp
@@ -1,9 +1,8 @@
//===--- NamedParameterCheck.cpp - clang-tidy -------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/NamedParameterCheck.h b/clang-tidy/readability/NamedParameterCheck.h
index bd38ad2f..33a51b4c 100644
--- a/clang-tidy/readability/NamedParameterCheck.h
+++ b/clang-tidy/readability/NamedParameterCheck.h
@@ -1,16 +1,15 @@
//===--- NamedParameterCheck.h - clang-tidy ---------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_NAMEDPARAMETERCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NAMEDPARAMETERCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/NamespaceCommentCheck.cpp b/clang-tidy/readability/NamespaceCommentCheck.cpp
index 229cc626..6428f8cd 100644
--- a/clang-tidy/readability/NamespaceCommentCheck.cpp
+++ b/clang-tidy/readability/NamespaceCommentCheck.cpp
@@ -1,9 +1,8 @@
//===--- NamespaceCommentCheck.cpp - clang-tidy ---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -103,11 +102,14 @@ void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
}
}
+ // FIXME: This probably breaks on comments between the namespace and its '{'.
auto TextRange =
Lexer::getAsCharRange(SourceRange(NestedNamespaceBegin, LBracketLocation),
Sources, getLangOpts());
StringRef NestedNamespaceName =
- Lexer::getSourceText(TextRange, Sources, getLangOpts()).rtrim();
+ Lexer::getSourceText(TextRange, Sources, getLangOpts())
+ .rtrim('{') // Drop the { itself.
+ .rtrim(); // Drop any whitespace before it.
bool IsNested = NestedNamespaceName.contains(':');
if (IsNested)
diff --git a/clang-tidy/readability/NamespaceCommentCheck.h b/clang-tidy/readability/NamespaceCommentCheck.h
index 1b1a2315..712cd466 100644
--- a/clang-tidy/readability/NamespaceCommentCheck.h
+++ b/clang-tidy/readability/NamespaceCommentCheck.h
@@ -1,16 +1,15 @@
//===--- NamespaceCommentCheck.h - clang-tidy -------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_NAMESPACECOMMENTCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NAMESPACECOMMENTCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "llvm/Support/Regex.h"
namespace clang {
diff --git a/clang-tidy/readability/NonConstParameterCheck.cpp b/clang-tidy/readability/NonConstParameterCheck.cpp
index e33191cf..4372e74c 100644
--- a/clang-tidy/readability/NonConstParameterCheck.cpp
+++ b/clang-tidy/readability/NonConstParameterCheck.cpp
@@ -1,9 +1,8 @@
//===--- NonConstParameterCheck.cpp - clang-tidy---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/NonConstParameterCheck.h b/clang-tidy/readability/NonConstParameterCheck.h
index 3cc73e90..39959e61 100644
--- a/clang-tidy/readability/NonConstParameterCheck.h
+++ b/clang-tidy/readability/NonConstParameterCheck.h
@@ -1,16 +1,15 @@
//===--- NonConstParameterCheck.h - clang-tidy-------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_NON_CONST_PARAMETER_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NON_CONST_PARAMETER_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tidy/readability/ReadabilityTidyModule.cpp
index e032d1f6..5b2aed42 100644
--- a/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -1,9 +1,8 @@
//===--- ReadabilityTidyModule.cpp - clang-tidy ---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/RedundantControlFlowCheck.cpp b/clang-tidy/readability/RedundantControlFlowCheck.cpp
index d5898ed9..003c05f8 100644
--- a/clang-tidy/readability/RedundantControlFlowCheck.cpp
+++ b/clang-tidy/readability/RedundantControlFlowCheck.cpp
@@ -1,9 +1,8 @@
//===--- RedundantControlFlowCheck.cpp - clang-tidy------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/RedundantControlFlowCheck.h b/clang-tidy/readability/RedundantControlFlowCheck.h
index 4b8b6fbf..d4513e6f 100644
--- a/clang-tidy/readability/RedundantControlFlowCheck.h
+++ b/clang-tidy/readability/RedundantControlFlowCheck.h
@@ -1,16 +1,15 @@
//===--- RedundantControlFlowCheck.h - clang-tidy----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_REDUNDANT_CONTROL_FLOW_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_CONTROL_FLOW_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/RedundantDeclarationCheck.cpp b/clang-tidy/readability/RedundantDeclarationCheck.cpp
index c5b6cc32..ff3809a2 100644
--- a/clang-tidy/readability/RedundantDeclarationCheck.cpp
+++ b/clang-tidy/readability/RedundantDeclarationCheck.cpp
@@ -1,9 +1,8 @@
//===--- RedundantDeclarationCheck.cpp - clang-tidy------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/RedundantDeclarationCheck.h b/clang-tidy/readability/RedundantDeclarationCheck.h
index 9be79b84..fbd05396 100644
--- a/clang-tidy/readability/RedundantDeclarationCheck.h
+++ b/clang-tidy/readability/RedundantDeclarationCheck.h
@@ -1,16 +1,15 @@
//===--- RedundantDeclarationCheck.h - clang-tidy----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_REDUNDANT_DECLARATION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_DECLARATION_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp b/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp
index fa503c57..f2360a09 100644
--- a/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp
+++ b/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp
@@ -1,9 +1,8 @@
//===--- RedundantFunctionPtrDereferenceCheck.cpp - clang-tidy-------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.h b/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.h
index 4cf6d112..7a284b3c 100644
--- a/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.h
+++ b/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.h
@@ -1,16 +1,15 @@
//===--- RedundantFunctionPtrDereferenceCheck.h - clang-tidy-----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_REDUNDANT_FUNCTION_PTR_DEREFERENCE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_FUNCTION_PTR_DEREFERENCE_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/RedundantMemberInitCheck.cpp b/clang-tidy/readability/RedundantMemberInitCheck.cpp
index 8409f9f4..d38d0a23 100644
--- a/clang-tidy/readability/RedundantMemberInitCheck.cpp
+++ b/clang-tidy/readability/RedundantMemberInitCheck.cpp
@@ -1,9 +1,8 @@
//===--- RedundantMemberInitCheck.cpp - clang-tidy-------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/RedundantMemberInitCheck.h b/clang-tidy/readability/RedundantMemberInitCheck.h
index 13cc9d3a..73ced118 100644
--- a/clang-tidy/readability/RedundantMemberInitCheck.h
+++ b/clang-tidy/readability/RedundantMemberInitCheck.h
@@ -1,16 +1,15 @@
//===--- RedundantMemberInitCheck.h - clang-tidy----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_REDUNDANT_MEMBER_INIT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_MEMBER_INIT_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/RedundantPreprocessorCheck.cpp b/clang-tidy/readability/RedundantPreprocessorCheck.cpp
index 352e2346..ea46d533 100644
--- a/clang-tidy/readability/RedundantPreprocessorCheck.cpp
+++ b/clang-tidy/readability/RedundantPreprocessorCheck.cpp
@@ -1,9 +1,8 @@
//===--- RedundantPreprocessorCheck.cpp - clang-tidy ----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -98,10 +97,9 @@ private:
} // namespace
void RedundantPreprocessorCheck::registerPPCallbacks(
- CompilerInstance &Compiler) {
- Compiler.getPreprocessor().addPPCallbacks(
- ::llvm::make_unique<RedundantPreprocessorCallbacks>(
- *this, Compiler.getPreprocessor()));
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ PP->addPPCallbacks(
+ ::llvm::make_unique<RedundantPreprocessorCallbacks>(*this, *PP));
}
} // namespace readability
diff --git a/clang-tidy/readability/RedundantPreprocessorCheck.h b/clang-tidy/readability/RedundantPreprocessorCheck.h
index d4407656..af4ccaa4 100644
--- a/clang-tidy/readability/RedundantPreprocessorCheck.h
+++ b/clang-tidy/readability/RedundantPreprocessorCheck.h
@@ -1,16 +1,15 @@
//===--- RedundantPreprocessorCheck.h - clang-tidy --------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_REDUNDANTPREPROCESSORCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTPREPROCESSORCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
@@ -25,7 +24,8 @@ class RedundantPreprocessorCheck : public ClangTidyCheck {
public:
RedundantPreprocessorCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
};
} // namespace readability
diff --git a/clang-tidy/readability/RedundantSmartptrGetCheck.cpp b/clang-tidy/readability/RedundantSmartptrGetCheck.cpp
index 189130ef..834c0cba 100644
--- a/clang-tidy/readability/RedundantSmartptrGetCheck.cpp
+++ b/clang-tidy/readability/RedundantSmartptrGetCheck.cpp
@@ -1,9 +1,8 @@
//===--- RedundantSmartptrGetCheck.cpp - clang-tidy -----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -31,6 +30,10 @@ internal::Matcher<Expr> callToGet(const internal::Matcher<Decl> &OnClass) {
.bind("redundant_get");
}
+internal::Matcher<Decl> knownSmartptr() {
+ return recordDecl(hasAnyName("::std::unique_ptr", "::std::shared_ptr"));
+}
+
void registerMatchersForGetArrowStart(MatchFinder *Finder,
MatchFinder::MatchCallback *Callback) {
const auto QuacksLikeASmartptr = recordDecl(
@@ -40,21 +43,23 @@ void registerMatchersForGetArrowStart(MatchFinder *Finder,
has(cxxMethodDecl(hasName("operator*"), returns(qualType(references(
type().bind("op*Type")))))));
+ // Make sure we are not missing the known standard types.
+ const auto Smartptr = anyOf(knownSmartptr(), QuacksLikeASmartptr);
+
// Catch 'ptr.get()->Foo()'
- Finder->addMatcher(memberExpr(expr().bind("memberExpr"), isArrow(),
- hasObjectExpression(ignoringImpCasts(
- callToGet(QuacksLikeASmartptr)))),
- Callback);
+ Finder->addMatcher(
+ memberExpr(expr().bind("memberExpr"), isArrow(),
+ hasObjectExpression(ignoringImpCasts(callToGet(Smartptr)))),
+ Callback);
// Catch '*ptr.get()' or '*ptr->get()'
Finder->addMatcher(
- unaryOperator(hasOperatorName("*"),
- hasUnaryOperand(callToGet(QuacksLikeASmartptr))),
+ unaryOperator(hasOperatorName("*"), hasUnaryOperand(callToGet(Smartptr))),
Callback);
// Catch '!ptr.get()'
- const auto CallToGetAsBool = ignoringParenImpCasts(callToGet(recordDecl(
- QuacksLikeASmartptr, has(cxxConversionDecl(returns(booleanType()))))));
+ const auto CallToGetAsBool = ignoringParenImpCasts(callToGet(
+ recordDecl(Smartptr, has(cxxConversionDecl(returns(booleanType()))))));
Finder->addMatcher(
unaryOperator(hasOperatorName("!"), hasUnaryOperand(CallToGetAsBool)),
Callback);
@@ -72,10 +77,7 @@ void registerMatchersForGetEquals(MatchFinder *Finder,
// This one is harder to do with duck typing.
// The operator==/!= that we are looking for might be member or non-member,
// might be on global namespace or found by ADL, might be a template, etc.
- // For now, lets keep a list of known standard types.
-
- const auto IsAKnownSmartptr =
- recordDecl(hasAnyName("::std::unique_ptr", "::std::shared_ptr"));
+ // For now, lets keep it to the known standard types.
// Matches against nullptr.
Finder->addMatcher(
@@ -83,7 +85,7 @@ void registerMatchersForGetEquals(MatchFinder *Finder,
hasEitherOperand(ignoringImpCasts(
anyOf(cxxNullPtrLiteralExpr(), gnuNullExpr(),
integerLiteral(equals(0))))),
- hasEitherOperand(callToGet(IsAKnownSmartptr))),
+ hasEitherOperand(callToGet(knownSmartptr()))),
Callback);
// FIXME: Match and fix if (l.get() == r.get()).
diff --git a/clang-tidy/readability/RedundantSmartptrGetCheck.h b/clang-tidy/readability/RedundantSmartptrGetCheck.h
index a6f5706c..66c13542 100644
--- a/clang-tidy/readability/RedundantSmartptrGetCheck.h
+++ b/clang-tidy/readability/RedundantSmartptrGetCheck.h
@@ -1,16 +1,15 @@
//===--- RedundantSmartptrGetCheck.h - clang-tidy ---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_REDUNDANTSMARTPTRGETCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTSMARTPTRGETCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/RedundantStringCStrCheck.cpp b/clang-tidy/readability/RedundantStringCStrCheck.cpp
index 903a0ed1..f7b0dfc4 100644
--- a/clang-tidy/readability/RedundantStringCStrCheck.cpp
+++ b/clang-tidy/readability/RedundantStringCStrCheck.cpp
@@ -1,9 +1,8 @@
//===- RedundantStringCStrCheck.cpp - Check for redundant c_str calls -----===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clang-tidy/readability/RedundantStringCStrCheck.h b/clang-tidy/readability/RedundantStringCStrCheck.h
index 9406f8ea..0448865f 100644
--- a/clang-tidy/readability/RedundantStringCStrCheck.h
+++ b/clang-tidy/readability/RedundantStringCStrCheck.h
@@ -1,16 +1,15 @@
//===--- RedundantStringCStrCheck.h - clang-tidy ----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_REDUNDANTSTRINGCSTRCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTSTRINGCSTRCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/RedundantStringInitCheck.cpp b/clang-tidy/readability/RedundantStringInitCheck.cpp
index 46ce2a47..9a9a3830 100644
--- a/clang-tidy/readability/RedundantStringInitCheck.cpp
+++ b/clang-tidy/readability/RedundantStringInitCheck.cpp
@@ -1,9 +1,8 @@
//===- RedundantStringInitCheck.cpp - clang-tidy ----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/RedundantStringInitCheck.h b/clang-tidy/readability/RedundantStringInitCheck.h
index 0a32eb6d..b1f551ed 100644
--- a/clang-tidy/readability/RedundantStringInitCheck.h
+++ b/clang-tidy/readability/RedundantStringInitCheck.h
@@ -1,16 +1,15 @@
//===- RedundantStringInitCheck.h - clang-tidy ------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_REDUNDANT_STRING_INIT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_STRING_INIT_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/SimplifyBooleanExprCheck.cpp b/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
index 710635ee..ef88d44f 100644
--- a/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
+++ b/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
@@ -1,9 +1,8 @@
-//===--- SimplifyBooleanExpr.cpp clang-tidy ---------------------*- C++ -*-===//
+//===-- SimplifyBooleanExprCheck.cpp - clang-tidy -------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/SimplifyBooleanExprCheck.h b/clang-tidy/readability/SimplifyBooleanExprCheck.h
index af47453f..06495361 100644
--- a/clang-tidy/readability/SimplifyBooleanExprCheck.h
+++ b/clang-tidy/readability/SimplifyBooleanExprCheck.h
@@ -1,16 +1,15 @@
//===--- SimplifyBooleanExpr.h clang-tidy -----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_SIMPLIFY_BOOLEAN_EXPR_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SIMPLIFY_BOOLEAN_EXPR_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/SimplifySubscriptExprCheck.cpp b/clang-tidy/readability/SimplifySubscriptExprCheck.cpp
index f4c306e9..ec060f86 100644
--- a/clang-tidy/readability/SimplifySubscriptExprCheck.cpp
+++ b/clang-tidy/readability/SimplifySubscriptExprCheck.cpp
@@ -1,9 +1,8 @@
//===--- SimplifySubscriptExprCheck.cpp - clang-tidy-----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/SimplifySubscriptExprCheck.h b/clang-tidy/readability/SimplifySubscriptExprCheck.h
index 86a21b91..01d4e4bf 100644
--- a/clang-tidy/readability/SimplifySubscriptExprCheck.h
+++ b/clang-tidy/readability/SimplifySubscriptExprCheck.h
@@ -1,16 +1,15 @@
//===--- SimplifySubscriptExprCheck.h - clang-tidy---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_SIMPLIFYSUBSCRIPTEXPRCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SIMPLIFYSUBSCRIPTEXPRCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
index 92d78796..8458fe3c 100644
--- a/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
+++ b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
@@ -1,9 +1,8 @@
//===--- StaticAccessedThroughInstanceCheck.cpp - clang-tidy---------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h
index c2eebabe..3d4d5e70 100644
--- a/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h
+++ b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h
@@ -1,16 +1,15 @@
//===--- StaticAccessedThroughInstanceCheck.h - clang-tidy-------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_STATIC_ACCESSED_THROUGH_INSTANCE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STATIC_ACCESSED_THROUGH_INSTANCE_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.cpp b/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.cpp
index 05546052..ef973a19 100644
--- a/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.cpp
+++ b/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.cpp
@@ -1,9 +1,8 @@
//===--- StaticDefinitionInAnonymousNamespaceCheck.cpp - clang-tidy--------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h b/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h
index 03e99fd0..18f93b8a 100644
--- a/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h
+++ b/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h
@@ -1,16 +1,15 @@
//===--- StaticDefinitionInAnonymousNamespaceCheck.h - clang-tidy*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_STATIC_DEFINITION_IN_ANONYMOUS_NAMESPACE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STATIC_DEFINITION_IN_ANONYMOUS_NAMESPACE_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/StringCompareCheck.cpp b/clang-tidy/readability/StringCompareCheck.cpp
index 38ac43f2..1064c3a8 100644
--- a/clang-tidy/readability/StringCompareCheck.cpp
+++ b/clang-tidy/readability/StringCompareCheck.cpp
@@ -1,9 +1,8 @@
-//===--- MiscStringCompare.cpp - clang-tidy--------------------------------===//
+//===-- StringCompareCheck.cpp - clang-tidy--------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/StringCompareCheck.h b/clang-tidy/readability/StringCompareCheck.h
index 248d2ee8..d58cce6a 100644
--- a/clang-tidy/readability/StringCompareCheck.h
+++ b/clang-tidy/readability/StringCompareCheck.h
@@ -1,16 +1,15 @@
//===--- StringCompareCheck.h - clang-tidy-----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_STRINGCOMPARECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STRINGCOMPARECHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp b/clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp
index bb2c6901..478a3f2f 100644
--- a/clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp
+++ b/clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp
@@ -1,9 +1,8 @@
//===--- UniqueptrDeleteReleaseCheck.cpp - clang-tidy----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/UniqueptrDeleteReleaseCheck.h b/clang-tidy/readability/UniqueptrDeleteReleaseCheck.h
index fd86bdb9..3e6f184b 100644
--- a/clang-tidy/readability/UniqueptrDeleteReleaseCheck.h
+++ b/clang-tidy/readability/UniqueptrDeleteReleaseCheck.h
@@ -1,16 +1,15 @@
//===--- UniqueptrDeleteReleaseCheck.h - clang-tidy--------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_UNIQUEPTR_DELETE_RELEASE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_UNIQUEPTR_DELETE_RELEASE_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
diff --git a/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp b/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp
index 588fb261..eef63b7e 100644
--- a/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp
+++ b/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp
@@ -1,9 +1,8 @@
//===--- UppercaseLiteralSuffixCheck.cpp - clang-tidy ---------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/UppercaseLiteralSuffixCheck.h b/clang-tidy/readability/UppercaseLiteralSuffixCheck.h
index 7aa631ae..c31fc06c 100644
--- a/clang-tidy/readability/UppercaseLiteralSuffixCheck.h
+++ b/clang-tidy/readability/UppercaseLiteralSuffixCheck.h
@@ -1,16 +1,15 @@
//===--- UppercaseLiteralSuffixCheck.h - clang-tidy -------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_READABILITY_UPPERCASELITERALSUFFIXCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_UPPERCASELITERALSUFFIXCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "../utils/OptionsUtils.h"
namespace clang {
diff --git a/clang-tidy/rename_check.py b/clang-tidy/rename_check.py
index 53a5ff92..4eb3d740 100755
--- a/clang-tidy/rename_check.py
+++ b/clang-tidy/rename_check.py
@@ -2,10 +2,9 @@
#
#===- rename_check.py - clang-tidy check renamer -------------*- python -*--===#
#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
+# 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
#
#===------------------------------------------------------------------------===#
diff --git a/clang-tidy/tool/CMakeLists.txt b/clang-tidy/tool/CMakeLists.txt
index f58cfea5..71d57ff5 100644
--- a/clang-tidy/tool/CMakeLists.txt
+++ b/clang-tidy/tool/CMakeLists.txt
@@ -9,7 +9,7 @@ add_clang_tool(clang-tidy
ClangTidyMain.cpp
)
add_dependencies(clang-tidy
- clang-headers
+ clang-resource-headers
)
target_link_libraries(clang-tidy
PRIVATE
@@ -30,6 +30,7 @@ target_link_libraries(clang-tidy
clangTidyMiscModule
clangTidyModernizeModule
clangTidyObjCModule
+ clangTidyOpenMPModule
clangTidyPerformanceModule
clangTidyPortabilityModule
clangTidyReadabilityModule
diff --git a/clang-tidy/tool/ClangTidyMain.cpp b/clang-tidy/tool/ClangTidyMain.cpp
index 12a60244..06291e9d 100644
--- a/clang-tidy/tool/ClangTidyMain.cpp
+++ b/clang-tidy/tool/ClangTidyMain.cpp
@@ -1,9 +1,8 @@
//===--- tools/extra/clang-tidy/ClangTidyMain.cpp - Clang tidy tool -------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
@@ -305,11 +304,10 @@ static std::unique_ptr<ClangTidyOptionsProvider> createOptionsProvider(
}
llvm::IntrusiveRefCntPtr<vfs::FileSystem>
-getVfsOverlayFromFile(const std::string &OverlayFile) {
- llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFS(
- new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+getVfsFromFile(const std::string &OverlayFile,
+ llvm::IntrusiveRefCntPtr<vfs::FileSystem> BaseFS) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
- OverlayFS->getBufferForFile(OverlayFile);
+ BaseFS->getBufferForFile(OverlayFile);
if (!Buffer) {
llvm::errs() << "Can't load virtual filesystem overlay file '"
<< OverlayFile << "': " << Buffer.getError().message()
@@ -324,19 +322,23 @@ getVfsOverlayFromFile(const std::string &OverlayFile) {
<< OverlayFile << "'.\n";
return nullptr;
}
- OverlayFS->pushOverlay(FS);
- return OverlayFS;
+ return FS;
}
static int clangTidyMain(int argc, const char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
CommonOptionsParser OptionsParser(argc, argv, ClangTidyCategory,
cl::ZeroOrMore);
- llvm::IntrusiveRefCntPtr<vfs::FileSystem> BaseFS(
- VfsOverlay.empty() ? vfs::getRealFileSystem()
- : getVfsOverlayFromFile(VfsOverlay));
- if (!BaseFS)
- return 1;
+ llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> BaseFS(
+ new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+
+ if (!VfsOverlay.empty()) {
+ IntrusiveRefCntPtr<vfs::FileSystem> VfsFromFile =
+ getVfsFromFile(VfsOverlay, BaseFS);
+ if (!VfsFromFile)
+ return 1;
+ BaseFS->pushOverlay(VfsFromFile);
+ }
auto OwningOptionsProvider = createOptionsProvider(BaseFS);
auto *OptionsProvider = OwningOptionsProvider.get();
diff --git a/clang-tidy/tool/clang-tidy-diff.py b/clang-tidy/tool/clang-tidy-diff.py
index 5eb2e3d6..8b6ad904 100755
--- a/clang-tidy/tool/clang-tidy-diff.py
+++ b/clang-tidy/tool/clang-tidy-diff.py
@@ -2,10 +2,9 @@
#
#===- clang-tidy-diff.py - ClangTidy Diff Checker ------------*- python -*--===#
#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
+# 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
#
#===------------------------------------------------------------------------===#
@@ -25,10 +24,94 @@ Example usage for git/svn users:
"""
import argparse
+import glob
import json
+import multiprocessing
+import os
import re
+import shutil
import subprocess
import sys
+import tempfile
+import threading
+import traceback
+
+try:
+ import yaml
+except ImportError:
+ yaml = None
+
+is_py2 = sys.version[0] == '2'
+
+if is_py2:
+ import Queue as queue
+else:
+ import queue as queue
+
+
+def run_tidy(task_queue, lock, timeout):
+ watchdog = None
+ while True:
+ command = task_queue.get()
+ try:
+ proc = subprocess.Popen(command,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ if timeout is not None:
+ watchdog = threading.Timer(timeout, proc.kill)
+ watchdog.start()
+
+ stdout, stderr = proc.communicate()
+
+ with lock:
+ sys.stdout.write(stdout.decode('utf-8') + '\n')
+ sys.stdout.flush()
+ if stderr:
+ sys.stderr.write(stderr.decode('utf-8') + '\n')
+ sys.stderr.flush()
+ except Exception as e:
+ with lock:
+ sys.stderr.write('Failed: ' + str(e) + ': '.join(command) + '\n')
+ finally:
+ with lock:
+ if (not timeout is None) and (not watchdog is None):
+ if not watchdog.is_alive():
+ sys.stderr.write('Terminated by timeout: ' +
+ ' '.join(command) + '\n')
+ watchdog.cancel()
+ task_queue.task_done()
+
+
+def start_workers(max_tasks, tidy_caller, task_queue, lock, timeout):
+ for _ in range(max_tasks):
+ t = threading.Thread(target=tidy_caller, args=(task_queue, lock, timeout))
+ t.daemon = True
+ t.start()
+
+def merge_replacement_files(tmpdir, mergefile):
+ """Merge all replacement files in a directory into a single file"""
+ # The fixes suggested by clang-tidy >= 4.0.0 are given under
+ # the top level key 'Diagnostics' in the output yaml files
+ mergekey = "Diagnostics"
+ merged = []
+ for replacefile in glob.iglob(os.path.join(tmpdir, '*.yaml')):
+ content = yaml.safe_load(open(replacefile, 'r'))
+ if not content:
+ continue # Skip empty files.
+ merged.extend(content.get(mergekey, []))
+
+ if merged:
+ # MainSourceFile: The key is required by the definition inside
+ # include/clang/Tooling/ReplacementsYaml.h, but the value
+ # is actually never used inside clang-apply-replacements,
+ # so we set it to '' here.
+ output = { 'MainSourceFile': '', mergekey: merged }
+ with open(mergefile, 'w') as out:
+ yaml.safe_dump(output, out)
+ else:
+ # Empty the file:
+ open(mergefile, 'w').close()
def main():
@@ -48,7 +131,10 @@ def main():
r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc)',
help='custom pattern selecting file paths to check '
'(case insensitive, overridden by -regex)')
-
+ parser.add_argument('-j', type=int, default=1,
+ help='number of tidy instances to be run in parallel.')
+ parser.add_argument('-timeout', type=int, default=None,
+ help='timeout per each file in seconds.')
parser.add_argument('-fix', action='store_true', default=False,
help='apply suggested fixes')
parser.add_argument('-checks',
@@ -57,9 +143,10 @@ def main():
default='')
parser.add_argument('-path', dest='build_path',
help='Path used to read a compile command database.')
- parser.add_argument('-export-fixes', metavar='FILE', dest='export_fixes',
- help='Create a yaml file to store suggested fixes in, '
- 'which can be applied with clang-apply-replacements.')
+ if yaml:
+ parser.add_argument('-export-fixes', metavar='FILE', dest='export_fixes',
+ help='Create a yaml file to store suggested fixes in, '
+ 'which can be applied with clang-apply-replacements.')
parser.add_argument('-extra-arg', dest='extra_arg',
action='append', default=[],
help='Additional argument to append to the compiler '
@@ -85,7 +172,7 @@ def main():
match = re.search('^\+\+\+\ \"?(.*?/){%s}([^ \t\n\"]*)' % args.p, line)
if match:
filename = match.group(2)
- if filename == None:
+ if filename is None:
continue
if args.regex is not None:
@@ -103,44 +190,79 @@ def main():
line_count = int(match.group(3))
if line_count == 0:
continue
- end_line = start_line + line_count - 1;
+ end_line = start_line + line_count - 1
lines_by_file.setdefault(filename, []).append([start_line, end_line])
- if len(lines_by_file) == 0:
+ if not any(lines_by_file):
print("No relevant changes found.")
sys.exit(0)
- line_filter_json = json.dumps(
- [{"name" : name, "lines" : lines_by_file[name]} for name in lines_by_file],
- separators = (',', ':'))
+ max_task_count = args.j
+ if max_task_count == 0:
+ max_task_count = multiprocessing.cpu_count()
+ max_task_count = min(len(lines_by_file), max_task_count)
- quote = "";
- if sys.platform == 'win32':
- line_filter_json=re.sub(r'"', r'"""', line_filter_json)
- else:
- quote = "'";
+ tmpdir = None
+ if yaml and args.export_fixes:
+ tmpdir = tempfile.mkdtemp()
+
+ # Tasks for clang-tidy.
+ task_queue = queue.Queue(max_task_count)
+ # A lock for console output.
+ lock = threading.Lock()
+
+ # Run a pool of clang-tidy workers.
+ start_workers(max_task_count, run_tidy, task_queue, lock, args.timeout)
- # Run clang-tidy on files containing changes.
- command = [args.clang_tidy_binary]
- command.append('-line-filter=' + quote + line_filter_json + quote)
+ # Form the common args list.
+ common_clang_tidy_args = []
if args.fix:
- command.append('-fix')
- if args.export_fixes:
- command.append('-export-fixes=' + args.export_fixes)
+ common_clang_tidy_args.append('-fix')
if args.checks != '':
- command.append('-checks=' + quote + args.checks + quote)
+ common_clang_tidy_args.append('-checks=' + args.checks)
if args.quiet:
- command.append('-quiet')
+ common_clang_tidy_args.append('-quiet')
if args.build_path is not None:
- command.append('-p=%s' % args.build_path)
- command.extend(lines_by_file.keys())
+ common_clang_tidy_args.append('-p=%s' % args.build_path)
for arg in args.extra_arg:
- command.append('-extra-arg=%s' % arg)
+ common_clang_tidy_args.append('-extra-arg=%s' % arg)
for arg in args.extra_arg_before:
- command.append('-extra-arg-before=%s' % arg)
- command.extend(clang_tidy_args)
+ common_clang_tidy_args.append('-extra-arg-before=%s' % arg)
+
+ for name in lines_by_file:
+ line_filter_json = json.dumps(
+ [{"name": name, "lines": lines_by_file[name]}],
+ separators=(',', ':'))
+
+ # Run clang-tidy on files containing changes.
+ command = [args.clang_tidy_binary]
+ command.append('-line-filter=' + line_filter_json)
+ if yaml and args.export_fixes:
+ # Get a temporary file. We immediately close the handle so clang-tidy can
+ # overwrite it.
+ (handle, tmp_name) = tempfile.mkstemp(suffix='.yaml', dir=tmpdir)
+ os.close(handle)
+ command.append('-export-fixes=' + tmp_name)
+ command.extend(common_clang_tidy_args)
+ command.append(name)
+ command.extend(clang_tidy_args)
+
+ task_queue.put(command)
+
+ # Wait for all threads to be done.
+ task_queue.join()
+
+ if yaml and args.export_fixes:
+ print('Writing fixes to ' + args.export_fixes + ' ...')
+ try:
+ merge_replacement_files(tmpdir, args.export_fixes)
+ except:
+ sys.stderr.write('Error exporting fixes.\n')
+ traceback.print_exc()
+
+ if tmpdir:
+ shutil.rmtree(tmpdir)
- sys.exit(subprocess.call(' '.join(command), shell=True))
if __name__ == '__main__':
main()
diff --git a/clang-tidy/tool/run-clang-tidy.py b/clang-tidy/tool/run-clang-tidy.py
index 93635cbe..648c17ea 100755
--- a/clang-tidy/tool/run-clang-tidy.py
+++ b/clang-tidy/tool/run-clang-tidy.py
@@ -2,10 +2,9 @@
#
#===- run-clang-tidy.py - Parallel clang-tidy runner ---------*- python -*--===#
#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
+# 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
#
#===------------------------------------------------------------------------===#
# FIXME: Integrate with clang-tidy-diff.py
@@ -48,7 +47,11 @@ import sys
import tempfile
import threading
import traceback
-import yaml
+
+try:
+ import yaml
+except ImportError:
+ yaml = None
is_py2 = sys.version[0] == '2'
@@ -169,6 +172,7 @@ def run_tidy(args, tmpdir, build_path, queue, lock, failed_files):
with lock:
sys.stdout.write(' '.join(invocation) + '\n' + output.decode('utf-8') + '\n')
if len(err) > 0:
+ sys.stdout.flush()
sys.stderr.write(err.decode('utf-8') + '\n')
queue.task_done()
@@ -200,9 +204,10 @@ def main():
'headers to output diagnostics from. Diagnostics from '
'the main file of each translation unit are always '
'displayed.')
- parser.add_argument('-export-fixes', metavar='filename', dest='export_fixes',
- help='Create a yaml file to store suggested fixes in, '
- 'which can be applied with clang-apply-replacements.')
+ if yaml:
+ parser.add_argument('-export-fixes', metavar='filename', dest='export_fixes',
+ help='Create a yaml file to store suggested fixes in, '
+ 'which can be applied with clang-apply-replacements.')
parser.add_argument('-j', type=int, default=0,
help='number of tidy instances to be run in parallel.')
parser.add_argument('files', nargs='*', default=['.*'],
@@ -255,7 +260,7 @@ def main():
max_task = multiprocessing.cpu_count()
tmpdir = None
- if args.fix or args.export_fixes:
+ if args.fix or (yaml and args.export_fixes):
check_clang_apply_replacements_binary(args)
tmpdir = tempfile.mkdtemp()
@@ -293,7 +298,7 @@ def main():
shutil.rmtree(tmpdir)
os.kill(0, 9)
- if args.export_fixes:
+ if yaml and args.export_fixes:
print('Writing fixes to ' + args.export_fixes + ' ...')
try:
merge_replacement_files(tmpdir, args.export_fixes)
diff --git a/clang-tidy/utils/ASTUtils.cpp b/clang-tidy/utils/ASTUtils.cpp
index 3c0427fd..9b8eca13 100644
--- a/clang-tidy/utils/ASTUtils.cpp
+++ b/clang-tidy/utils/ASTUtils.cpp
@@ -1,9 +1,8 @@
//===---------- ASTUtils.cpp - clang-tidy ---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/ASTUtils.h b/clang-tidy/utils/ASTUtils.h
index 4196eeb9..ad2a055f 100644
--- a/clang-tidy/utils/ASTUtils.h
+++ b/clang-tidy/utils/ASTUtils.h
@@ -1,9 +1,8 @@
//===---------- ASTUtils.h - clang-tidy -----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/CMakeLists.txt b/clang-tidy/utils/CMakeLists.txt
index 9162bce1..68ab7a10 100644
--- a/clang-tidy/utils/CMakeLists.txt
+++ b/clang-tidy/utils/CMakeLists.txt
@@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyUtils
ASTUtils.cpp
DeclRefExprUtils.cpp
+ ExceptionAnalyzer.cpp
ExprSequence.cpp
FixItHintUtils.cpp
HeaderFileExtensionsUtils.cpp
diff --git a/clang-tidy/utils/DeclRefExprUtils.cpp b/clang-tidy/utils/DeclRefExprUtils.cpp
index 06acd310..628b8506 100644
--- a/clang-tidy/utils/DeclRefExprUtils.cpp
+++ b/clang-tidy/utils/DeclRefExprUtils.cpp
@@ -1,9 +1,8 @@
//===--- DeclRefExprUtils.cpp - clang-tidy---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/DeclRefExprUtils.h b/clang-tidy/utils/DeclRefExprUtils.h
index c25102f8..2cf8eddc 100644
--- a/clang-tidy/utils/DeclRefExprUtils.h
+++ b/clang-tidy/utils/DeclRefExprUtils.h
@@ -1,9 +1,8 @@
//===--- DeclRefExprUtils.h - clang-tidy-------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tidy/utils/ExceptionAnalyzer.cpp
new file mode 100644
index 00000000..09fce323
--- /dev/null
+++ b/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -0,0 +1,262 @@
+//===--- ExceptionAnalyzer.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 "ExceptionAnalyzer.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+void ExceptionAnalyzer::ExceptionInfo::registerException(
+ const Type *ExceptionType) {
+ assert(ExceptionType != nullptr && "Only valid types are accepted");
+ Behaviour = State::Throwing;
+ ThrownExceptions.insert(ExceptionType);
+}
+
+void ExceptionAnalyzer::ExceptionInfo::registerExceptions(
+ const Throwables &Exceptions) {
+ if (Exceptions.size() == 0)
+ return;
+ Behaviour = State::Throwing;
+ ThrownExceptions.insert(Exceptions.begin(), Exceptions.end());
+}
+
+ExceptionAnalyzer::ExceptionInfo &ExceptionAnalyzer::ExceptionInfo::merge(
+ const ExceptionAnalyzer::ExceptionInfo &Other) {
+ // Only the following two cases require an update to the local
+ // 'Behaviour'. If the local entity is already throwing there will be no
+ // change and if the other entity is throwing the merged entity will throw
+ // as well.
+ // If one of both entities is 'Unknown' and the other one does not throw
+ // the merged entity is 'Unknown' as well.
+ if (Other.Behaviour == State::Throwing)
+ Behaviour = State::Throwing;
+ else if (Other.Behaviour == State::Unknown && Behaviour == State::NotThrowing)
+ Behaviour = State::Unknown;
+
+ ContainsUnknown = ContainsUnknown || Other.ContainsUnknown;
+ ThrownExceptions.insert(Other.ThrownExceptions.begin(),
+ Other.ThrownExceptions.end());
+ return *this;
+}
+
+static bool isBaseOf(const Type *DerivedType, const Type *BaseType) {
+ const auto *DerivedClass = DerivedType->getAsCXXRecordDecl();
+ const auto *BaseClass = BaseType->getAsCXXRecordDecl();
+ if (!DerivedClass || !BaseClass)
+ return false;
+
+ return !DerivedClass->forallBases(
+ [BaseClass](const CXXRecordDecl *Cur) { return Cur != BaseClass; });
+}
+
+bool ExceptionAnalyzer::ExceptionInfo::filterByCatch(const Type *BaseClass) {
+ llvm::SmallVector<const Type *, 8> TypesToDelete;
+ for (const Type *T : ThrownExceptions) {
+ if (T == BaseClass || isBaseOf(T, BaseClass))
+ TypesToDelete.push_back(T);
+ }
+
+ for (const Type *T : TypesToDelete)
+ ThrownExceptions.erase(T);
+
+ reevaluateBehaviour();
+ return TypesToDelete.size() > 0;
+}
+
+ExceptionAnalyzer::ExceptionInfo &
+ExceptionAnalyzer::ExceptionInfo::filterIgnoredExceptions(
+ const llvm::StringSet<> &IgnoredTypes, bool IgnoreBadAlloc) {
+ llvm::SmallVector<const Type *, 8> TypesToDelete;
+ // Note: Using a 'SmallSet' with 'llvm::remove_if()' is not possible.
+ // Therefore this slightly hacky implementation is required.
+ for (const Type *T : ThrownExceptions) {
+ if (const auto *TD = T->getAsTagDecl()) {
+ if (TD->getDeclName().isIdentifier()) {
+ if ((IgnoreBadAlloc &&
+ (TD->getName() == "bad_alloc" && TD->isInStdNamespace())) ||
+ (IgnoredTypes.count(TD->getName()) > 0))
+ TypesToDelete.push_back(T);
+ }
+ }
+ }
+ for (const Type *T : TypesToDelete)
+ ThrownExceptions.erase(T);
+
+ reevaluateBehaviour();
+ return *this;
+}
+
+void ExceptionAnalyzer::ExceptionInfo::clear() {
+ Behaviour = State::NotThrowing;
+ ContainsUnknown = false;
+ ThrownExceptions.clear();
+}
+
+void ExceptionAnalyzer::ExceptionInfo::reevaluateBehaviour() {
+ if (ThrownExceptions.size() == 0)
+ if (ContainsUnknown)
+ Behaviour = State::Unknown;
+ else
+ Behaviour = State::NotThrowing;
+ else
+ Behaviour = State::Throwing;
+}
+
+ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
+ const FunctionDecl *Func,
+ llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
+ if (CallStack.count(Func))
+ return ExceptionInfo::createNonThrowing();
+
+ if (const Stmt *Body = Func->getBody()) {
+ CallStack.insert(Func);
+ ExceptionInfo Result =
+ throwsException(Body, ExceptionInfo::Throwables(), CallStack);
+ CallStack.erase(Func);
+ return Result;
+ }
+
+ auto Result = ExceptionInfo::createUnknown();
+ if (const auto *FPT = Func->getType()->getAs<FunctionProtoType>()) {
+ for (const QualType Ex : FPT->exceptions())
+ Result.registerException(Ex.getTypePtr());
+ }
+ return Result;
+}
+
+/// Analyzes a single statment on it's throwing behaviour. This is in principle
+/// possible except some 'Unknown' functions are called.
+ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
+ const Stmt *St, const ExceptionInfo::Throwables &Caught,
+ llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
+ auto Results = ExceptionInfo::createNonThrowing();
+ if (!St)
+ return Results;
+
+ if (const auto *Throw = dyn_cast<CXXThrowExpr>(St)) {
+ if (const auto *ThrownExpr = Throw->getSubExpr()) {
+ const auto *ThrownType =
+ ThrownExpr->getType()->getUnqualifiedDesugaredType();
+ if (ThrownType->isReferenceType())
+ ThrownType = ThrownType->castAs<ReferenceType>()
+ ->getPointeeType()
+ ->getUnqualifiedDesugaredType();
+ Results.registerException(
+ ThrownExpr->getType()->getUnqualifiedDesugaredType());
+ } else
+ // A rethrow of a caught exception happens which makes it possible
+ // to throw all exception that are caught in the 'catch' clause of
+ // the parent try-catch block.
+ Results.registerExceptions(Caught);
+ } else if (const auto *Try = dyn_cast<CXXTryStmt>(St)) {
+ ExceptionInfo Uncaught =
+ throwsException(Try->getTryBlock(), Caught, CallStack);
+ for (unsigned i = 0; i < Try->getNumHandlers(); ++i) {
+ const CXXCatchStmt *Catch = Try->getHandler(i);
+
+ // Everything is catched through 'catch(...)'.
+ if (!Catch->getExceptionDecl()) {
+ ExceptionInfo Rethrown = throwsException(
+ Catch->getHandlerBlock(), Uncaught.getExceptionTypes(), CallStack);
+ Results.merge(Rethrown);
+ Uncaught.clear();
+ } else {
+ const auto *CaughtType =
+ Catch->getCaughtType()->getUnqualifiedDesugaredType();
+ if (CaughtType->isReferenceType()) {
+ CaughtType = CaughtType->castAs<ReferenceType>()
+ ->getPointeeType()
+ ->getUnqualifiedDesugaredType();
+ }
+
+ // If the caught exception will catch multiple previously potential
+ // thrown types (because it's sensitive to inheritance) the throwing
+ // situation changes. First of all filter the exception types and
+ // analyze if the baseclass-exception is rethrown.
+ if (Uncaught.filterByCatch(CaughtType)) {
+ ExceptionInfo::Throwables CaughtExceptions;
+ CaughtExceptions.insert(CaughtType);
+ ExceptionInfo Rethrown = throwsException(Catch->getHandlerBlock(),
+ CaughtExceptions, CallStack);
+ Results.merge(Rethrown);
+ }
+ }
+ }
+ Results.merge(Uncaught);
+ } else if (const auto *Call = dyn_cast<CallExpr>(St)) {
+ if (const FunctionDecl *Func = Call->getDirectCallee()) {
+ ExceptionInfo Excs = throwsException(Func, CallStack);
+ Results.merge(Excs);
+ }
+ } else {
+ for (const Stmt *Child : St->children()) {
+ ExceptionInfo Excs = throwsException(Child, Caught, CallStack);
+ Results.merge(Excs);
+ }
+ }
+ return Results;
+}
+
+ExceptionAnalyzer::ExceptionInfo
+ExceptionAnalyzer::analyzeImpl(const FunctionDecl *Func) {
+ ExceptionInfo ExceptionList;
+
+ // Check if the function has already been analyzed and reuse that result.
+ if (FunctionCache.count(Func) == 0) {
+ llvm::SmallSet<const FunctionDecl *, 32> CallStack;
+ ExceptionList = throwsException(Func, CallStack);
+
+ // Cache the result of the analysis. This is done prior to filtering
+ // because it is best to keep as much information as possible.
+ // The results here might be relevant to different analysis passes
+ // with different needs as well.
+ FunctionCache.insert(std::make_pair(Func, ExceptionList));
+ } else
+ ExceptionList = FunctionCache[Func];
+
+ return ExceptionList;
+}
+
+ExceptionAnalyzer::ExceptionInfo
+ExceptionAnalyzer::analyzeImpl(const Stmt *Stmt) {
+ llvm::SmallSet<const FunctionDecl *, 32> CallStack;
+ return throwsException(Stmt, ExceptionInfo::Throwables(), CallStack);
+}
+
+template <typename T>
+ExceptionAnalyzer::ExceptionInfo
+ExceptionAnalyzer::analyzeDispatch(const T *Node) {
+ ExceptionInfo ExceptionList = analyzeImpl(Node);
+
+ if (ExceptionList.getBehaviour() == State::NotThrowing ||
+ ExceptionList.getBehaviour() == State::Unknown)
+ return ExceptionList;
+
+ // Remove all ignored exceptions from the list of exceptions that can be
+ // thrown.
+ ExceptionList.filterIgnoredExceptions(IgnoredExceptions, IgnoreBadAlloc);
+
+ return ExceptionList;
+}
+
+ExceptionAnalyzer::ExceptionInfo
+ExceptionAnalyzer::analyze(const FunctionDecl *Func) {
+ return analyzeDispatch(Func);
+}
+
+ExceptionAnalyzer::ExceptionInfo
+ExceptionAnalyzer::analyze(const Stmt *Stmt) {
+ return analyzeDispatch(Stmt);
+}
+
+} // namespace utils
+} // namespace tidy
+
+} // namespace clang
diff --git a/clang-tidy/utils/ExceptionAnalyzer.h b/clang-tidy/utils/ExceptionAnalyzer.h
new file mode 100644
index 00000000..2caa1aad
--- /dev/null
+++ b/clang-tidy/utils/ExceptionAnalyzer.h
@@ -0,0 +1,156 @@
+//===--- ExceptionAnalyzer.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_UTILS_EXCEPTION_ANALYZER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_EXCEPTION_ANALYZER_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringSet.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+/// This class analysis if a `FunctionDecl` can in principle throw an
+/// exception, either directly or indirectly. It can be configured to ignore
+/// custom exception types.
+class ExceptionAnalyzer {
+public:
+ enum class State : std::int8_t {
+ Throwing = 0, ///< The function can definitly throw given an AST.
+ NotThrowing = 1, ///< This function can not throw, given an AST.
+ Unknown = 2, ///< This can happen for extern functions without available
+ ///< definition.
+ };
+
+ /// Bundle the gathered information about an entity like a function regarding
+ /// it's exception behaviour. The 'NonThrowing'-state can be considered as the
+ /// neutral element in terms of information propagation.
+ /// In the case of 'Throwing' state it is possible that 'getExceptionTypes'
+ /// does not include *ALL* possible types as there is the possibility that
+ /// an 'Unknown' function is called that might throw a previously unknown
+ /// exception at runtime.
+ class ExceptionInfo {
+ public:
+ using Throwables = llvm::SmallSet<const Type *, 2>;
+ static ExceptionInfo createUnknown() {
+ return ExceptionInfo(State::Unknown);
+ }
+ static ExceptionInfo createNonThrowing() {
+ return ExceptionInfo(State::Throwing);
+ }
+
+ /// By default the exception situation is unknown and must be
+ /// clarified step-wise.
+ ExceptionInfo() : Behaviour(State::NotThrowing), ContainsUnknown(false) {}
+ ExceptionInfo(State S)
+ : Behaviour(S), ContainsUnknown(S == State::Unknown) {}
+
+ ExceptionInfo(const ExceptionInfo &) = default;
+ ExceptionInfo &operator=(const ExceptionInfo &) = default;
+ ExceptionInfo(ExceptionInfo &&) = default;
+ ExceptionInfo &operator=(ExceptionInfo &&) = default;
+
+ State getBehaviour() const { return Behaviour; }
+
+ /// Register a single exception type as recognized potential exception to be
+ /// thrown.
+ void registerException(const Type *ExceptionType);
+
+ /// Registers a `SmallVector` of exception types as recognized potential
+ /// exceptions to be thrown.
+ void registerExceptions(const Throwables &Exceptions);
+
+ /// Updates the local state according to the other state. That means if
+ /// for example a function contains multiple statements the 'ExceptionInfo'
+ /// for the final function is the merged result of each statement.
+ /// If one of these statements throws the whole function throws and if one
+ /// part is unknown and the rest is non-throwing the result will be
+ /// unknown.
+ ExceptionInfo &merge(const ExceptionInfo &Other);
+
+ /// This method is useful in case 'catch' clauses are analyzed as it is
+ /// possible to catch multiple exception types by one 'catch' if they
+ /// are a subclass of the 'catch'ed exception type.
+ /// Returns 'true' if some exceptions were filtered, otherwise 'false'.
+ bool filterByCatch(const Type *BaseClass);
+
+ /// Filter the set of thrown exception type against a set of ignored
+ /// types that shall not be considered in the exception analysis.
+ /// This includes explicit `std::bad_alloc` ignoring as separate option.
+ ExceptionInfo &
+ filterIgnoredExceptions(const llvm::StringSet<> &IgnoredTypes,
+ bool IgnoreBadAlloc);
+
+ /// Clear the state to 'NonThrowing' to make the corresponding entity
+ /// neutral.
+ void clear();
+
+ /// References the set of known exception types that can escape from the
+ /// corresponding entity.
+ const Throwables &getExceptionTypes() const { return ThrownExceptions; }
+
+ /// Signal if the there is any 'Unknown' element within the scope of
+ /// the related entity. This might be relevant if the entity is 'Throwing'
+ /// and to ensure that no other exception then 'getExceptionTypes' can
+ /// occur. If there is an 'Unknown' element this can not be guaranteed.
+ bool containsUnknownElements() const { return ContainsUnknown; }
+
+ private:
+ /// Recalculate the 'Behaviour' for example after filtering.
+ void reevaluateBehaviour();
+
+ /// Keep track if the entity related to this 'ExceptionInfo' can in princple
+ /// throw, if it's unknown or if it won't throw.
+ State Behaviour;
+
+ /// Keep track if the entity contains any unknown elements to keep track
+ /// of the certainty of decisions and/or correct 'Behaviour' transition
+ /// after filtering.
+ bool ContainsUnknown;
+
+ /// 'ThrownException' is empty if the 'Behaviour' is either 'NotThrowing' or
+ /// 'Unknown'.
+ Throwables ThrownExceptions;
+ };
+
+ ExceptionAnalyzer() = default;
+
+ void ignoreBadAlloc(bool ShallIgnore) { IgnoreBadAlloc = ShallIgnore; }
+ void ignoreExceptions(llvm::StringSet<> ExceptionNames) {
+ IgnoredExceptions = std::move(ExceptionNames);
+ }
+
+ ExceptionInfo analyze(const FunctionDecl *Func);
+ ExceptionInfo analyze(const Stmt *Stmt);
+
+private:
+ ExceptionInfo
+ throwsException(const FunctionDecl *Func,
+ llvm::SmallSet<const FunctionDecl *, 32> &CallStack);
+ ExceptionInfo
+ throwsException(const Stmt *St, const ExceptionInfo::Throwables &Caught,
+ llvm::SmallSet<const FunctionDecl *, 32> &CallStack);
+
+ ExceptionInfo analyzeImpl(const FunctionDecl *Func);
+ ExceptionInfo analyzeImpl(const Stmt *Stmt);
+
+ template <typename T> ExceptionInfo analyzeDispatch(const T *Node);
+
+ bool IgnoreBadAlloc = true;
+ llvm::StringSet<> IgnoredExceptions;
+ std::map<const FunctionDecl *, ExceptionInfo> FunctionCache;
+};
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_EXCEPTION_ANALYZER_H
diff --git a/clang-tidy/utils/ExprSequence.cpp b/clang-tidy/utils/ExprSequence.cpp
index c3602ff8..0a1558e1 100644
--- a/clang-tidy/utils/ExprSequence.cpp
+++ b/clang-tidy/utils/ExprSequence.cpp
@@ -1,9 +1,8 @@
//===---------- ExprSequence.cpp - clang-tidy -----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/ExprSequence.h b/clang-tidy/utils/ExprSequence.h
index 0868a899..7bb87ad8 100644
--- a/clang-tidy/utils/ExprSequence.h
+++ b/clang-tidy/utils/ExprSequence.h
@@ -1,9 +1,8 @@
//===------------- ExprSequence.h - clang-tidy ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/FixItHintUtils.cpp b/clang-tidy/utils/FixItHintUtils.cpp
index 9da93653..c30a59e9 100644
--- a/clang-tidy/utils/FixItHintUtils.cpp
+++ b/clang-tidy/utils/FixItHintUtils.cpp
@@ -1,9 +1,8 @@
//===--- FixItHintUtils.cpp - clang-tidy-----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/FixItHintUtils.h b/clang-tidy/utils/FixItHintUtils.h
index e64a6e41..28bbb12c 100644
--- a/clang-tidy/utils/FixItHintUtils.h
+++ b/clang-tidy/utils/FixItHintUtils.h
@@ -1,9 +1,8 @@
//===--- FixItHintUtils.h - clang-tidy---------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/HeaderFileExtensionsUtils.cpp b/clang-tidy/utils/HeaderFileExtensionsUtils.cpp
index b734b897..0215b2f4 100644
--- a/clang-tidy/utils/HeaderFileExtensionsUtils.cpp
+++ b/clang-tidy/utils/HeaderFileExtensionsUtils.cpp
@@ -1,9 +1,8 @@
//===--- HeaderFileExtensionsUtils.cpp - clang-tidy--------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/HeaderFileExtensionsUtils.h b/clang-tidy/utils/HeaderFileExtensionsUtils.h
index 20120171..5a132e66 100644
--- a/clang-tidy/utils/HeaderFileExtensionsUtils.h
+++ b/clang-tidy/utils/HeaderFileExtensionsUtils.h
@@ -1,9 +1,8 @@
//===--- HeaderFileExtensionsUtils.h - clang-tidy----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/HeaderGuard.cpp b/clang-tidy/utils/HeaderGuard.cpp
index 515f8821..366d7d42 100644
--- a/clang-tidy/utils/HeaderGuard.cpp
+++ b/clang-tidy/utils/HeaderGuard.cpp
@@ -1,9 +1,8 @@
//===--- HeaderGuard.cpp - clang-tidy -------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -267,10 +266,10 @@ private:
};
} // namespace
-void HeaderGuardCheck::registerPPCallbacks(CompilerInstance &Compiler) {
- Compiler.getPreprocessor().addPPCallbacks(
- llvm::make_unique<HeaderGuardPPCallbacks>(&Compiler.getPreprocessor(),
- this));
+void HeaderGuardCheck::registerPPCallbacks(const SourceManager &SM,
+ Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) {
+ PP->addPPCallbacks(llvm::make_unique<HeaderGuardPPCallbacks>(PP, this));
}
bool HeaderGuardCheck::shouldSuggestEndifComment(StringRef FileName) {
diff --git a/clang-tidy/utils/HeaderGuard.h b/clang-tidy/utils/HeaderGuard.h
index a2d8288e..8ece3311 100644
--- a/clang-tidy/utils/HeaderGuard.h
+++ b/clang-tidy/utils/HeaderGuard.h
@@ -1,9 +1,8 @@
//===--- HeaderGuard.h - clang-tidy -----------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -33,7 +32,8 @@ public:
utils::parseHeaderFileExtensions(RawStringHeaderFileExtensions,
HeaderFileExtensions, ',');
}
- void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
/// Returns ``true`` if the check should suggest inserting a trailing comment
/// on the ``#endif`` of the header guard. It will use the same name as
diff --git a/clang-tidy/utils/IncludeInserter.cpp b/clang-tidy/utils/IncludeInserter.cpp
index 64e4213c..6b366cf2 100644
--- a/clang-tidy/utils/IncludeInserter.cpp
+++ b/clang-tidy/utils/IncludeInserter.cpp
@@ -1,9 +1,8 @@
//===-------- IncludeInserter.cpp - clang-tidy ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/IncludeInserter.h b/clang-tidy/utils/IncludeInserter.h
index 9578649d..36c16aca 100644
--- a/clang-tidy/utils/IncludeInserter.h
+++ b/clang-tidy/utils/IncludeInserter.h
@@ -1,9 +1,8 @@
//===---------- IncludeInserter.h - clang-tidy ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -32,11 +31,11 @@ namespace utils {
///
/// class MyCheck : public ClangTidyCheck {
/// public:
-/// void registerPPCallbacks(CompilerInstance& Compiler) override {
-/// Inserter = llvm::make_unique<IncludeInserter>(&Compiler.getSourceManager(),
-/// &Compiler.getLangOpts());
-/// Compiler.getPreprocessor().addPPCallbacks(
-/// Inserter->CreatePPCallbacks());
+/// void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+/// Preprocessor *ModuleExpanderPP) override {
+/// Inserter = llvm::make_unique<IncludeInserter>(
+/// SM, getLangOpts(), utils::IncludeSorter::IS_Google);
+/// PP->addPPCallbacks(Inserter->CreatePPCallbacks());
/// }
///
/// void registerMatchers(ast_matchers::MatchFinder* Finder) override { ... }
diff --git a/clang-tidy/utils/IncludeSorter.cpp b/clang-tidy/utils/IncludeSorter.cpp
index 1502da76..9d792272 100644
--- a/clang-tidy/utils/IncludeSorter.cpp
+++ b/clang-tidy/utils/IncludeSorter.cpp
@@ -1,9 +1,8 @@
//===---------- IncludeSorter.cpp - clang-tidy ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/IncludeSorter.h b/clang-tidy/utils/IncludeSorter.h
index 07fa293d..9c07274a 100644
--- a/clang-tidy/utils/IncludeSorter.h
+++ b/clang-tidy/utils/IncludeSorter.h
@@ -1,9 +1,8 @@
//===------------ IncludeSorter.h - clang-tidy ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/LexerUtils.cpp b/clang-tidy/utils/LexerUtils.cpp
index edd4cd62..a6e361d6 100644
--- a/clang-tidy/utils/LexerUtils.cpp
+++ b/clang-tidy/utils/LexerUtils.cpp
@@ -1,9 +1,8 @@
//===--- LexerUtils.cpp - clang-tidy---------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/LexerUtils.h b/clang-tidy/utils/LexerUtils.h
index 55a8b85c..06a03b6e 100644
--- a/clang-tidy/utils/LexerUtils.h
+++ b/clang-tidy/utils/LexerUtils.h
@@ -1,9 +1,8 @@
//===--- LexerUtils.h - clang-tidy-------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/Matchers.h b/clang-tidy/utils/Matchers.h
index 849b36fb..dbb72c9d 100644
--- a/clang-tidy/utils/Matchers.h
+++ b/clang-tidy/utils/Matchers.h
@@ -1,9 +1,8 @@
//===--- Matchers.h - clang-tidy-------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/NamespaceAliaser.cpp b/clang-tidy/utils/NamespaceAliaser.cpp
index 25182304..fe99e684 100644
--- a/clang-tidy/utils/NamespaceAliaser.cpp
+++ b/clang-tidy/utils/NamespaceAliaser.cpp
@@ -1,9 +1,8 @@
//===---------- NamespaceAliaser.cpp - clang-tidy -------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/NamespaceAliaser.h b/clang-tidy/utils/NamespaceAliaser.h
index e56d69d3..ab1b9781 100644
--- a/clang-tidy/utils/NamespaceAliaser.h
+++ b/clang-tidy/utils/NamespaceAliaser.h
@@ -1,9 +1,8 @@
//===---------- NamespaceAliaser.h - clang-tidy ---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/OptionsUtils.cpp b/clang-tidy/utils/OptionsUtils.cpp
index 0b1d27d5..36f4b6fc 100644
--- a/clang-tidy/utils/OptionsUtils.cpp
+++ b/clang-tidy/utils/OptionsUtils.cpp
@@ -1,9 +1,8 @@
-//===--- DanglingHandleCheck.cpp - clang-tidy------------------------------===//
+//===-- OptionsUtils.cpp - clang-tidy -------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/OptionsUtils.h b/clang-tidy/utils/OptionsUtils.h
index d822ac98..26b82e9d 100644
--- a/clang-tidy/utils/OptionsUtils.h
+++ b/clang-tidy/utils/OptionsUtils.h
@@ -1,9 +1,8 @@
//===--- DanglingHandleCheck.h - clang-tidy----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/TypeTraits.cpp b/clang-tidy/utils/TypeTraits.cpp
index 2cdc5064..954a288e 100644
--- a/clang-tidy/utils/TypeTraits.cpp
+++ b/clang-tidy/utils/TypeTraits.cpp
@@ -1,9 +1,8 @@
//===--- TypeTraits.cpp - clang-tidy---------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/TypeTraits.h b/clang-tidy/utils/TypeTraits.h
index ae0b3f0f..6102c288 100644
--- a/clang-tidy/utils/TypeTraits.h
+++ b/clang-tidy/utils/TypeTraits.h
@@ -1,9 +1,8 @@
//===--- TypeTraits.h - clang-tidy-------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/UsingInserter.cpp b/clang-tidy/utils/UsingInserter.cpp
index e479d591..e852532a 100644
--- a/clang-tidy/utils/UsingInserter.cpp
+++ b/clang-tidy/utils/UsingInserter.cpp
@@ -1,9 +1,8 @@
//===---------- UsingInserter.cpp - clang-tidy ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/UsingInserter.h b/clang-tidy/utils/UsingInserter.h
index 62108e41..9d3c60ca 100644
--- a/clang-tidy/utils/UsingInserter.h
+++ b/clang-tidy/utils/UsingInserter.h
@@ -1,9 +1,8 @@
//===---------- UsingInserter.h - clang-tidy ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/zircon/TemporaryObjectsCheck.cpp b/clang-tidy/zircon/TemporaryObjectsCheck.cpp
index be2fb835..d3fac14f 100644
--- a/clang-tidy/zircon/TemporaryObjectsCheck.cpp
+++ b/clang-tidy/zircon/TemporaryObjectsCheck.cpp
@@ -1,9 +1,8 @@
//===--- TemporaryObjectsCheck.cpp - clang-tidy----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/zircon/TemporaryObjectsCheck.h b/clang-tidy/zircon/TemporaryObjectsCheck.h
index 302ef72a..1243dad8 100644
--- a/clang-tidy/zircon/TemporaryObjectsCheck.h
+++ b/clang-tidy/zircon/TemporaryObjectsCheck.h
@@ -1,16 +1,15 @@
//===--- TemporaryObjectsCheck.h - clang-tidy------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_ZIRCON_TEMPORARYOBJECTSCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ZIRCON_TEMPORARYOBJECTSCHECK_H
-#include "../ClangTidy.h"
+#include "../ClangTidyCheck.h"
#include "../utils/OptionsUtils.h"
namespace clang {
diff --git a/clang-tidy/zircon/ZirconTidyModule.cpp b/clang-tidy/zircon/ZirconTidyModule.cpp
index 3e53c23a..94bbd27a 100644
--- a/clang-tidy/zircon/ZirconTidyModule.cpp
+++ b/clang-tidy/zircon/ZirconTidyModule.cpp
@@ -1,9 +1,8 @@
//===--- ZirconTidyModule.cpp - clang-tidy---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/AST.cpp b/clangd/AST.cpp
index a185a6d8..113069a0 100644
--- a/clangd/AST.cpp
+++ b/clangd/AST.cpp
@@ -1,9 +1,8 @@
//===--- AST.cpp - Utility AST functions -----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -12,15 +11,37 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/TemplateBase.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Index/USRGeneration.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/raw_ostream.h"
namespace clang {
namespace clangd {
+namespace {
+llvm::Optional<llvm::ArrayRef<TemplateArgumentLoc>>
+getTemplateSpecializationArgLocs(const NamedDecl &ND) {
+ if (auto *Func = llvm::dyn_cast<FunctionDecl>(&ND)) {
+ if (const ASTTemplateArgumentListInfo *Args =
+ Func->getTemplateSpecializationArgsAsWritten())
+ return Args->arguments();
+ } else if (auto *Cls =
+ llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(&ND)) {
+ if (auto *Args = Cls->getTemplateArgsAsWritten())
+ return Args->arguments();
+ } else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND))
+ return Var->getTemplateArgsInfo().arguments();
+ // We return None for ClassTemplateSpecializationDecls because it does not
+ // contain TemplateArgumentLoc information.
+ return llvm::None;
+}
+} // namespace
+
// Returns true if the complete name of decl \p D is spelled in the source code.
// This is not the case for:
// * symbols formed via macro concatenation, the spelling location will
@@ -66,17 +87,6 @@ std::string printQualifiedName(const NamedDecl &ND) {
return QName;
}
-static const TemplateArgumentList *
-getTemplateSpecializationArgs(const NamedDecl &ND) {
- if (auto *Func = llvm::dyn_cast<FunctionDecl>(&ND))
- return Func->getTemplateSpecializationArgs();
- if (auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND))
- return &Cls->getTemplateInstantiationArgs();
- if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND))
- return &Var->getTemplateInstantiationArgs();
- return nullptr;
-}
-
std::string printName(const ASTContext &Ctx, const NamedDecl &ND) {
std::string Name;
llvm::raw_string_ostream Out(Name);
@@ -91,9 +101,7 @@ std::string printName(const ASTContext &Ctx, const NamedDecl &ND) {
}
ND.getDeclName().print(Out, PP);
if (!Out.str().empty()) {
- // FIXME(ibiryukov): do not show args not explicitly written by the user.
- if (auto *ArgList = getTemplateSpecializationArgs(ND))
- printTemplateArgumentList(Out, ArgList->asArray(), PP);
+ Out << printTemplateSpecializationArgs(ND);
return Out.str();
}
// The name was empty, so present an anonymous entity.
@@ -106,6 +114,35 @@ std::string printName(const ASTContext &Ctx, const NamedDecl &ND) {
return "(anonymous)";
}
+std::string printTemplateSpecializationArgs(const NamedDecl &ND) {
+ std::string TemplateArgs;
+ llvm::raw_string_ostream OS(TemplateArgs);
+ PrintingPolicy Policy(ND.getASTContext().getLangOpts());
+ if (llvm::Optional<llvm::ArrayRef<TemplateArgumentLoc>> Args =
+ getTemplateSpecializationArgLocs(ND)) {
+ printTemplateArgumentList(OS, *Args, Policy);
+ } else if (auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) {
+ if (const TypeSourceInfo *TSI = Cls->getTypeAsWritten()) {
+ // ClassTemplateSpecializationDecls do not contain
+ // TemplateArgumentTypeLocs, they only have TemplateArgumentTypes. So we
+ // create a new argument location list from TypeSourceInfo.
+ auto STL = TSI->getTypeLoc().getAs<TemplateSpecializationTypeLoc>();
+ llvm::SmallVector<TemplateArgumentLoc, 8> ArgLocs;
+ ArgLocs.reserve(STL.getNumArgs());
+ for (unsigned I = 0; I < STL.getNumArgs(); ++I)
+ ArgLocs.push_back(STL.getArgLoc(I));
+ printTemplateArgumentList(OS, ArgLocs, Policy);
+ } else {
+ // FIXME: Fix cases when getTypeAsWritten returns null inside clang AST,
+ // e.g. friend decls. Currently we fallback to Template Arguments without
+ // location information.
+ printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy);
+ }
+ }
+ OS.flush();
+ return TemplateArgs;
+}
+
std::string printNamespaceScope(const DeclContext &DC) {
for (const auto *Ctx = &DC; Ctx != nullptr; Ctx = Ctx->getParent())
if (const auto *NS = dyn_cast<NamespaceDecl>(Ctx))
diff --git a/clangd/AST.h b/clangd/AST.h
index 85eb47c4..e0e84a0f 100644
--- a/clangd/AST.h
+++ b/clangd/AST.h
@@ -1,9 +1,8 @@
//===--- AST.h - Utility AST functions -------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -14,9 +13,10 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_AST_H_
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_AST_H_
-#include "index/Index.h"
+#include "index/SymbolID.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/MacroInfo.h"
namespace clang {
class SourceManager;
@@ -47,6 +47,12 @@ std::string printNamespaceScope(const DeclContext &DC);
/// "(anonymous struct)" or "(anonymous namespace)".
std::string printName(const ASTContext &Ctx, const NamedDecl &ND);
+/// Prints template arguments of a decl as written in the source code, including
+/// enclosing '<' and '>', e.g for a partial specialization like: template
+/// <typename U> struct Foo<int, U> will return '<int, U>'. Returns an empty
+/// string if decl is not a template specialization.
+std::string printTemplateSpecializationArgs(const NamedDecl &ND);
+
/// Gets the symbol ID for a declaration, if possible.
llvm::Optional<SymbolID> getSymbolID(const Decl *D);
diff --git a/clangd/CMakeLists.txt b/clangd/CMakeLists.txt
index 92f62001..1eb444ea 100644
--- a/clangd/CMakeLists.txt
+++ b/clangd/CMakeLists.txt
@@ -1,6 +1,19 @@
# Configure the Features.inc file.
-llvm_canonicalize_cmake_booleans(
- CLANGD_BUILD_XPC)
+if (NOT DEFINED CLANGD_BUILD_XPC)
+ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ set(CLANGD_BUILD_XPC_DEFAULT ON)
+ else ()
+ set(CLANGD_BUILD_XPC_DEFAULT OFF)
+ endif ()
+
+ llvm_canonicalize_cmake_booleans(CLANGD_BUILD_XPC_DEFAULT)
+
+ set(CLANGD_BUILD_XPC ${CLANGD_BUILD_XPC_DEFAULT} CACHE BOOL "Build XPC Support For Clangd." FORCE)
+ unset(CLANGD_BUILD_XPC_DEFAULT)
+endif ()
+
+llvm_canonicalize_cmake_booleans(CLANGD_BUILD_XPC)
+
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/Features.inc.in
${CMAKE_CURRENT_BINARY_DIR}/Features.inc
@@ -40,11 +53,13 @@ add_clang_library(clangDaemon
FuzzyMatch.cpp
GlobalCompilationDatabase.cpp
Headers.cpp
+ IncludeFixer.cpp
JSONTransport.cpp
Logger.cpp
Protocol.cpp
Quality.cpp
RIFF.cpp
+ Selection.cpp
SourceCode.cpp
Threading.cpp
Trace.cpp
@@ -60,9 +75,13 @@ add_clang_library(clangDaemon
index/IndexAction.cpp
index/MemIndex.cpp
index/Merge.cpp
- index/SymbolID.cpp
+ index/Ref.cpp
index/Serialization.cpp
+ index/Symbol.cpp
index/SymbolCollector.cpp
+ index/SymbolID.cpp
+ index/SymbolLocation.cpp
+ index/SymbolOrigin.cpp
index/YAMLSerialization.cpp
index/dex/Dex.cpp
@@ -70,6 +89,8 @@ add_clang_library(clangDaemon
index/dex/PostingList.cpp
index/dex/Trigram.cpp
+ refactor/Tweak.cpp
+
LINK_LIBS
clangAST
clangASTMatchers
@@ -107,7 +128,9 @@ add_clang_library(clangDaemon
${CLANGD_ATOMIC_LIB}
)
-if( LLVM_LIB_FUZZING_ENGINE OR LLVM_USE_SANITIZE_COVERAGE )
+add_subdirectory(refactor/tweaks)
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+ # FIXME: Make fuzzer not use linux-specific APIs, build it everywhere.
add_subdirectory(fuzzer)
endif()
add_subdirectory(tool)
@@ -120,3 +143,8 @@ endif()
if ( CLANGD_BUILD_XPC )
add_subdirectory(xpc)
endif ()
+
+if(CLANG_INCLUDE_TESTS)
+add_subdirectory(test)
+add_subdirectory(unittests)
+endif()
diff --git a/clangd/Cancellation.cpp b/clangd/Cancellation.cpp
index cc1c11ce..6b0e21d3 100644
--- a/clangd/Cancellation.cpp
+++ b/clangd/Cancellation.cpp
@@ -1,9 +1,8 @@
//===--- Cancellation.cpp -----------------------------------------*-C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/Cancellation.h b/clangd/Cancellation.h
index d6f26211..6872c448 100644
--- a/clangd/Cancellation.h
+++ b/clangd/Cancellation.h
@@ -1,9 +1,8 @@
//===--- Cancellation.h -------------------------------------------*-C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
// Cancellation mechanism for long-running tasks.
diff --git a/clangd/ClangdLSPServer.cpp b/clangd/ClangdLSPServer.cpp
index 80792edd..44357df7 100644
--- a/clangd/ClangdLSPServer.cpp
+++ b/clangd/ClangdLSPServer.cpp
@@ -1,19 +1,22 @@
//===--- ClangdLSPServer.cpp - LSP server ------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "ClangdLSPServer.h"
#include "Diagnostics.h"
+#include "Protocol.h"
#include "SourceCode.h"
#include "Trace.h"
#include "URI.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -31,6 +34,28 @@ public:
}
};
+/// Transforms a tweak into a code action that would apply it if executed.
+/// EXPECTS: T.prepare() was called and returned true.
+CodeAction toCodeAction(const ClangdServer::TweakRef &T, const URIForFile &File,
+ Range Selection) {
+ CodeAction CA;
+ CA.title = T.Title;
+ CA.kind = CodeAction::REFACTOR_KIND;
+ // This tweak may have an expensive second stage, we only run it if the user
+ // actually chooses it in the UI. We reply with a command that would run the
+ // corresponding tweak.
+ // FIXME: for some tweaks, computing the edits is cheap and we could send them
+ // directly.
+ CA.command.emplace();
+ CA.command->title = T.Title;
+ CA.command->command = Command::CLANGD_APPLY_TWEAK;
+ CA.command->tweakArgs.emplace();
+ CA.command->tweakArgs->file = File;
+ CA.command->tweakArgs->tweakID = T.ID;
+ CA.command->tweakArgs->selection = Selection;
+ return CA;
+}
+
void adjustSymbolKinds(llvm::MutableArrayRef<DocumentSymbol> Syms,
SymbolKindBitset Kinds) {
for (auto &S : Syms) {
@@ -69,6 +94,7 @@ public:
MessageHandler(ClangdLSPServer &Server) : Server(Server) {}
bool onNotify(llvm::StringRef Method, llvm::json::Value Params) override {
+ WithContext HandlerContext(handlerContext());
log("<-- {0}", Method);
if (Method == "exit")
return false;
@@ -85,6 +111,7 @@ public:
bool onCall(llvm::StringRef Method, llvm::json::Value Params,
llvm::json::Value ID) override {
+ WithContext HandlerContext(handlerContext());
// Calls can be canceled by the client. Add cancellation context.
WithContext WithCancel(cancelableRequestContext(ID));
trace::Span Tracer(Method);
@@ -105,6 +132,7 @@ public:
bool onReply(llvm::json::Value ID,
llvm::Expected<llvm::json::Value> Result) override {
+ WithContext HandlerContext(handlerContext());
// We ignore replies, just log them.
if (Result)
log("<-- reply({0})", ID);
@@ -235,6 +263,13 @@ private:
if (It != RequestCancelers.end())
It->second.first(); // Invoke the canceler.
}
+
+ Context handlerContext() const {
+ return Context::current().derive(
+ kCurrentOffsetEncoding,
+ Server.NegotiatedOffsetEncoding.getValueOr(OffsetEncoding::UTF16));
+ }
+
// We run cancelable requests in a context that does two things:
// - allows cancellation using RequestCancelers[ID]
// - cleans up the entry in RequestCancelers when it's no longer needed
@@ -278,6 +313,20 @@ void ClangdLSPServer::notify(llvm::StringRef Method, llvm::json::Value Params) {
void ClangdLSPServer::onInitialize(const InitializeParams &Params,
Callback<llvm::json::Value> Reply) {
+ // Determine character encoding first as it affects constructed ClangdServer.
+ if (Params.capabilities.offsetEncoding && !NegotiatedOffsetEncoding) {
+ NegotiatedOffsetEncoding = OffsetEncoding::UTF16; // fallback
+ for (OffsetEncoding Supported : *Params.capabilities.offsetEncoding)
+ if (Supported != OffsetEncoding::UnsupportedEncoding) {
+ NegotiatedOffsetEncoding = Supported;
+ break;
+ }
+ }
+ llvm::Optional<WithContextValue> WithOffsetEncoding;
+ if (NegotiatedOffsetEncoding)
+ WithOffsetEncoding.emplace(kCurrentOffsetEncoding,
+ *NegotiatedOffsetEncoding);
+
if (Params.rootUri && *Params.rootUri)
ClangdServerOpts.WorkspaceRoot = Params.rootUri->file();
else if (Params.rootPath && !Params.rootPath->empty())
@@ -290,7 +339,8 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
if (UseDirBasedCDB)
BaseCDB = llvm::make_unique<DirectoryBasedGlobalCompilationDatabase>(
CompileCommandsDir);
- CDB.emplace(BaseCDB.get(), Params.initializationOptions.fallbackFlags);
+ CDB.emplace(BaseCDB.get(), Params.initializationOptions.fallbackFlags,
+ ClangdServerOpts.ResourceDir);
Server.emplace(*CDB, FSProvider, static_cast<DiagnosticsConsumer &>(*this),
ClangdServerOpts);
applyConfiguration(Params.initializationOptions.ConfigSettings);
@@ -298,6 +348,8 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
CCOpts.EnableSnippets = Params.capabilities.CompletionSnippets;
DiagOpts.EmbedFixesInDiagnostics = Params.capabilities.DiagnosticFixes;
DiagOpts.SendDiagnosticCategory = Params.capabilities.DiagnosticCategory;
+ DiagOpts.EmitRelatedLocations =
+ Params.capabilities.DiagnosticRelatedInformation;
if (Params.capabilities.WorkspaceSymbolKinds)
SupportedSymbolKinds |= *Params.capabilities.WorkspaceSymbolKinds;
if (Params.capabilities.CompletionItemKinds)
@@ -306,7 +358,7 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
SupportsHierarchicalDocumentSymbol =
Params.capabilities.HierarchicalDocumentSymbol;
SupportFileStatus = Params.initializationOptions.FileStatus;
- Reply(llvm::json::Object{
+ llvm::json::Object Result{
{{"capabilities",
llvm::json::Object{
{"textDocumentSync", (int)TextDocumentSyncKind::Incremental},
@@ -329,6 +381,7 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
llvm::json::Object{
{"triggerCharacters", {"(", ","}},
}},
+ {"declarationProvider", true},
{"definitionProvider", true},
{"documentHighlightProvider", true},
{"hoverProvider", true},
@@ -338,9 +391,15 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
{"referencesProvider", true},
{"executeCommandProvider",
llvm::json::Object{
- {"commands", {ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND}},
+ {"commands",
+ {ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND,
+ ExecuteCommandParams::CLANGD_APPLY_TWEAK}},
}},
- }}}});
+ {"typeHierarchyProvider", true},
+ }}}};
+ if (NegotiatedOffsetEncoding)
+ Result["offsetEncoding"] = *NegotiatedOffsetEncoding;
+ Reply(std::move(Result));
}
void ClangdLSPServer::onShutdown(const ShutdownParams &Params,
@@ -400,7 +459,7 @@ void ClangdLSPServer::onFileEvent(const DidChangeWatchedFilesParams &Params) {
void ClangdLSPServer::onCommand(const ExecuteCommandParams &Params,
Callback<llvm::json::Value> Reply) {
- auto ApplyEdit = [&](WorkspaceEdit WE) {
+ auto ApplyEdit = [this](WorkspaceEdit WE) {
ApplyWorkspaceEditParams Edit;
Edit.edit = std::move(WE);
// Ideally, we would wait for the response and if there is no error, we
@@ -420,6 +479,31 @@ void ClangdLSPServer::onCommand(const ExecuteCommandParams &Params,
Reply("Fix applied.");
ApplyEdit(*Params.workspaceEdit);
+ } else if (Params.command == ExecuteCommandParams::CLANGD_APPLY_TWEAK &&
+ Params.tweakArgs) {
+ auto Code = DraftMgr.getDraft(Params.tweakArgs->file.file());
+ if (!Code)
+ return Reply(llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "trying to apply a code action for a non-added file"));
+
+ auto Action = [ApplyEdit](decltype(Reply) Reply, URIForFile File,
+ std::string Code,
+ llvm::Expected<tooling::Replacements> R) {
+ if (!R)
+ return Reply(R.takeError());
+
+ WorkspaceEdit WE;
+ WE.changes.emplace();
+ (*WE.changes)[File.uri()] = replacementsToEdits(Code, *R);
+
+ Reply("Fix applied.");
+ ApplyEdit(std::move(WE));
+ };
+ Server->applyTweak(Params.tweakArgs->file.file(),
+ Params.tweakArgs->selection, Params.tweakArgs->tweakID,
+ Bind(Action, std::move(Reply), Params.tweakArgs->file,
+ std::move(*Code)));
} else {
// We should not get here because ExecuteCommandParams would not have
// parsed in the first place and this handler should not be called. But if
@@ -459,19 +543,13 @@ void ClangdLSPServer::onRename(const RenameParams &Params,
Server->rename(
File, Params.position, Params.newName,
Bind(
- [File, Code, Params](
- decltype(Reply) Reply,
- llvm::Expected<std::vector<tooling::Replacement>> Replacements) {
- if (!Replacements)
- return Reply(Replacements.takeError());
-
- // Turn the replacements into the format specified by the Language
- // Server Protocol. Fuse them into one big JSON array.
- std::vector<TextEdit> Edits;
- for (const auto &R : *Replacements)
- Edits.push_back(replacementToEdit(*Code, R));
+ [File, Code, Params](decltype(Reply) Reply,
+ llvm::Expected<std::vector<TextEdit>> Edits) {
+ if (!Edits)
+ return Reply(Edits.takeError());
+
WorkspaceEdit WE;
- WE.changes = {{Params.textDocument.uri.uri(), Edits}};
+ WE.changes = {{Params.textDocument.uri.uri(), *Edits}};
Reply(WE);
},
std::move(Reply)));
@@ -482,6 +560,17 @@ void ClangdLSPServer::onDocumentDidClose(
PathRef File = Params.textDocument.uri.file();
DraftMgr.removeDraft(File);
Server->removeDocument(File);
+
+ {
+ std::lock_guard<std::mutex> Lock(FixItsMutex);
+ FixItsMap.erase(File);
+ }
+ // clangd will not send updates for this file anymore, so we empty out the
+ // list of diagnostics shown on the client (e.g. in the "Problems" pane of
+ // VSCode). Note that this cannot race with actual diagnostics responses
+ // because removeDocument() guarantees no diagnostic callbacks will be
+ // executed after it returns.
+ publishDiagnostics(URIForFile::canonicalize(File, /*TUPath=*/File), {});
}
void ClangdLSPServer::onDocumentOnTypeFormatting(
@@ -601,28 +690,47 @@ static llvm::Optional<Command> asCommand(const CodeAction &Action) {
void ClangdLSPServer::onCodeAction(const CodeActionParams &Params,
Callback<llvm::json::Value> Reply) {
- auto Code = DraftMgr.getDraft(Params.textDocument.uri.file());
+ URIForFile File = Params.textDocument.uri;
+ auto Code = DraftMgr.getDraft(File.file());
if (!Code)
return Reply(llvm::make_error<LSPError>(
"onCodeAction called for non-added file", ErrorCode::InvalidParams));
// We provide a code action for Fixes on the specified diagnostics.
- std::vector<CodeAction> Actions;
+ std::vector<CodeAction> FixIts;
for (const Diagnostic &D : Params.context.diagnostics) {
- for (auto &F : getFixes(Params.textDocument.uri.file(), D)) {
- Actions.push_back(toCodeAction(F, Params.textDocument.uri));
- Actions.back().diagnostics = {D};
+ for (auto &F : getFixes(File.file(), D)) {
+ FixIts.push_back(toCodeAction(F, Params.textDocument.uri));
+ FixIts.back().diagnostics = {D};
}
}
- if (SupportsCodeAction)
- Reply(llvm::json::Array(Actions));
- else {
- std::vector<Command> Commands;
- for (const auto &Action : Actions)
- if (auto Command = asCommand(Action))
- Commands.push_back(std::move(*Command));
- Reply(llvm::json::Array(Commands));
- }
+ // Now enumerate the semantic code actions.
+ auto ConsumeActions =
+ [this](decltype(Reply) Reply, URIForFile File, std::string Code,
+ Range Selection, std::vector<CodeAction> FixIts,
+ llvm::Expected<std::vector<ClangdServer::TweakRef>> Tweaks) {
+ if (!Tweaks)
+ return Reply(Tweaks.takeError());
+
+ std::vector<CodeAction> Actions = std::move(FixIts);
+ Actions.reserve(Actions.size() + Tweaks->size());
+ for (const auto &T : *Tweaks)
+ Actions.push_back(toCodeAction(T, File, Selection));
+
+ if (SupportsCodeAction)
+ return Reply(llvm::json::Array(Actions));
+ std::vector<Command> Commands;
+ for (const auto &Action : Actions) {
+ if (auto Command = asCommand(Action))
+ Commands.push_back(std::move(*Command));
+ }
+ return Reply(llvm::json::Array(Commands));
+ };
+
+ Server->enumerateTweaks(File.file(), Params.range,
+ Bind(ConsumeActions, std::move(Reply), File,
+ std::move(*Code), Params.range,
+ std::move(FixIts)));
}
void ClangdLSPServer::onCompletion(const CompletionParams &Params,
@@ -654,10 +762,65 @@ void ClangdLSPServer::onSignatureHelp(const TextDocumentPositionParams &Params,
std::move(Reply));
}
+// Go to definition has a toggle function: if def and decl are distinct, then
+// the first press gives you the def, the second gives you the matching def.
+// getToggle() returns the counterpart location that under the cursor.
+//
+// We return the toggled location alone (ignoring other symbols) to encourage
+// editors to "bounce" quickly between locations, without showing a menu.
+static Location *getToggle(const TextDocumentPositionParams &Point,
+ LocatedSymbol &Sym) {
+ // Toggle only makes sense with two distinct locations.
+ if (!Sym.Definition || *Sym.Definition == Sym.PreferredDeclaration)
+ return nullptr;
+ if (Sym.Definition->uri.file() == Point.textDocument.uri.file() &&
+ Sym.Definition->range.contains(Point.position))
+ return &Sym.PreferredDeclaration;
+ if (Sym.PreferredDeclaration.uri.file() == Point.textDocument.uri.file() &&
+ Sym.PreferredDeclaration.range.contains(Point.position))
+ return &*Sym.Definition;
+ return nullptr;
+}
+
void ClangdLSPServer::onGoToDefinition(const TextDocumentPositionParams &Params,
Callback<std::vector<Location>> Reply) {
- Server->findDefinitions(Params.textDocument.uri.file(), Params.position,
- std::move(Reply));
+ Server->locateSymbolAt(
+ Params.textDocument.uri.file(), Params.position,
+ Bind(
+ [&, Params](decltype(Reply) Reply,
+ llvm::Expected<std::vector<LocatedSymbol>> Symbols) {
+ if (!Symbols)
+ return Reply(Symbols.takeError());
+ std::vector<Location> Defs;
+ for (auto &S : *Symbols) {
+ if (Location *Toggle = getToggle(Params, S))
+ return Reply(std::vector<Location>{std::move(*Toggle)});
+ Defs.push_back(S.Definition.getValueOr(S.PreferredDeclaration));
+ }
+ Reply(std::move(Defs));
+ },
+ std::move(Reply)));
+}
+
+void ClangdLSPServer::onGoToDeclaration(
+ const TextDocumentPositionParams &Params,
+ Callback<std::vector<Location>> Reply) {
+ Server->locateSymbolAt(
+ Params.textDocument.uri.file(), Params.position,
+ Bind(
+ [&, Params](decltype(Reply) Reply,
+ llvm::Expected<std::vector<LocatedSymbol>> Symbols) {
+ if (!Symbols)
+ return Reply(Symbols.takeError());
+ std::vector<Location> Decls;
+ for (auto &S : *Symbols) {
+ if (Location *Toggle = getToggle(Params, S))
+ return Reply(std::vector<Location>{std::move(*Toggle)});
+ Decls.push_back(std::move(S.PreferredDeclaration));
+ }
+ Reply(std::move(Decls));
+ },
+ std::move(Reply)));
}
void ClangdLSPServer::onSwitchSourceHeader(const TextDocumentIdentifier &Params,
@@ -679,6 +842,13 @@ void ClangdLSPServer::onHover(const TextDocumentPositionParams &Params,
std::move(Reply));
}
+void ClangdLSPServer::onTypeHierarchy(
+ const TypeHierarchyParams &Params,
+ Callback<Optional<TypeHierarchyItem>> Reply) {
+ Server->typeHierarchy(Params.textDocument.uri.file(), Params.position,
+ Params.resolve, Params.direction, std::move(Reply));
+}
+
void ClangdLSPServer::applyConfiguration(
const ConfigurationSettings &Settings) {
// Per-file update to the compilation database.
@@ -701,6 +871,16 @@ void ClangdLSPServer::applyConfiguration(
reparseOpenedFiles();
}
+void ClangdLSPServer::publishDiagnostics(
+ const URIForFile &File, std::vector<clangd::Diagnostic> Diagnostics) {
+ // Publish diagnostics.
+ notify("textDocument/publishDiagnostics",
+ llvm::json::Object{
+ {"uri", File},
+ {"diagnostics", std::move(Diagnostics)},
+ });
+}
+
// FIXME: This function needs to be properly tested.
void ClangdLSPServer::onChangeConfiguration(
const DidChangeConfigurationParams &Params) {
@@ -719,17 +899,19 @@ void ClangdLSPServer::onSymbolInfo(const TextDocumentPositionParams &Params,
std::move(Reply));
}
-ClangdLSPServer::ClangdLSPServer(class Transport &Transp,
- const clangd::CodeCompleteOptions &CCOpts,
- llvm::Optional<Path> CompileCommandsDir,
- bool UseDirBasedCDB,
- const ClangdServer::Options &Opts)
- : Transp(Transp), MsgHandler(new MessageHandler(*this)), CCOpts(CCOpts),
+ClangdLSPServer::ClangdLSPServer(
+ class Transport &Transp, const FileSystemProvider &FSProvider,
+ const clangd::CodeCompleteOptions &CCOpts,
+ llvm::Optional<Path> CompileCommandsDir, bool UseDirBasedCDB,
+ llvm::Optional<OffsetEncoding> ForcedOffsetEncoding,
+ const ClangdServer::Options &Opts)
+ : Transp(Transp), MsgHandler(new MessageHandler(*this)),
+ FSProvider(FSProvider), CCOpts(CCOpts),
SupportedSymbolKinds(defaultSymbolKinds()),
SupportedCompletionItemKinds(defaultCompletionItemKinds()),
UseDirBasedCDB(UseDirBasedCDB),
- CompileCommandsDir(std::move(CompileCommandsDir)),
- ClangdServerOpts(Opts) {
+ CompileCommandsDir(std::move(CompileCommandsDir)), ClangdServerOpts(Opts),
+ NegotiatedOffsetEncoding(ForcedOffsetEncoding) {
// clang-format off
MsgHandler->bind("initialize", &ClangdLSPServer::onInitialize);
MsgHandler->bind("shutdown", &ClangdLSPServer::onShutdown);
@@ -741,6 +923,7 @@ ClangdLSPServer::ClangdLSPServer(class Transport &Transp,
MsgHandler->bind("textDocument/completion", &ClangdLSPServer::onCompletion);
MsgHandler->bind("textDocument/signatureHelp", &ClangdLSPServer::onSignatureHelp);
MsgHandler->bind("textDocument/definition", &ClangdLSPServer::onGoToDefinition);
+ MsgHandler->bind("textDocument/declaration", &ClangdLSPServer::onGoToDeclaration);
MsgHandler->bind("textDocument/references", &ClangdLSPServer::onReference);
MsgHandler->bind("textDocument/switchSourceHeader", &ClangdLSPServer::onSwitchSourceHeader);
MsgHandler->bind("textDocument/rename", &ClangdLSPServer::onRename);
@@ -755,6 +938,7 @@ ClangdLSPServer::ClangdLSPServer(class Transport &Transp,
MsgHandler->bind("workspace/didChangeWatchedFiles", &ClangdLSPServer::onFileEvent);
MsgHandler->bind("workspace/didChangeConfiguration", &ClangdLSPServer::onChangeConfiguration);
MsgHandler->bind("textDocument/symbolInfo", &ClangdLSPServer::onSymbolInfo);
+ MsgHandler->bind("textDocument/typeHierarchy", &ClangdLSPServer::onTypeHierarchy);
// clang-format on
}
@@ -839,17 +1023,12 @@ void ClangdLSPServer::onDiagnosticsReady(PathRef File,
// Cache FixIts
{
- // FIXME(ibiryukov): should be deleted when documents are removed
std::lock_guard<std::mutex> Lock(FixItsMutex);
FixItsMap[File] = LocalFixIts;
}
- // Publish diagnostics.
- notify("textDocument/publishDiagnostics",
- llvm::json::Object{
- {"uri", URI},
- {"diagnostics", std::move(LSPDiagnostics)},
- });
+ // Send a notification to the LSP client.
+ publishDiagnostics(URI, std::move(LSPDiagnostics));
}
void ClangdLSPServer::onFileUpdated(PathRef File, const TUStatus &Status) {
diff --git a/clangd/ClangdLSPServer.h b/clangd/ClangdLSPServer.h
index 80052b4a..171ba075 100644
--- a/clangd/ClangdLSPServer.h
+++ b/clangd/ClangdLSPServer.h
@@ -1,9 +1,8 @@
//===--- ClangdLSPServer.h - LSP server --------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -12,6 +11,7 @@
#include "ClangdServer.h"
#include "DraftStore.h"
+#include "Features.inc"
#include "FindSymbols.h"
#include "GlobalCompilationDatabase.h"
#include "Path.h"
@@ -38,8 +38,10 @@ public:
/// for compile_commands.json in all parent directories of each file.
/// If UseDirBasedCDB is false, compile commands are not read from disk.
// FIXME: Clean up signature around CDBs.
- ClangdLSPServer(Transport &Transp, const clangd::CodeCompleteOptions &CCOpts,
+ ClangdLSPServer(Transport &Transp, const FileSystemProvider &FSProvider,
+ const clangd::CodeCompleteOptions &CCOpts,
llvm::Optional<Path> CompileCommandsDir, bool UseDirBasedCDB,
+ llvm::Optional<OffsetEncoding> ForcedOffsetEncoding,
const ClangdServer::Options &Opts);
~ClangdLSPServer();
@@ -77,6 +79,8 @@ private:
void onCompletion(const CompletionParams &, Callback<CompletionList>);
void onSignatureHelp(const TextDocumentPositionParams &,
Callback<SignatureHelp>);
+ void onGoToDeclaration(const TextDocumentPositionParams &,
+ Callback<std::vector<Location>>);
void onGoToDefinition(const TextDocumentPositionParams &,
Callback<std::vector<Location>>);
void onReference(const ReferenceParams &, Callback<std::vector<Location>>);
@@ -91,6 +95,8 @@ private:
void onRename(const RenameParams &, Callback<WorkspaceEdit>);
void onHover(const TextDocumentPositionParams &,
Callback<llvm::Optional<Hover>>);
+ void onTypeHierarchy(const TypeHierarchyParams &,
+ Callback<llvm::Optional<TypeHierarchyItem>>);
void onChangeConfiguration(const DidChangeConfigurationParams &);
void onSymbolInfo(const TextDocumentPositionParams &,
Callback<std::vector<SymbolDetails>>);
@@ -109,6 +115,10 @@ private:
void reparseOpenedFiles();
void applyConfiguration(const ConfigurationSettings &Settings);
+ /// Sends a "publishDiagnostics" notification to the LSP client.
+ void publishDiagnostics(const URIForFile &File,
+ std::vector<clangd::Diagnostic> Diagnostics);
+
/// Used to indicate that the 'shutdown' request was received from the
/// Language Server client.
bool ShutdownRequestReceived = false;
@@ -129,7 +139,7 @@ private:
void call(StringRef Method, llvm::json::Value Params);
void notify(StringRef Method, llvm::json::Value Params);
- RealFileSystemProvider FSProvider;
+ const FileSystemProvider &FSProvider;
/// Options used for code completion
clangd::CodeCompleteOptions CCOpts;
/// Options used for diagnostics.
@@ -157,6 +167,7 @@ private:
// It is destroyed before run() returns, to ensure worker threads exit.
ClangdServer::Options ClangdServerOpts;
llvm::Optional<ClangdServer> Server;
+ llvm::Optional<OffsetEncoding> NegotiatedOffsetEncoding;
};
} // namespace clangd
} // namespace clang
diff --git a/clangd/ClangdServer.cpp b/clangd/ClangdServer.cpp
index 53a27bdb..374ffc0b 100644
--- a/clangd/ClangdServer.cpp
+++ b/clangd/ClangdServer.cpp
@@ -1,26 +1,30 @@
//===--- ClangdServer.cpp - Main clangd server code --------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "ClangdServer.h"
+#include "ClangdUnit.h"
#include "CodeComplete.h"
#include "FindSymbols.h"
#include "Headers.h"
+#include "Protocol.h"
#include "SourceCode.h"
+#include "TUScheduler.h"
#include "Trace.h"
-#include "XRefs.h"
+#include "index/CanonicalIncludes.h"
#include "index/FileIndex.h"
#include "index/Merge.h"
+#include "refactor/Tweak.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Core/Replacement.h"
#include "clang/Tooling/Refactoring/RefactoringResultConsumer.h"
#include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
#include "llvm/ADT/ArrayRef.h"
@@ -28,19 +32,29 @@
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <future>
+#include <memory>
#include <mutex>
namespace clang {
namespace clangd {
namespace {
-std::string getStandardResourceDir() {
- static int Dummy; // Just an address in this process.
- return CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy);
+// Expand a DiagnosticError to make it print-friendly (print the detailed
+// message, rather than "clang diagnostic").
+llvm::Error expandDiagnostics(llvm::Error Err, DiagnosticsEngine &DE) {
+ if (auto Diag = DiagnosticError::take(Err)) {
+ llvm::cantFail(std::move(Err));
+ SmallVector<char, 128> DiagMessage;
+ Diag->second.EmitToString(DE, DiagMessage);
+ return llvm::make_error<llvm::StringError>(DiagMessage,
+ llvm::inconvertibleErrorCode());
+ }
+ return Err;
}
class RefactoringResultCollector final
@@ -48,9 +62,6 @@ class RefactoringResultCollector final
public:
void handleError(llvm::Error Err) override {
assert(!Result.hasValue());
- // FIXME: figure out a way to return better message for DiagnosticError.
- // clangd uses llvm::toString to convert the Err to string, however, for
- // DiagnosticError, only "clang diagnostic" will be generated.
Result = std::move(Err);
}
@@ -71,9 +82,10 @@ struct UpdateIndexCallbacks : public ParsingCallbacks {
: FIndex(FIndex), DiagConsumer(DiagConsumer) {}
void onPreambleAST(PathRef Path, ASTContext &Ctx,
- std::shared_ptr<clang::Preprocessor> PP) override {
+ std::shared_ptr<clang::Preprocessor> PP,
+ const CanonicalIncludes &CanonIncludes) override {
if (FIndex)
- FIndex->updatePreamble(Path, Ctx, std::move(PP));
+ FIndex->updatePreamble(Path, Ctx, std::move(PP), CanonIncludes);
}
void onMainAST(PathRef Path, ParsedAST &AST) override {
@@ -107,20 +119,19 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
const FileSystemProvider &FSProvider,
DiagnosticsConsumer &DiagConsumer,
const Options &Opts)
- : CDB(CDB), FSProvider(FSProvider),
- ResourceDir(Opts.ResourceDir ? *Opts.ResourceDir
- : getStandardResourceDir()),
+ : FSProvider(FSProvider),
DynamicIdx(Opts.BuildDynamicSymbolIndex
? new FileIndex(Opts.HeavyweightDynamicSymbolIndex)
: nullptr),
+ ClangTidyOptProvider(Opts.ClangTidyOptProvider),
+ SuggestMissingIncludes(Opts.SuggestMissingIncludes),
WorkspaceRoot(Opts.WorkspaceRoot),
- PCHs(std::make_shared<PCHContainerOperations>()),
// Pass a callback into `WorkScheduler` to extract symbols from a newly
// parsed file and rebuild the file index synchronously each time an AST
// is parsed.
// FIXME(ioeric): this can be slow and we may be able to index on less
// critical paths.
- WorkScheduler(Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
+ WorkScheduler(CDB, Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
llvm::make_unique<UpdateIndexCallbacks>(DynamicIdx.get(),
DiagConsumer),
Opts.UpdateDebounce, Opts.RetentionPolicy) {
@@ -137,7 +148,7 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
AddIndex(Opts.StaticIndex);
if (Opts.BackgroundIndex) {
BackgroundIdx = llvm::make_unique<BackgroundIndex>(
- Context::current().clone(), ResourceDir, FSProvider, CDB,
+ Context::current().clone(), FSProvider, CDB,
BackgroundIndexStorage::createDiskBackedStorageFactory(),
Opts.BackgroundIndexRebuildPeriodMs);
AddIndex(BackgroundIdx.get());
@@ -148,14 +159,19 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
void ClangdServer::addDocument(PathRef File, llvm::StringRef Contents,
WantDiagnostics WantDiags) {
- // FIXME: some build systems like Bazel will take time to preparing
- // environment to build the file, it would be nice if we could emit a
- // "PreparingBuild" status to inform users, it is non-trivial given the
- // current implementation.
- WorkScheduler.update(File,
- ParseInputs{getCompileCommand(File),
- FSProvider.getFileSystem(), Contents.str()},
- WantDiags);
+ ParseOptions Opts;
+ Opts.ClangTidyOpts = tidy::ClangTidyOptions::getDefaults();
+ if (ClangTidyOptProvider)
+ Opts.ClangTidyOpts = ClangTidyOptProvider->getOptions(File);
+ Opts.SuggestMissingIncludes = SuggestMissingIncludes;
+
+ // Compile command is set asynchronously during update, as it can be slow.
+ ParseInputs Inputs;
+ Inputs.FS = FSProvider.getFileSystem();
+ Inputs.Contents = Contents;
+ Inputs.Opts = std::move(Opts);
+ Inputs.Index = Index;
+ WorkScheduler.update(File, Inputs, WantDiags);
}
void ClangdServer::removeDocument(PathRef File) { WorkScheduler.remove(File); }
@@ -168,11 +184,8 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
if (!CodeCompleteOpts.Index) // Respect overridden index.
CodeCompleteOpts.Index = Index;
- // Copy PCHs to avoid accessing this->PCHs concurrently
- std::shared_ptr<PCHContainerOperations> PCHs = this->PCHs;
auto FS = FSProvider.getFileSystem();
-
- auto Task = [PCHs, Pos, FS, CodeCompleteOpts,
+ auto Task = [Pos, FS, CodeCompleteOpts,
this](Path File, Callback<CodeCompleteResult> CB,
llvm::Expected<InputsAndPreamble> IP) {
if (!IP)
@@ -181,18 +194,25 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
return CB(llvm::make_error<CancelledError>());
llvm::Optional<SpeculativeFuzzyFind> SpecFuzzyFind;
- if (CodeCompleteOpts.Index && CodeCompleteOpts.SpeculativeIndexRequest) {
- SpecFuzzyFind.emplace();
- {
- std::lock_guard<std::mutex> Lock(CachedCompletionFuzzyFindRequestMutex);
- SpecFuzzyFind->CachedReq = CachedCompletionFuzzyFindRequestByFile[File];
+ if (!IP->Preamble) {
+ // No speculation in Fallback mode, as it's supposed to be much faster
+ // without compiling.
+ vlog("Build for file {0} is not ready. Enter fallback mode.", File);
+ } else {
+ if (CodeCompleteOpts.Index && CodeCompleteOpts.SpeculativeIndexRequest) {
+ SpecFuzzyFind.emplace();
+ {
+ std::lock_guard<std::mutex> Lock(
+ CachedCompletionFuzzyFindRequestMutex);
+ SpecFuzzyFind->CachedReq =
+ CachedCompletionFuzzyFindRequestByFile[File];
+ }
}
}
-
// FIXME(ibiryukov): even if Preamble is non-null, we may want to check
// both the old and the new version in case only one of them matches.
CodeCompleteResult Result = clangd::codeComplete(
- File, IP->Command, IP->Preamble, IP->Contents, Pos, FS, PCHs,
+ File, IP->Command, IP->Preamble, IP->Contents, Pos, FS,
CodeCompleteOpts, SpecFuzzyFind ? SpecFuzzyFind.getPointer() : nullptr);
{
clang::clangd::trace::Span Tracer("Completion results callback");
@@ -210,24 +230,25 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
};
// We use a potentially-stale preamble because latency is critical here.
- WorkScheduler.runWithPreamble("CodeComplete", File, TUScheduler::Stale,
+ WorkScheduler.runWithPreamble("CodeComplete", File,
+ Opts.AllowFallback ? TUScheduler::StaleOrAbsent
+ : TUScheduler::Stale,
Bind(Task, File.str(), std::move(CB)));
}
void ClangdServer::signatureHelp(PathRef File, Position Pos,
Callback<SignatureHelp> CB) {
- auto PCHs = this->PCHs;
auto FS = FSProvider.getFileSystem();
auto *Index = this->Index;
- auto Action = [Pos, FS, PCHs, Index](Path File, Callback<SignatureHelp> CB,
- llvm::Expected<InputsAndPreamble> IP) {
+ auto Action = [Pos, FS, Index](Path File, Callback<SignatureHelp> CB,
+ llvm::Expected<InputsAndPreamble> IP) {
if (!IP)
return CB(IP.takeError());
auto PreambleData = IP->Preamble;
CB(clangd::signatureHelp(File, IP->Command, PreambleData, IP->Contents, Pos,
- FS, PCHs, Index));
+ FS, Index));
};
// Unlike code completion, we wait for an up-to-date preamble here.
@@ -272,9 +293,9 @@ ClangdServer::formatOnType(llvm::StringRef Code, PathRef File, Position Pos) {
}
void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
- Callback<std::vector<tooling::Replacement>> CB) {
+ Callback<std::vector<TextEdit>> CB) {
auto Action = [Pos](Path File, std::string NewName,
- Callback<std::vector<tooling::Replacement>> CB,
+ Callback<std::vector<TextEdit>> CB,
llvm::Expected<InputsAndAST> InpAST) {
if (!InpAST)
return CB(InpAST.takeError());
@@ -290,15 +311,17 @@ void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
auto Rename = clang::tooling::RenameOccurrences::initiate(
Context, SourceRange(SourceLocationBeg), NewName);
if (!Rename)
- return CB(Rename.takeError());
+ return CB(expandDiagnostics(Rename.takeError(),
+ AST.getASTContext().getDiagnostics()));
Rename->invoke(ResultCollector, Context);
assert(ResultCollector.Result.hasValue());
if (!ResultCollector.Result.getValue())
- return CB(ResultCollector.Result->takeError());
+ return CB(expandDiagnostics(ResultCollector.Result->takeError(),
+ AST.getASTContext().getDiagnostics()));
- std::vector<tooling::Replacement> Replacements;
+ std::vector<TextEdit> Replacements;
for (const tooling::AtomicChange &Change : ResultCollector.Result->get()) {
tooling::Replacements ChangeReps = Change.getReplacements();
for (const auto &Rep : ChangeReps) {
@@ -312,7 +335,8 @@ void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
// * rename globally in project
// * rename in open files
if (Rep.getFilePath() == File)
- Replacements.push_back(Rep);
+ Replacements.push_back(
+ replacementToEdit(InpAST->Inputs.Contents, Rep));
}
}
return CB(std::move(Replacements));
@@ -322,6 +346,63 @@ void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
"Rename", File, Bind(Action, File.str(), NewName.str(), std::move(CB)));
}
+static llvm::Expected<Tweak::Selection>
+tweakSelection(const Range &Sel, const InputsAndAST &AST) {
+ auto Begin = positionToOffset(AST.Inputs.Contents, Sel.start);
+ if (!Begin)
+ return Begin.takeError();
+ auto End = positionToOffset(AST.Inputs.Contents, Sel.end);
+ if (!End)
+ return End.takeError();
+ return Tweak::Selection(AST.AST, *Begin, *End);
+}
+
+void ClangdServer::enumerateTweaks(PathRef File, Range Sel,
+ Callback<std::vector<TweakRef>> CB) {
+ auto Action = [Sel](decltype(CB) CB, std::string File,
+ Expected<InputsAndAST> InpAST) {
+ if (!InpAST)
+ return CB(InpAST.takeError());
+ auto Selection = tweakSelection(Sel, *InpAST);
+ if (!Selection)
+ return CB(Selection.takeError());
+ std::vector<TweakRef> Res;
+ for (auto &T : prepareTweaks(*Selection))
+ Res.push_back({T->id(), T->title()});
+ CB(std::move(Res));
+ };
+
+ WorkScheduler.runWithAST("EnumerateTweaks", File,
+ Bind(Action, std::move(CB), File.str()));
+}
+
+void ClangdServer::applyTweak(PathRef File, Range Sel, StringRef TweakID,
+ Callback<tooling::Replacements> CB) {
+ auto Action = [Sel](decltype(CB) CB, std::string File, std::string TweakID,
+ Expected<InputsAndAST> InpAST) {
+ if (!InpAST)
+ return CB(InpAST.takeError());
+ auto Selection = tweakSelection(Sel, *InpAST);
+ if (!Selection)
+ return CB(Selection.takeError());
+ auto A = prepareTweak(TweakID, *Selection);
+ if (!A)
+ return CB(A.takeError());
+ auto RawReplacements = (*A)->apply(*Selection);
+ if (!RawReplacements)
+ return CB(RawReplacements.takeError());
+ // FIXME: this function has I/O operations (find .clang-format file), figure
+ // out a way to cache the format style.
+ auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents,
+ InpAST->Inputs.FS.get());
+ return CB(
+ cleanupAndFormat(InpAST->Inputs.Contents, *RawReplacements, Style));
+ };
+ WorkScheduler.runWithAST(
+ "ApplyTweak", File,
+ Bind(Action, std::move(CB), File.str(), TweakID.str()));
+}
+
void ClangdServer::dumpAST(PathRef File,
llvm::unique_function<void(std::string)> Callback) {
auto Action = [](decltype(Callback) Callback,
@@ -342,13 +423,13 @@ void ClangdServer::dumpAST(PathRef File,
WorkScheduler.runWithAST("DumpAST", File, Bind(Action, std::move(Callback)));
}
-void ClangdServer::findDefinitions(PathRef File, Position Pos,
- Callback<std::vector<Location>> CB) {
- auto Action = [Pos, this](Callback<std::vector<Location>> CB,
+void ClangdServer::locateSymbolAt(PathRef File, Position Pos,
+ Callback<std::vector<LocatedSymbol>> CB) {
+ auto Action = [Pos, this](decltype(CB) CB,
llvm::Expected<InputsAndAST> InpAST) {
if (!InpAST)
return CB(InpAST.takeError());
- CB(clangd::findDefinitions(InpAST->AST, Pos, Index));
+ CB(clangd::locateSymbolAt(InpAST->AST, Pos, Index));
};
WorkScheduler.runWithAST("Definitions", File, Bind(Action, std::move(CB)));
@@ -415,20 +496,16 @@ llvm::Expected<tooling::Replacements>
ClangdServer::formatCode(llvm::StringRef Code, PathRef File,
llvm::ArrayRef<tooling::Range> Ranges) {
// Call clang-format.
- auto FS = FSProvider.getFileSystem();
- auto Style = format::getStyle(format::DefaultFormatStyle, File,
- format::DefaultFallbackStyle, Code, FS.get());
- if (!Style)
- return Style.takeError();
-
+ format::FormatStyle Style =
+ getFormatStyleForFile(File, Code, FSProvider.getFileSystem().get());
tooling::Replacements IncludeReplaces =
- format::sortIncludes(*Style, Code, Ranges, File);
+ format::sortIncludes(Style, Code, Ranges, File);
auto Changed = tooling::applyAllReplacements(Code, IncludeReplaces);
if (!Changed)
return Changed.takeError();
return IncludeReplaces.merge(format::reformat(
- Style.get(), *Changed,
+ Style, *Changed,
tooling::calculateRangesAfterReplacements(IncludeReplaces, Ranges),
File));
}
@@ -457,16 +534,17 @@ void ClangdServer::findHover(PathRef File, Position Pos,
WorkScheduler.runWithAST("Hover", File, Bind(Action, std::move(CB)));
}
-tooling::CompileCommand ClangdServer::getCompileCommand(PathRef File) {
- trace::Span Span("GetCompileCommand");
- llvm::Optional<tooling::CompileCommand> C = CDB.getCompileCommand(File);
- if (!C) // FIXME: Suppress diagnostics? Let the user know?
- C = CDB.getFallbackCommand(File);
+void ClangdServer::typeHierarchy(PathRef File, Position Pos, int Resolve,
+ TypeHierarchyDirection Direction,
+ Callback<Optional<TypeHierarchyItem>> CB) {
+ auto Action = [Pos, Resolve, Direction](decltype(CB) CB,
+ Expected<InputsAndAST> InpAST) {
+ if (!InpAST)
+ return CB(InpAST.takeError());
+ CB(clangd::getTypeHierarchy(InpAST->AST, Pos, Resolve, Direction));
+ };
- // Inject the resource dir.
- // FIXME: Don't overwrite it if it's already there.
- C->CommandLine.push_back("-resource-dir=" + ResourceDir);
- return std::move(*C);
+ WorkScheduler.runWithAST("Type Hierarchy", File, Bind(Action, std::move(CB)));
}
void ClangdServer::onFileEvent(const DidChangeWatchedFilesParams &Params) {
diff --git a/clangd/ClangdServer.h b/clangd/ClangdServer.h
index 213f042c..b5360a7a 100644
--- a/clangd/ClangdServer.h
+++ b/clangd/ClangdServer.h
@@ -1,15 +1,15 @@
//===--- ClangdServer.h - Main clangd server code ----------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CLANGD_CLANGDSERVER_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDSERVER_H
+#include "../clang-tidy/ClangTidyOptions.h"
#include "Cancellation.h"
#include "ClangdUnit.h"
#include "CodeComplete.h"
@@ -18,11 +18,14 @@
#include "GlobalCompilationDatabase.h"
#include "Protocol.h"
#include "TUScheduler.h"
+#include "XRefs.h"
#include "index/Background.h"
#include "index/FileIndex.h"
#include "index/Index.h"
+#include "refactor/Tweak.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/FunctionExtras.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
@@ -33,8 +36,6 @@
#include <utility>
namespace clang {
-class PCHContainerOperations;
-
namespace clangd {
// FIXME: find a better name.
@@ -93,6 +94,13 @@ public:
/// If set, use this index to augment code completion results.
SymbolIndex *StaticIndex = nullptr;
+ /// If set, enable clang-tidy in clangd, used to get clang-tidy
+ /// configurations for a particular file.
+ /// Clangd supports only a small subset of ClangTidyOptions, these options
+ /// (Checks, CheckOptions) are about which clang-tidy checks will be
+ /// enabled.
+ tidy::ClangTidyOptionsProvider *ClangTidyOptProvider = nullptr;
+
/// Clangd's workspace root. Relevant for "workspace" operations not bound
/// to a particular file.
/// FIXME: If not set, should use the current working directory.
@@ -107,6 +115,8 @@ public:
/// Time to wait after a new file version before computing diagnostics.
std::chrono::steady_clock::duration UpdateDebounce =
std::chrono::milliseconds(500);
+
+ bool SuggestMissingIncludes = false;
};
// Sensible default options for use in tests.
// Features like indexing must be enabled if desired.
@@ -156,9 +166,9 @@ public:
/// called for tracked files.
void signatureHelp(PathRef File, Position Pos, Callback<SignatureHelp> CB);
- /// Get definition of symbol at a specified \p Line and \p Column in \p File.
- void findDefinitions(PathRef File, Position Pos,
- Callback<std::vector<Location>> CB);
+ /// Find declaration/definition locations of symbol at a specified position.
+ void locateSymbolAt(PathRef File, Position Pos,
+ Callback<std::vector<LocatedSymbol>> CB);
/// Helper function that returns a path to the corresponding source file when
/// given a header file and vice versa.
@@ -172,6 +182,11 @@ public:
void findHover(PathRef File, Position Pos,
Callback<llvm::Optional<Hover>> CB);
+ /// Get information about type hierarchy for a given position.
+ void typeHierarchy(PathRef File, Position Pos, int Resolve,
+ TypeHierarchyDirection Direction,
+ Callback<llvm::Optional<TypeHierarchyItem>> CB);
+
/// Retrieve the top symbols from the workspace matching a query.
void workspaceSymbols(StringRef Query, int Limit,
Callback<std::vector<SymbolInformation>> CB);
@@ -200,7 +215,19 @@ public:
/// Rename all occurrences of the symbol at the \p Pos in \p File to
/// \p NewName.
void rename(PathRef File, Position Pos, llvm::StringRef NewName,
- Callback<std::vector<tooling::Replacement>> CB);
+ Callback<std::vector<TextEdit>> CB);
+
+ struct TweakRef {
+ std::string ID; /// ID to pass for applyTweak.
+ std::string Title; /// A single-line message to show in the UI.
+ };
+ /// Enumerate the code tweaks available to the user at a specified point.
+ void enumerateTweaks(PathRef File, Range Sel,
+ Callback<std::vector<TweakRef>> CB);
+
+ /// Apply the code tweak with a specified \p ID.
+ void applyTweak(PathRef File, Range Sel, StringRef ID,
+ Callback<tooling::Replacements> CB);
/// Only for testing purposes.
/// Waits until all requests to worker thread are finished and dumps AST for
@@ -223,10 +250,6 @@ public:
/// FIXME: those metrics might be useful too, we should add them.
std::vector<std::pair<Path, std::size_t>> getUsedBytesPerFile() const;
- /// Returns the active dynamic index if one was built.
- /// This can be useful for testing, debugging, or observing memory usage.
- const SymbolIndex *dynamicIndex() const { return DynamicIdx.get(); }
-
// Blocks the main thread until the server is idle. Only for use in tests.
// Returns false if the timeout expires.
LLVM_NODISCARD bool
@@ -239,9 +262,6 @@ private:
formatCode(llvm::StringRef Code, PathRef File,
ArrayRef<tooling::Range> Ranges);
- tooling::CompileCommand getCompileCommand(PathRef File);
-
- const GlobalCompilationDatabase &CDB;
const FileSystemProvider &FSProvider;
Path ResourceDir;
@@ -258,13 +278,19 @@ private:
// Storage for merged views of the various indexes.
std::vector<std::unique_ptr<SymbolIndex>> MergedIdx;
+ // The provider used to provide a clang-tidy option for a specific file.
+ tidy::ClangTidyOptionsProvider *ClangTidyOptProvider = nullptr;
+
+ // If this is true, suggest include insertion fixes for diagnostic errors that
+ // can be caused by missing includes (e.g. member access in incomplete type).
+ bool SuggestMissingIncludes = false;
+
// GUARDED_BY(CachedCompletionFuzzyFindRequestMutex)
llvm::StringMap<llvm::Optional<FuzzyFindRequest>>
CachedCompletionFuzzyFindRequestByFile;
mutable std::mutex CachedCompletionFuzzyFindRequestMutex;
llvm::Optional<std::string> WorkspaceRoot;
- std::shared_ptr<PCHContainerOperations> PCHs;
// WorkScheduler has to be the last member, because its destructor has to be
// called before all other members to stop the worker thread that references
// ClangdServer.
diff --git a/clangd/ClangdUnit.cpp b/clangd/ClangdUnit.cpp
index 5add1179..c8c41330 100644
--- a/clangd/ClangdUnit.cpp
+++ b/clangd/ClangdUnit.cpp
@@ -1,9 +1,8 @@
//===--- ClangdUnit.cpp ------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -12,11 +11,17 @@
#include "../clang-tidy/ClangTidyModuleRegistry.h"
#include "Compiler.h"
#include "Diagnostics.h"
+#include "Headers.h"
+#include "IncludeFixer.h"
#include "Logger.h"
#include "SourceCode.h"
#include "Trace.h"
+#include "index/CanonicalIncludes.h"
+#include "index/Index.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
@@ -29,12 +34,15 @@
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Sema/Sema.h"
#include "clang/Serialization/ASTWriter.h"
+#include "clang/Serialization/PCHContainerOperations.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <memory>
namespace clang {
namespace clangd {
@@ -88,18 +96,55 @@ private:
std::vector<Decl *> TopLevelDecls;
};
+class CollectMainFileMacros : public PPCallbacks {
+public:
+ explicit CollectMainFileMacros(const SourceManager &SM,
+ std::vector<std::string> *Out)
+ : SM(SM), Out(Out) {}
+
+ void FileChanged(SourceLocation Loc, FileChangeReason,
+ SrcMgr::CharacteristicKind, FileID Prev) {
+ InMainFile = SM.isWrittenInMainFile(Loc);
+ }
+
+ void MacroDefined(const Token &MacroName, const MacroDirective *MD) {
+ if (InMainFile)
+ MainFileMacros.insert(MacroName.getIdentifierInfo()->getName());
+ }
+
+ void EndOfMainFile() {
+ for (const auto& Entry : MainFileMacros)
+ Out->push_back(Entry.getKey());
+ llvm::sort(*Out);
+ }
+
+ private:
+ const SourceManager &SM;
+ bool InMainFile = true;
+ llvm::StringSet<> MainFileMacros;
+ std::vector<std::string> *Out;
+};
+
class CppFilePreambleCallbacks : public PreambleCallbacks {
public:
CppFilePreambleCallbacks(PathRef File, PreambleParsedCallback ParsedCallback)
- : File(File), ParsedCallback(ParsedCallback) {}
+ : File(File), ParsedCallback(ParsedCallback) {
+ addSystemHeadersMapping(&CanonIncludes);
+ }
IncludeStructure takeIncludes() { return std::move(Includes); }
+ std::vector<std::string> takeMainFileMacros() {
+ return std::move(MainFileMacros);
+ }
+
+ CanonicalIncludes takeCanonicalIncludes() { return std::move(CanonIncludes); }
+
void AfterExecute(CompilerInstance &CI) override {
if (!ParsedCallback)
return;
trace::Span Tracer("Running PreambleCallback");
- ParsedCallback(CI.getASTContext(), CI.getPreprocessorPtr());
+ ParsedCallback(CI.getASTContext(), CI.getPreprocessorPtr(), CanonIncludes);
}
void BeforeExecute(CompilerInstance &CI) override {
@@ -108,13 +153,23 @@ public:
std::unique_ptr<PPCallbacks> createPPCallbacks() override {
assert(SourceMgr && "SourceMgr must be set at this point");
- return collectIncludeStructureCallback(*SourceMgr, &Includes);
+ return llvm::make_unique<PPChainedCallbacks>(
+ collectIncludeStructureCallback(*SourceMgr, &Includes),
+ llvm::make_unique<CollectMainFileMacros>(*SourceMgr, &MainFileMacros));
+ }
+
+ CommentHandler *getCommentHandler() override {
+ IWYUHandler = collectIWYUHeaderMaps(&CanonIncludes);
+ return IWYUHandler.get();
}
private:
PathRef File;
PreambleParsedCallback ParsedCallback;
IncludeStructure Includes;
+ CanonicalIncludes CanonIncludes;
+ std::vector<std::string> MainFileMacros;
+ std::unique_ptr<CommentHandler> IWYUHandler = nullptr;
SourceManager *SourceMgr = nullptr;
};
@@ -133,6 +188,9 @@ public:
CompilerInstance &Clang) {
auto &PP = Clang.getPreprocessor();
auto *ExistingCallbacks = PP.getPPCallbacks();
+ // No need to replay events if nobody is listening.
+ if (!ExistingCallbacks)
+ return;
PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(
new ReplayPreamble(Includes, ExistingCallbacks,
Clang.getSourceManager(), PP, Clang.getLangOpts())));
@@ -227,8 +285,8 @@ llvm::Optional<ParsedAST>
ParsedAST::build(std::unique_ptr<CompilerInvocation> CI,
std::shared_ptr<const PreambleData> Preamble,
std::unique_ptr<llvm::MemoryBuffer> Buffer,
- std::shared_ptr<PCHContainerOperations> PCHs,
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
+ const SymbolIndex *Index, const ParseOptions &Opts) {
assert(CI);
// Command-line parsing sets DisableFree to true by default, but we don't want
// to leak memory in clangd.
@@ -237,9 +295,10 @@ ParsedAST::build(std::unique_ptr<CompilerInvocation> CI,
Preamble ? &Preamble->Preamble : nullptr;
StoreDiags ASTDiags;
- auto Clang =
- prepareCompilerInstance(std::move(CI), PreamblePCH, std::move(Buffer),
- std::move(PCHs), std::move(VFS), ASTDiags);
+ std::string Content = Buffer->getBuffer();
+
+ auto Clang = prepareCompilerInstance(std::move(CI), PreamblePCH,
+ std::move(Buffer), VFS, ASTDiags);
if (!Clang)
return None;
@@ -262,30 +321,48 @@ ParsedAST::build(std::unique_ptr<CompilerInvocation> CI,
llvm::Optional<tidy::ClangTidyContext> CTContext;
{
trace::Span Tracer("ClangTidyInit");
+ dlog("ClangTidy configuration for file {0}: {1}", MainInput.getFile(),
+ tidy::configurationAsText(Opts.ClangTidyOpts));
tidy::ClangTidyCheckFactories CTFactories;
for (const auto &E : tidy::ClangTidyModuleRegistry::entries())
E.instantiate()->addCheckFactories(CTFactories);
- auto CTOpts = tidy::ClangTidyOptions::getDefaults();
- // FIXME: this needs to be configurable, and we need to support .clang-tidy
- // files and other options providers.
- // These checks exercise the matcher- and preprocessor-based hooks.
- CTOpts.Checks = "bugprone-sizeof-expression,"
- "bugprone-macro-repeated-side-effects,"
- "modernize-deprecated-headers";
CTContext.emplace(llvm::make_unique<tidy::DefaultOptionsProvider>(
- tidy::ClangTidyGlobalOptions(), CTOpts));
+ tidy::ClangTidyGlobalOptions(), Opts.ClangTidyOpts));
CTContext->setDiagnosticsEngine(&Clang->getDiagnostics());
CTContext->setASTContext(&Clang->getASTContext());
CTContext->setCurrentFile(MainInput.getFile());
CTFactories.createChecks(CTContext.getPointer(), CTChecks);
+ Preprocessor *PP = &Clang->getPreprocessor();
for (const auto &Check : CTChecks) {
// FIXME: the PP callbacks skip the entire preamble.
// Checks that want to see #includes in the main file do not see them.
- Check->registerPPCallbacks(*Clang);
+ Check->registerPPCallbacks(Clang->getSourceManager(), PP, PP);
Check->registerMatchers(&CTFinder);
}
}
+ // Add IncludeFixer which can recorver diagnostics caused by missing includes
+ // (e.g. incomplete type) and attach include insertion fixes to diagnostics.
+ llvm::Optional<IncludeFixer> FixIncludes;
+ auto BuildDir = VFS->getCurrentWorkingDirectory();
+ if (Opts.SuggestMissingIncludes && Index && !BuildDir.getError()) {
+ auto Style = getFormatStyleForFile(MainInput.getFile(), Content, VFS.get());
+ auto Inserter = std::make_shared<IncludeInserter>(
+ MainInput.getFile(), Content, Style, BuildDir.get(),
+ &Clang->getPreprocessor().getHeaderSearchInfo());
+ if (Preamble) {
+ for (const auto &Inc : Preamble->Includes.MainFileIncludes)
+ Inserter->addExisting(Inc);
+ }
+ FixIncludes.emplace(MainInput.getFile(), Inserter, *Index,
+ /*IndexRequestLimit=*/5);
+ ASTDiags.contributeFixes([&FixIncludes](DiagnosticsEngine::Level DiagLevl,
+ const clang::Diagnostic &Info) {
+ return FixIncludes->fix(DiagLevl, Info);
+ });
+ Clang->setExternalSemaSource(FixIncludes->unresolvedNameRecorder());
+ }
+
// Copy over the includes from the preamble, then combine with the
// non-preamble includes below.
auto Includes = Preamble ? Preamble->Includes : IncludeStructure{};
@@ -298,6 +375,17 @@ ParsedAST::build(std::unique_ptr<CompilerInvocation> CI,
Clang->getPreprocessor().addPPCallbacks(
collectIncludeStructureCallback(Clang->getSourceManager(), &Includes));
+ // Copy over the includes from the preamble, then combine with the
+ // non-preamble includes below.
+ CanonicalIncludes CanonIncludes;
+ if (Preamble)
+ CanonIncludes = Preamble->CanonIncludes;
+ else
+ addSystemHeadersMapping(&CanonIncludes);
+ std::unique_ptr<CommentHandler> IWYUHandler =
+ collectIWYUHeaderMaps(&CanonIncludes);
+ Clang->getPreprocessor().addCommentHandler(IWYUHandler.get());
+
if (!Action->Execute())
log("Execute() failed when building AST for {0}", MainInput.getFile());
@@ -321,13 +409,13 @@ ParsedAST::build(std::unique_ptr<CompilerInvocation> CI,
// So just inform the preprocessor of EOF, while keeping everything alive.
Clang->getPreprocessor().EndSourceFile();
- std::vector<Diag> Diags = ASTDiags.take();
+ std::vector<Diag> Diags = ASTDiags.take(CTContext.getPointer());
// Add diagnostics from the preamble, if any.
if (Preamble)
Diags.insert(Diags.begin(), Preamble->Diags.begin(), Preamble->Diags.end());
return ParsedAST(std::move(Preamble), std::move(Clang), std::move(Action),
std::move(ParsedDecls), std::move(Diags),
- std::move(Includes));
+ std::move(Includes), std::move(CanonIncludes));
}
ParsedAST::ParsedAST(ParsedAST &&Other) = default;
@@ -403,59 +491,39 @@ const IncludeStructure &ParsedAST::getIncludeStructure() const {
return Includes;
}
+const CanonicalIncludes &ParsedAST::getCanonicalIncludes() const {
+ return CanonIncludes;
+}
+
PreambleData::PreambleData(PrecompiledPreamble Preamble,
std::vector<Diag> Diags, IncludeStructure Includes,
- std::unique_ptr<PreambleFileStatusCache> StatCache)
+ std::vector<std::string> MainFileMacros,
+ std::unique_ptr<PreambleFileStatusCache> StatCache,
+ CanonicalIncludes CanonIncludes)
: Preamble(std::move(Preamble)), Diags(std::move(Diags)),
- Includes(std::move(Includes)), StatCache(std::move(StatCache)) {}
+ Includes(std::move(Includes)), MainFileMacros(std::move(MainFileMacros)),
+ StatCache(std::move(StatCache)), CanonIncludes(std::move(CanonIncludes)) {
+}
ParsedAST::ParsedAST(std::shared_ptr<const PreambleData> Preamble,
std::unique_ptr<CompilerInstance> Clang,
std::unique_ptr<FrontendAction> Action,
std::vector<Decl *> LocalTopLevelDecls,
- std::vector<Diag> Diags, IncludeStructure Includes)
+ std::vector<Diag> Diags, IncludeStructure Includes,
+ CanonicalIncludes CanonIncludes)
: Preamble(std::move(Preamble)), Clang(std::move(Clang)),
Action(std::move(Action)), Diags(std::move(Diags)),
LocalTopLevelDecls(std::move(LocalTopLevelDecls)),
- Includes(std::move(Includes)) {
+ Includes(std::move(Includes)), CanonIncludes(std::move(CanonIncludes)) {
assert(this->Clang);
assert(this->Action);
}
-std::unique_ptr<CompilerInvocation>
-buildCompilerInvocation(const ParseInputs &Inputs) {
- std::vector<const char *> ArgStrs;
- for (const auto &S : Inputs.CompileCommand.CommandLine)
- ArgStrs.push_back(S.c_str());
-
- if (Inputs.FS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
- log("Couldn't set working directory when creating compiler invocation.");
- // We proceed anyway, our lit-tests rely on results for non-existing working
- // dirs.
- }
-
- // FIXME(ibiryukov): store diagnostics from CommandLine when we start
- // reporting them.
- IgnoreDiagnostics IgnoreDiagnostics;
- llvm::IntrusiveRefCntPtr<DiagnosticsEngine> CommandLineDiagsEngine =
- CompilerInstance::createDiagnostics(new DiagnosticOptions,
- &IgnoreDiagnostics, false);
- std::unique_ptr<CompilerInvocation> CI = createInvocationFromCommandLine(
- ArgStrs, CommandLineDiagsEngine, Inputs.FS);
- if (!CI)
- return nullptr;
- // createInvocationFromCommandLine sets DisableFree.
- CI->getFrontendOpts().DisableFree = false;
- CI->getLangOpts()->CommentOpts.ParseAllComments = true;
- return CI;
-}
-
std::shared_ptr<const PreambleData>
buildPreamble(PathRef FileName, CompilerInvocation &CI,
std::shared_ptr<const PreambleData> OldPreamble,
const tooling::CompileCommand &OldCompileCommand,
- const ParseInputs &Inputs,
- std::shared_ptr<PCHContainerOperations> PCHs, bool StoreInMemory,
+ const ParseInputs &Inputs, bool StoreInMemory,
PreambleParsedCallback PreambleCallback) {
// Note that we don't need to copy the input contents, preamble can live
// without those.
@@ -500,7 +568,8 @@ buildPreamble(PathRef FileName, CompilerInvocation &CI,
auto StatCache = llvm::make_unique<PreambleFileStatusCache>(AbsFileName);
auto BuiltPreamble = PrecompiledPreamble::Build(
CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine,
- StatCache->getProducingFS(Inputs.FS), PCHs, StoreInMemory,
+ StatCache->getProducingFS(Inputs.FS),
+ std::make_shared<PCHContainerOperations>(), StoreInMemory,
SerializedDeclsCollector);
// When building the AST for the main file, we do want the function
@@ -510,9 +579,12 @@ buildPreamble(PathRef FileName, CompilerInvocation &CI,
if (BuiltPreamble) {
vlog("Built preamble of size {0} for file {1}", BuiltPreamble->getSize(),
FileName);
+ std::vector<Diag> Diags = PreambleDiagnostics.take();
return std::make_shared<PreambleData>(
- std::move(*BuiltPreamble), PreambleDiagnostics.take(),
- SerializedDeclsCollector.takeIncludes(), std::move(StatCache));
+ std::move(*BuiltPreamble), std::move(Diags),
+ SerializedDeclsCollector.takeIncludes(),
+ SerializedDeclsCollector.takeMainFileMacros(), std::move(StatCache),
+ SerializedDeclsCollector.takeCanonicalIncludes());
} else {
elog("Could not build a preamble for file {0}", FileName);
return nullptr;
@@ -522,8 +594,7 @@ buildPreamble(PathRef FileName, CompilerInvocation &CI,
llvm::Optional<ParsedAST>
buildAST(PathRef FileName, std::unique_ptr<CompilerInvocation> Invocation,
const ParseInputs &Inputs,
- std::shared_ptr<const PreambleData> Preamble,
- std::shared_ptr<PCHContainerOperations> PCHs) {
+ std::shared_ptr<const PreambleData> Preamble) {
trace::Span Tracer("BuildAST");
SPAN_ATTACH(Tracer, "File", FileName);
@@ -539,7 +610,7 @@ buildAST(PathRef FileName, std::unique_ptr<CompilerInvocation> Invocation,
return ParsedAST::build(llvm::make_unique<CompilerInvocation>(*Invocation),
Preamble,
llvm::MemoryBuffer::getMemBufferCopy(Inputs.Contents),
- PCHs, std::move(VFS));
+ std::move(VFS), Inputs.Index, Inputs.Opts);
}
SourceLocation getBeginningOfIdentifier(ParsedAST &Unit, const Position &Pos,
diff --git a/clangd/ClangdUnit.h b/clangd/ClangdUnit.h
index 15bf998d..d5d29981 100644
--- a/clangd/ClangdUnit.h
+++ b/clangd/ClangdUnit.h
@@ -1,21 +1,23 @@
//===--- ClangdUnit.h --------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CLANGD_CLANGDUNIT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H
+#include "Compiler.h"
#include "Diagnostics.h"
#include "FS.h"
#include "Function.h"
#include "Headers.h"
#include "Path.h"
#include "Protocol.h"
+#include "index/CanonicalIncludes.h"
+#include "index/Index.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/PrecompiledPreamble.h"
#include "clang/Lex/Preprocessor.h"
@@ -31,15 +33,14 @@ class raw_ostream;
namespace vfs {
class FileSystem;
-}
+} // namespace vfs
} // namespace llvm
namespace clang {
-class PCHContainerOperations;
namespace tooling {
struct CompileCommand;
-}
+} // namespace tooling
namespace clangd {
@@ -47,7 +48,9 @@ namespace clangd {
struct PreambleData {
PreambleData(PrecompiledPreamble Preamble, std::vector<Diag> Diags,
IncludeStructure Includes,
- std::unique_ptr<PreambleFileStatusCache> StatCache);
+ std::vector<std::string> MainFileMacros,
+ std::unique_ptr<PreambleFileStatusCache> StatCache,
+ CanonicalIncludes CanonIncludes);
tooling::CompileCommand CompileCommand;
PrecompiledPreamble Preamble;
@@ -55,16 +58,14 @@ struct PreambleData {
// Processes like code completions and go-to-definitions will need #include
// information, and their compile action skips preamble range.
IncludeStructure Includes;
+ // Macros defined in the preamble section of the main file.
+ // Users care about headers vs main-file, not preamble vs non-preamble.
+ // These should be treated as main-file entities e.g. for code completion.
+ std::vector<std::string> MainFileMacros;
// Cache of FS operations performed when building the preamble.
// When reusing a preamble, this cache can be consumed to save IO.
std::unique_ptr<PreambleFileStatusCache> StatCache;
-};
-
-/// Information required to run clang, e.g. to parse AST or do code completion.
-struct ParseInputs {
- tooling::CompileCommand CompileCommand;
- IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
- std::string Contents;
+ CanonicalIncludes CanonIncludes;
};
/// Stores and provides access to parsed AST.
@@ -76,8 +77,8 @@ public:
build(std::unique_ptr<clang::CompilerInvocation> CI,
std::shared_ptr<const PreambleData> Preamble,
std::unique_ptr<llvm::MemoryBuffer> Buffer,
- std::shared_ptr<PCHContainerOperations> PCHs,
- IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS);
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, const SymbolIndex *Index,
+ const ParseOptions &Opts);
ParsedAST(ParsedAST &&Other);
ParsedAST &operator=(ParsedAST &&Other);
@@ -105,13 +106,14 @@ public:
/// bytes. Does not include the size of the preamble.
std::size_t getUsedBytes() const;
const IncludeStructure &getIncludeStructure() const;
+ const CanonicalIncludes &getCanonicalIncludes() const;
private:
ParsedAST(std::shared_ptr<const PreambleData> Preamble,
std::unique_ptr<CompilerInstance> Clang,
std::unique_ptr<FrontendAction> Action,
std::vector<Decl *> LocalTopLevelDecls, std::vector<Diag> Diags,
- IncludeStructure Includes);
+ IncludeStructure Includes, CanonicalIncludes CanonIncludes);
// In-memory preambles must outlive the AST, it is important that this member
// goes before Clang and Action.
@@ -130,14 +132,12 @@ private:
// top-level decls from the preamble.
std::vector<Decl *> LocalTopLevelDecls;
IncludeStructure Includes;
+ CanonicalIncludes CanonIncludes;
};
using PreambleParsedCallback =
- std::function<void(ASTContext &, std::shared_ptr<clang::Preprocessor>)>;
-
-/// Builds compiler invocation that could be used to build AST or preamble.
-std::unique_ptr<CompilerInvocation>
-buildCompilerInvocation(const ParseInputs &Inputs);
+ std::function<void(ASTContext &, std::shared_ptr<clang::Preprocessor>,
+ const CanonicalIncludes &)>;
/// Rebuild the preamble for the new inputs unless the old one can be reused.
/// If \p OldPreamble can be reused, it is returned unchanged.
@@ -149,8 +149,7 @@ std::shared_ptr<const PreambleData>
buildPreamble(PathRef FileName, CompilerInvocation &CI,
std::shared_ptr<const PreambleData> OldPreamble,
const tooling::CompileCommand &OldCompileCommand,
- const ParseInputs &Inputs,
- std::shared_ptr<PCHContainerOperations> PCHs, bool StoreInMemory,
+ const ParseInputs &Inputs, bool StoreInMemory,
PreambleParsedCallback PreambleCallback);
/// Build an AST from provided user inputs. This function does not check if
@@ -159,8 +158,7 @@ buildPreamble(PathRef FileName, CompilerInvocation &CI,
llvm::Optional<ParsedAST>
buildAST(PathRef FileName, std::unique_ptr<CompilerInvocation> Invocation,
const ParseInputs &Inputs,
- std::shared_ptr<const PreambleData> Preamble,
- std::shared_ptr<PCHContainerOperations> PCHs);
+ std::shared_ptr<const PreambleData> Preamble);
/// Get the beginning SourceLocation at a specified \p Pos.
/// May be invalid if Pos is, or if there's no identifier.
diff --git a/clangd/CodeComplete.cpp b/clangd/CodeComplete.cpp
index 7642ea9d..4789a809 100644
--- a/clangd/CodeComplete.cpp
+++ b/clangd/CodeComplete.cpp
@@ -1,9 +1,8 @@
//===--- CodeComplete.cpp ----------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -35,20 +34,29 @@
#include "Trace.h"
#include "URI.h"
#include "index/Index.h"
+#include "index/Symbol.h"
+#include "index/SymbolOrigin.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
+#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/ExternalPreprocessorSource.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
@@ -178,27 +186,11 @@ std::string getOptionalParameters(const CodeCompletionString &CCS,
return Result;
}
-/// Creates a `HeaderFile` from \p Header which can be either a URI or a literal
-/// include.
-static llvm::Expected<HeaderFile> toHeaderFile(llvm::StringRef Header,
- llvm::StringRef HintPath) {
- if (isLiteralInclude(Header))
- return HeaderFile{Header.str(), /*Verbatim=*/true};
- auto U = URI::parse(Header);
- if (!U)
- return U.takeError();
-
- auto IncludePath = URI::includeSpelling(*U);
- if (!IncludePath)
- return IncludePath.takeError();
- if (!IncludePath->empty())
- return HeaderFile{std::move(*IncludePath), /*Verbatim=*/true};
-
- auto Resolved = URI::resolve(*U, HintPath);
- if (!Resolved)
- return Resolved.takeError();
- return HeaderFile{std::move(*Resolved), /*Verbatim=*/false};
-}
+// Identifier code completion result.
+struct RawIdentifier {
+ llvm::StringRef Name;
+ unsigned References; // # of usages in file.
+};
/// A code completion result, in clang-native form.
/// It may be promoted to a CompletionItem if it's among the top-ranked results.
@@ -207,11 +199,14 @@ struct CompletionCandidate {
// We may have a result from Sema, from the index, or both.
const CodeCompletionResult *SemaResult = nullptr;
const Symbol *IndexResult = nullptr;
+ const RawIdentifier *IdentifierResult = nullptr;
llvm::SmallVector<llvm::StringRef, 1> RankedIncludeHeaders;
// Returns a token identifying the overload set this is part of.
// 0 indicates it's not part of any overload set.
- size_t overloadSet() const {
+ size_t overloadSet(const CodeCompleteOptions &Opts) const {
+ if (!Opts.BundleOverloads)
+ return 0;
llvm::SmallString<256> Scratch;
if (IndexResult) {
switch (IndexResult->SymInfo.Kind) {
@@ -228,27 +223,32 @@ struct CompletionCandidate {
// This could break #include insertion.
return llvm::hash_combine(
(IndexResult->Scope + IndexResult->Name).toStringRef(Scratch),
- headerToInsertIfAllowed().getValueOr(""));
+ headerToInsertIfAllowed(Opts).getValueOr(""));
default:
return 0;
}
}
- assert(SemaResult);
- // We need to make sure we're consistent with the IndexResult case!
- const NamedDecl *D = SemaResult->Declaration;
- if (!D || !D->isFunctionOrFunctionTemplate())
- return 0;
- {
- llvm::raw_svector_ostream OS(Scratch);
- D->printQualifiedName(OS);
+ if (SemaResult) {
+ // We need to make sure we're consistent with the IndexResult case!
+ const NamedDecl *D = SemaResult->Declaration;
+ if (!D || !D->isFunctionOrFunctionTemplate())
+ return 0;
+ {
+ llvm::raw_svector_ostream OS(Scratch);
+ D->printQualifiedName(OS);
+ }
+ return llvm::hash_combine(Scratch,
+ headerToInsertIfAllowed(Opts).getValueOr(""));
}
- return llvm::hash_combine(Scratch,
- headerToInsertIfAllowed().getValueOr(""));
+ assert(IdentifierResult);
+ return 0;
}
// The best header to include if include insertion is allowed.
- llvm::Optional<llvm::StringRef> headerToInsertIfAllowed() const {
- if (RankedIncludeHeaders.empty())
+ llvm::Optional<llvm::StringRef>
+ headerToInsertIfAllowed(const CodeCompleteOptions &Opts) const {
+ if (Opts.InsertIncludes == CodeCompleteOptions::NeverInsert ||
+ RankedIncludeHeaders.empty())
return None;
if (SemaResult && SemaResult->Declaration) {
// Avoid inserting new #include if the declaration is found in the current
@@ -282,7 +282,7 @@ struct ScoredBundleGreater {
// computed from the first candidate, in the constructor.
// Others vary per candidate, so add() must be called for remaining candidates.
struct CodeCompletionBuilder {
- CodeCompletionBuilder(ASTContext &ASTCtx, const CompletionCandidate &C,
+ CodeCompletionBuilder(ASTContext *ASTCtx, const CompletionCandidate &C,
CodeCompletionString *SemaCCS,
llvm::ArrayRef<std::string> QueryScopes,
const IncludeInserter &Includes,
@@ -293,6 +293,7 @@ struct CodeCompletionBuilder {
EnableFunctionArgSnippets(Opts.EnableFunctionArgSnippets) {
add(C, SemaCCS);
if (C.SemaResult) {
+ assert(ASTCtx);
Completion.Origin |= SymbolOrigin::AST;
Completion.Name = llvm::StringRef(SemaCCS->getTypedText());
if (Completion.Scope.empty()) {
@@ -311,8 +312,8 @@ struct CodeCompletionBuilder {
Completion.Name.back() == '/')
Completion.Kind = CompletionItemKind::Folder;
for (const auto &FixIt : C.SemaResult->FixIts) {
- Completion.FixIts.push_back(
- toTextEdit(FixIt, ASTCtx.getSourceManager(), ASTCtx.getLangOpts()));
+ Completion.FixIts.push_back(toTextEdit(
+ FixIt, ASTCtx->getSourceManager(), ASTCtx->getLangOpts()));
}
llvm::sort(Completion.FixIts, [](const TextEdit &X, const TextEdit &Y) {
return std::tie(X.range.start.line, X.range.start.character) <
@@ -343,22 +344,30 @@ struct CodeCompletionBuilder {
}
Completion.Deprecated |= (C.IndexResult->Flags & Symbol::Deprecated);
}
+ if (C.IdentifierResult) {
+ Completion.Origin |= SymbolOrigin::Identifier;
+ Completion.Kind = CompletionItemKind::Text;
+ Completion.Name = C.IdentifierResult->Name;
+ }
// Turn absolute path into a literal string that can be #included.
auto Inserted = [&](llvm::StringRef Header)
-> llvm::Expected<std::pair<std::string, bool>> {
- auto ResolvedDeclaring =
- toHeaderFile(C.IndexResult->CanonicalDeclaration.FileURI, FileName);
+ auto DeclaringURI =
+ URI::parse(C.IndexResult->CanonicalDeclaration.FileURI);
+ if (!DeclaringURI)
+ return DeclaringURI.takeError();
+ auto ResolvedDeclaring = URI::resolve(*DeclaringURI, FileName);
if (!ResolvedDeclaring)
return ResolvedDeclaring.takeError();
auto ResolvedInserted = toHeaderFile(Header, FileName);
if (!ResolvedInserted)
return ResolvedInserted.takeError();
return std::make_pair(
- Includes.calculateIncludePath(*ResolvedDeclaring, *ResolvedInserted),
+ Includes.calculateIncludePath(*ResolvedInserted),
Includes.shouldInsertInclude(*ResolvedDeclaring, *ResolvedInserted));
};
- bool ShouldInsert = C.headerToInsertIfAllowed().hasValue();
+ bool ShouldInsert = C.headerToInsertIfAllowed(Opts).hasValue();
// Calculate include paths and edits for all possible headers.
for (const auto &Inc : C.RankedIncludeHeaders) {
if (auto ToInclude = Inserted(Inc)) {
@@ -397,7 +406,7 @@ struct CodeCompletionBuilder {
if (C.IndexResult)
Completion.Documentation = C.IndexResult->Documentation;
else if (C.SemaResult)
- Completion.Documentation = getDocComment(ASTCtx, *C.SemaResult,
+ Completion.Documentation = getDocComment(*ASTCtx, *C.SemaResult,
/*CommentsFromHeader=*/false);
}
}
@@ -492,7 +501,8 @@ private:
return "(…)";
}
- ASTContext &ASTCtx;
+ // ASTCtx can be nullptr if not run with sema.
+ ASTContext *ASTCtx;
CodeCompletion Completion;
llvm::SmallVector<BundledEntry, 1> Bundled;
bool ExtractDocumentation;
@@ -549,7 +559,7 @@ struct SpecifiedScope {
std::set<std::string> Results;
for (llvm::StringRef AS : AccessibleScopes)
Results.insert(
- ((UnresolvedQualifier ? *UnresolvedQualifier : "") + AS).str());
+ (AS + (UnresolvedQualifier ? *UnresolvedQualifier : "")).str());
return {Results.begin(), Results.end()};
}
};
@@ -559,55 +569,59 @@ struct SpecifiedScope {
// (e.g. enclosing namespace).
std::pair<std::vector<std::string>, bool>
getQueryScopes(CodeCompletionContext &CCContext, const Sema &CCSema,
+ const CompletionPrefix &HeuristicPrefix,
const CodeCompleteOptions &Opts) {
- auto GetAllAccessibleScopes = [](CodeCompletionContext &CCContext) {
- SpecifiedScope Info;
- for (auto *Context : CCContext.getVisitedContexts()) {
- if (isa<TranslationUnitDecl>(Context))
- Info.AccessibleScopes.push_back(""); // global namespace
- else if (isa<NamespaceDecl>(Context))
- Info.AccessibleScopes.push_back(printNamespaceScope(*Context));
- }
- return Info;
- };
-
- auto SS = CCContext.getCXXScopeSpecifier();
+ SpecifiedScope Scopes;
+ for (auto *Context : CCContext.getVisitedContexts()) {
+ if (isa<TranslationUnitDecl>(Context))
+ Scopes.AccessibleScopes.push_back(""); // global namespace
+ else if (isa<NamespaceDecl>(Context))
+ Scopes.AccessibleScopes.push_back(printNamespaceScope(*Context));
+ }
- // Unqualified completion (e.g. "vec^").
- if (!SS) {
- std::vector<std::string> Scopes;
+ const CXXScopeSpec *SemaSpecifier =
+ CCContext.getCXXScopeSpecifier().getValueOr(nullptr);
+ // Case 1: unqualified completion.
+ if (!SemaSpecifier) {
+ // Case 2 (exception): sema saw no qualifier, but there appears to be one!
+ // This can happen e.g. in incomplete macro expansions. Use heuristics.
+ if (!HeuristicPrefix.Qualifier.empty()) {
+ vlog("Sema said no scope specifier, but we saw {0} in the source code",
+ HeuristicPrefix.Qualifier);
+ StringRef SpelledSpecifier = HeuristicPrefix.Qualifier;
+ if (SpelledSpecifier.consume_front("::"))
+ Scopes.AccessibleScopes = {""};
+ Scopes.UnresolvedQualifier = SpelledSpecifier;
+ return {Scopes.scopesForIndexQuery(), false};
+ }
+ // The enclosing namespace must be first, it gets a quality boost.
+ std::vector<std::string> EnclosingAtFront;
std::string EnclosingScope = printNamespaceScope(*CCSema.CurContext);
- Scopes.push_back(EnclosingScope);
- for (auto &S : GetAllAccessibleScopes(CCContext).scopesForIndexQuery()) {
+ EnclosingAtFront.push_back(EnclosingScope);
+ for (auto &S : Scopes.scopesForIndexQuery()) {
if (EnclosingScope != S)
- Scopes.push_back(std::move(S));
+ EnclosingAtFront.push_back(std::move(S));
}
- // Allow AllScopes completion only for there is no explicit scope qualifier.
- return {Scopes, Opts.AllScopes};
+ // Allow AllScopes completion as there is no explicit scope qualifier.
+ return {EnclosingAtFront, Opts.AllScopes};
}
-
- // Qualified completion ("std::vec^"), we have two cases depending on whether
- // the qualifier can be resolved by Sema.
- if ((*SS)->isValid()) { // Resolved qualifier.
- return {GetAllAccessibleScopes(CCContext).scopesForIndexQuery(), false};
- }
-
- // Unresolved qualifier.
- // FIXME: When Sema can resolve part of a scope chain (e.g.
- // "known::unknown::id"), we should expand the known part ("known::") rather
- // than treating the whole thing as unknown.
- SpecifiedScope Info;
- Info.AccessibleScopes.push_back(""); // global namespace
-
- Info.UnresolvedQualifier =
- Lexer::getSourceText(CharSourceRange::getCharRange((*SS)->getRange()),
- CCSema.SourceMgr, clang::LangOptions())
- .ltrim("::");
+ // Case 3: sema saw and resolved a scope qualifier.
+ if (SemaSpecifier && SemaSpecifier->isValid())
+ return {Scopes.scopesForIndexQuery(), false};
+
+ // Case 4: There was a qualifier, and Sema didn't resolve it.
+ Scopes.AccessibleScopes.push_back(""); // Make sure global scope is included.
+ llvm::StringRef SpelledSpecifier = Lexer::getSourceText(
+ CharSourceRange::getCharRange(SemaSpecifier->getRange()),
+ CCSema.SourceMgr, clang::LangOptions());
+ if (SpelledSpecifier.consume_front("::"))
+ Scopes.AccessibleScopes = {""};
+ Scopes.UnresolvedQualifier = SpelledSpecifier;
// Sema excludes the trailing "::".
- if (!Info.UnresolvedQualifier->empty())
- *Info.UnresolvedQualifier += "::";
+ if (!Scopes.UnresolvedQualifier->empty())
+ *Scopes.UnresolvedQualifier += "::";
- return {Info.scopesForIndexQuery(), false};
+ return {Scopes.scopesForIndexQuery(), false};
}
// Should we perform index-based completion in a context of the specified kind?
@@ -691,8 +705,7 @@ static bool isBlacklistedMember(const NamedDecl &D) {
struct CompletionRecorder : public CodeCompleteConsumer {
CompletionRecorder(const CodeCompleteOptions &Opts,
llvm::unique_function<void()> ResultsCallback)
- : CodeCompleteConsumer(Opts.getClangCompleteOpts(),
- /*OutputIsBinary=*/false),
+ : CodeCompleteConsumer(Opts.getClangCompleteOpts()),
CCContext(CodeCompletionContext::CCC_Other), Opts(Opts),
CCAllocator(std::make_shared<GlobalCodeCompletionAllocator>()),
CCTUInfo(CCAllocator), ResultsCallback(std::move(ResultsCallback)) {
@@ -813,8 +826,7 @@ class SignatureHelpCollector final : public CodeCompleteConsumer {
public:
SignatureHelpCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,
const SymbolIndex *Index, SignatureHelp &SigHelp)
- : CodeCompleteConsumer(CodeCompleteOpts,
- /*OutputIsBinary=*/false),
+ : CodeCompleteConsumer(CodeCompleteOpts),
SigHelp(SigHelp),
Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
CCTUInfo(Allocator), Index(Index) {}
@@ -1005,11 +1017,28 @@ struct SemaCompleteInput {
const tooling::CompileCommand &Command;
const PreambleData *Preamble;
llvm::StringRef Contents;
- Position Pos;
+ size_t Offset;
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;
- std::shared_ptr<PCHContainerOperations> PCHs;
};
+void loadMainFilePreambleMacros(const Preprocessor &PP,
+ const PreambleData &Preamble) {
+ // The ExternalPreprocessorSource has our macros, if we know where to look.
+ // We can read all the macros using PreambleMacros->ReadDefinedMacros(),
+ // but this includes transitively included files, so may deserialize a lot.
+ ExternalPreprocessorSource *PreambleMacros = PP.getExternalSource();
+ // As we have the names of the macros, we can look up their IdentifierInfo
+ // and then use this to load just the macros we want.
+ IdentifierInfoLookup *PreambleIdentifiers =
+ PP.getIdentifierTable().getExternalIdentifierLookup();
+ if (!PreambleIdentifiers || !PreambleMacros)
+ return;
+ for (const auto& MacroName : Preamble.MainFileMacros)
+ if (auto *II = PreambleIdentifiers->get(MacroName))
+ if (II->isOutOfDate())
+ PreambleMacros->updateOutOfDateIdentifier(*II);
+}
+
// Invokes Sema code completion on a file.
// If \p Includes is set, it will be updated based on the compiler invocation.
bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
@@ -1017,46 +1046,29 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
const SemaCompleteInput &Input,
IncludeStructure *Includes = nullptr) {
trace::Span Tracer("Sema completion");
- std::vector<const char *> ArgStrs;
- for (const auto &S : Input.Command.CommandLine)
- ArgStrs.push_back(S.c_str());
-
- if (Input.VFS->setCurrentWorkingDirectory(Input.Command.Directory)) {
- log("Couldn't set working directory");
- // We run parsing anyway, our lit-tests rely on results for non-existing
- // working dirs.
- }
-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = Input.VFS;
if (Input.Preamble && Input.Preamble->StatCache)
VFS = Input.Preamble->StatCache->getConsumingFS(std::move(VFS));
- IgnoreDiagnostics DummyDiagsConsumer;
- auto CI = createInvocationFromCommandLine(
- ArgStrs,
- CompilerInstance::createDiagnostics(new DiagnosticOptions,
- &DummyDiagsConsumer, false),
- VFS);
+ ParseInputs ParseInput;
+ ParseInput.CompileCommand = Input.Command;
+ ParseInput.FS = VFS;
+ ParseInput.Contents = Input.Contents;
+ ParseInput.Opts = ParseOptions();
+ auto CI = buildCompilerInvocation(ParseInput);
if (!CI) {
elog("Couldn't create CompilerInvocation");
return false;
}
auto &FrontendOpts = CI->getFrontendOpts();
- FrontendOpts.DisableFree = false;
FrontendOpts.SkipFunctionBodies = true;
- CI->getLangOpts()->CommentOpts.ParseAllComments = true;
// Disable typo correction in Sema.
CI->getLangOpts()->SpellChecking = false;
// Setup code completion.
FrontendOpts.CodeCompleteOpts = Options;
FrontendOpts.CodeCompletionAt.FileName = Input.FileName;
- auto Offset = positionToOffset(Input.Contents, Input.Pos);
- if (!Offset) {
- elog("Code completion position was invalid {0}", Offset.takeError());
- return false;
- }
std::tie(FrontendOpts.CodeCompletionAt.Line,
FrontendOpts.CodeCompletionAt.Column) =
- offsetToClangLineColumn(Input.Contents, *Offset);
+ offsetToClangLineColumn(Input.Contents, Input.Offset);
std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer =
llvm::MemoryBuffer::getMemBufferCopy(Input.Contents, Input.FileName);
@@ -1068,17 +1080,17 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
// However, if we're completing *inside* the preamble section of the draft,
// overriding the preamble will break sema completion. Fortunately we can just
// skip all includes in this case; these completions are really simple.
- bool CompletingInPreamble =
- ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0).Size >
- *Offset;
+ PreambleBounds PreambleRegion =
+ ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0);
+ bool CompletingInPreamble = PreambleRegion.Size > Input.Offset;
// NOTE: we must call BeginSourceFile after prepareCompilerInstance. Otherwise
// the remapped buffers do not get freed.
+ IgnoreDiagnostics DummyDiagsConsumer;
auto Clang = prepareCompilerInstance(
std::move(CI),
(Input.Preamble && !CompletingInPreamble) ? &Input.Preamble->Preamble
: nullptr,
- std::move(ContentsBuffer), std::move(Input.PCHs), std::move(VFS),
- DummyDiagsConsumer);
+ std::move(ContentsBuffer), std::move(VFS), DummyDiagsConsumer);
Clang->getPreprocessorOpts().SingleFileParseMode = CompletingInPreamble;
Clang->setCodeCompletionConsumer(Consumer.release());
@@ -1088,6 +1100,14 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
Input.FileName);
return false;
}
+ // Macros can be defined within the preamble region of the main file.
+ // They don't fall nicely into our index/Sema dichotomy:
+ // - they're not indexed for completion (they're not available across files)
+ // - but Sema code complete won't see them: as part of the preamble, they're
+ // deserialized only when mentioned.
+ // Force them to be deserialized so SemaCodeComplete sees them.
+ if (Input.Preamble)
+ loadMainFilePreambleMacros(Clang->getPreprocessor(), *Input.Preamble);
if (Includes)
Clang->getPreprocessor().addPPCallbacks(
collectIncludeStructureCallback(Clang->getSourceManager(), Includes));
@@ -1141,39 +1161,12 @@ std::future<SymbolSlab> startAsyncFuzzyFind(const SymbolIndex &Index,
// Creates a `FuzzyFindRequest` based on the cached index request from the
// last completion, if any, and the speculated completion filter text in the
// source code.
-llvm::Optional<FuzzyFindRequest>
-speculativeFuzzyFindRequestForCompletion(FuzzyFindRequest CachedReq,
- PathRef File, llvm::StringRef Content,
- Position Pos) {
- auto Filter = speculateCompletionFilter(Content, Pos);
- if (!Filter) {
- elog("Failed to speculate filter text for code completion at Pos "
- "{0}:{1}: {2}",
- Pos.line, Pos.character, Filter.takeError());
- return None;
- }
- CachedReq.Query = *Filter;
+FuzzyFindRequest speculativeFuzzyFindRequestForCompletion(
+ FuzzyFindRequest CachedReq, const CompletionPrefix &HeuristicPrefix) {
+ CachedReq.Query = HeuristicPrefix.Name;
return CachedReq;
}
-// Returns the most popular include header for \p Sym. If two headers are
-// equally popular, prefer the shorter one. Returns empty string if \p Sym has
-// no include header.
-llvm::SmallVector<llvm::StringRef, 1> getRankedIncludes(const Symbol &Sym) {
- auto Includes = Sym.IncludeHeaders;
- // Sort in descending order by reference count and header length.
- llvm::sort(Includes, [](const Symbol::IncludeHeaderWithReferences &LHS,
- const Symbol::IncludeHeaderWithReferences &RHS) {
- if (LHS.References == RHS.References)
- return LHS.IncludeHeader.size() < RHS.IncludeHeader.size();
- return LHS.References > RHS.References;
- });
- llvm::SmallVector<llvm::StringRef, 1> Headers;
- for (const auto &Include : Includes)
- Headers.push_back(Include.IncludeHeader);
- return Headers;
-}
-
// Runs Sema-based (AST) and Index-based completion, returns merged results.
//
// There are a few tricky considerations:
@@ -1211,15 +1204,20 @@ class CodeCompleteFlow {
// Sema takes ownership of Recorder. Recorder is valid until Sema cleanup.
CompletionRecorder *Recorder = nullptr;
- int NSema = 0, NIndex = 0, NBoth = 0; // Counters for logging.
- bool Incomplete = false; // Would more be available with a higher limit?
+ CodeCompletionContext::Kind CCContextKind = CodeCompletionContext::CCC_Other;
+ // Counters for logging.
+ int NSema = 0, NIndex = 0, NSemaAndIndex = 0, NIdent = 0;
+ bool Incomplete = false; // Would more be available with a higher limit?
+ CompletionPrefix HeuristicPrefix;
llvm::Optional<FuzzyMatcher> Filter; // Initialized once Sema runs.
+ Range ReplacedRange;
std::vector<std::string> QueryScopes; // Initialized once Sema runs.
// Initialized once QueryScopes is initialized, if there are scopes.
llvm::Optional<ScopeDistance> ScopeProximity;
llvm::Optional<OpaqueType> PreferredType; // Initialized once Sema runs.
// Whether to query symbols from any scope. Initialized once Sema runs.
bool AllScopes = false;
+ llvm::StringSet<> ContextWords;
// Include-insertion and proximity scoring rely on the include structure.
// This is available after Sema has run.
llvm::Optional<IncludeInserter> Inserter; // Available during runWithSema.
@@ -1240,12 +1238,14 @@ public:
CodeCompleteResult run(const SemaCompleteInput &SemaCCInput) && {
trace::Span Tracer("CodeCompleteFlow");
+ HeuristicPrefix =
+ guessCompletionPrefix(SemaCCInput.Contents, SemaCCInput.Offset);
+ populateContextWords(SemaCCInput.Contents);
if (Opts.Index && SpecFuzzyFind && SpecFuzzyFind->CachedReq.hasValue()) {
assert(!SpecFuzzyFind->Result.valid());
- if ((SpecReq = speculativeFuzzyFindRequestForCompletion(
- *SpecFuzzyFind->CachedReq, SemaCCInput.FileName,
- SemaCCInput.Contents, SemaCCInput.Pos)))
- SpecFuzzyFind->Result = startAsyncFuzzyFind(*Opts.Index, *SpecReq);
+ SpecReq = speculativeFuzzyFindRequestForCompletion(
+ *SpecFuzzyFind->CachedReq, HeuristicPrefix);
+ SpecFuzzyFind->Result = startAsyncFuzzyFind(*Opts.Index, *SpecReq);
}
// We run Sema code completion first. It builds an AST and calculates:
@@ -1254,21 +1254,15 @@ public:
CodeCompleteResult Output;
auto RecorderOwner = llvm::make_unique<CompletionRecorder>(Opts, [&]() {
assert(Recorder && "Recorder is not set");
- auto Style =
- format::getStyle(format::DefaultFormatStyle, SemaCCInput.FileName,
- format::DefaultFallbackStyle, SemaCCInput.Contents,
- SemaCCInput.VFS.get());
- if (!Style) {
- log("getStyle() failed for file {0}: {1}. Fallback is LLVM style.",
- SemaCCInput.FileName, Style.takeError());
- Style = format::getLLVMStyle();
- }
+ CCContextKind = Recorder->CCContext.getKind();
+ auto Style = getFormatStyleForFile(
+ SemaCCInput.FileName, SemaCCInput.Contents, SemaCCInput.VFS.get());
// If preprocessor was run, inclusions from preprocessor callback should
// already be added to Includes.
Inserter.emplace(
- SemaCCInput.FileName, SemaCCInput.Contents, *Style,
+ SemaCCInput.FileName, SemaCCInput.Contents, Style,
SemaCCInput.Command.Directory,
- Recorder->CCSema->getPreprocessor().getHeaderSearchInfo());
+ &Recorder->CCSema->getPreprocessor().getHeaderSearchInfo());
for (const auto &Inc : Includes.MainFileIncludes)
Inserter->addExisting(Inc);
@@ -1294,10 +1288,10 @@ public:
Output = runWithSema();
Inserter.reset(); // Make sure this doesn't out-live Clang.
SPAN_ATTACH(Tracer, "sema_completion_kind",
- getCompletionKindString(Recorder->CCContext.getKind()));
+ getCompletionKindString(CCContextKind));
log("Code complete: sema context {0}, query scopes [{1}] (AnyScope={2}), "
"expected type {3}",
- getCompletionKindString(Recorder->CCContext.getKind()),
+ getCompletionKindString(CCContextKind),
llvm::join(QueryScopes.begin(), QueryScopes.end(), ","), AllScopes,
PreferredType ? Recorder->CCContext.getPreferredType().getAsString()
: "<none>");
@@ -1307,47 +1301,132 @@ public:
semaCodeComplete(std::move(RecorderOwner), Opts.getClangCompleteOpts(),
SemaCCInput, &Includes);
+ logResults(Output, Tracer);
+ return Output;
+ }
+ void logResults(const CodeCompleteResult &Output, const trace::Span &Tracer) {
SPAN_ATTACH(Tracer, "sema_results", NSema);
SPAN_ATTACH(Tracer, "index_results", NIndex);
- SPAN_ATTACH(Tracer, "merged_results", NBoth);
+ SPAN_ATTACH(Tracer, "merged_results", NSemaAndIndex);
+ SPAN_ATTACH(Tracer, "identifier_results", NIdent);
SPAN_ATTACH(Tracer, "returned_results", int64_t(Output.Completions.size()));
SPAN_ATTACH(Tracer, "incomplete", Output.HasMore);
log("Code complete: {0} results from Sema, {1} from Index, "
- "{2} matched, {3} returned{4}.",
- NSema, NIndex, NBoth, Output.Completions.size(),
+ "{2} matched, {3} from identifiers, {4} returned{5}.",
+ NSema, NIndex, NSemaAndIndex, NIdent, Output.Completions.size(),
Output.HasMore ? " (incomplete)" : "");
assert(!Opts.Limit || Output.Completions.size() <= Opts.Limit);
// We don't assert that isIncomplete means we hit a limit.
// Indexes may choose to impose their own limits even if we don't have one.
+ }
+
+ CodeCompleteResult
+ runWithoutSema(llvm::StringRef Content, size_t Offset,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) && {
+ trace::Span Tracer("CodeCompleteWithoutSema");
+ // Fill in fields normally set by runWithSema()
+ HeuristicPrefix = guessCompletionPrefix(Content, Offset);
+ populateContextWords(Content);
+ CCContextKind = CodeCompletionContext::CCC_Recovery;
+ Filter = FuzzyMatcher(HeuristicPrefix.Name);
+ auto Pos = offsetToPosition(Content, Offset);
+ ReplacedRange.start = ReplacedRange.end = Pos;
+ ReplacedRange.start.character -= HeuristicPrefix.Name.size();
+
+ llvm::StringMap<SourceParams> ProxSources;
+ ProxSources[FileName].Cost = 0;
+ FileProximity.emplace(ProxSources);
+
+ auto Style = getFormatStyleForFile(FileName, Content, VFS.get());
+ // This will only insert verbatim headers.
+ Inserter.emplace(FileName, Content, Style,
+ /*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr);
+
+ auto Identifiers = collectIdentifiers(Content, Style);
+ std::vector<RawIdentifier> IdentifierResults;
+ for (const auto &IDAndCount : Identifiers) {
+ RawIdentifier ID;
+ ID.Name = IDAndCount.first();
+ ID.References = IDAndCount.second;
+ // Avoid treating typed filter as an identifier.
+ if (ID.Name == HeuristicPrefix.Name)
+ --ID.References;
+ if (ID.References > 0)
+ IdentifierResults.push_back(std::move(ID));
+ }
+
+ // Simplified version of getQueryScopes():
+ // - accessible scopes are determined heuristically.
+ // - all-scopes query if no qualifier was typed (and it's allowed).
+ SpecifiedScope Scopes;
+ Scopes.AccessibleScopes =
+ visibleNamespaces(Content.take_front(Offset), Style);
+ for (std::string &S : Scopes.AccessibleScopes)
+ if (!S.empty())
+ S.append("::"); // visibleNamespaces doesn't include trailing ::.
+ if (HeuristicPrefix.Qualifier.empty())
+ AllScopes = Opts.AllScopes;
+ else if (HeuristicPrefix.Qualifier.startswith("::")) {
+ Scopes.AccessibleScopes = {""};
+ Scopes.UnresolvedQualifier = HeuristicPrefix.Qualifier.drop_front(2);
+ } else
+ Scopes.UnresolvedQualifier = HeuristicPrefix.Qualifier;
+ // First scope is the (modified) enclosing scope.
+ QueryScopes = Scopes.scopesForIndexQuery();
+ ScopeProximity.emplace(QueryScopes);
+
+ SymbolSlab IndexResults = Opts.Index ? queryIndex() : SymbolSlab();
+
+ CodeCompleteResult Output = toCodeCompleteResult(mergeResults(
+ /*SemaResults=*/{}, IndexResults, IdentifierResults));
+ Output.RanParser = false;
+ logResults(Output, Tracer);
return Output;
}
private:
+ void populateContextWords(llvm::StringRef Content) {
+ // Take last 3 lines before the completion point.
+ unsigned RangeEnd = HeuristicPrefix.Qualifier.begin() - Content.data(),
+ RangeBegin = RangeEnd;
+ for (size_t I = 0; I < 3 && RangeBegin > 0; ++I) {
+ auto PrevNL = Content.rfind('\n', RangeBegin - 1);
+ if (PrevNL == StringRef::npos) {
+ RangeBegin = 0;
+ break;
+ }
+ RangeBegin = PrevNL + 1;
+ }
+
+ ContextWords = collectWords(Content.slice(RangeBegin, RangeEnd));
+ dlog("Completion context words: {0}",
+ llvm::join(ContextWords.keys(), ", "));
+ }
+
// This is called by run() once Sema code completion is done, but before the
// Sema data structures are torn down. It does all the real work.
CodeCompleteResult runWithSema() {
const auto &CodeCompletionRange = CharSourceRange::getCharRange(
Recorder->CCSema->getPreprocessor().getCodeCompletionTokenRange());
- Range TextEditRange;
// When we are getting completions with an empty identifier, for example
// std::vector<int> asdf;
// asdf.^;
// Then the range will be invalid and we will be doing insertion, use
// current cursor position in such cases as range.
if (CodeCompletionRange.isValid()) {
- TextEditRange = halfOpenToRange(Recorder->CCSema->getSourceManager(),
+ ReplacedRange = halfOpenToRange(Recorder->CCSema->getSourceManager(),
CodeCompletionRange);
} else {
const auto &Pos = sourceLocToPosition(
Recorder->CCSema->getSourceManager(),
Recorder->CCSema->getPreprocessor().getCodeCompletionLoc());
- TextEditRange.start = TextEditRange.end = Pos;
+ ReplacedRange.start = ReplacedRange.end = Pos;
}
Filter = FuzzyMatcher(
Recorder->CCSema->getPreprocessor().getCodeCompletionFilter());
- std::tie(QueryScopes, AllScopes) =
- getQueryScopes(Recorder->CCContext, *Recorder->CCSema, Opts);
+ std::tie(QueryScopes, AllScopes) = getQueryScopes(
+ Recorder->CCContext, *Recorder->CCSema, HeuristicPrefix, Opts);
if (!QueryScopes.empty())
ScopeProximity.emplace(QueryScopes);
PreferredType =
@@ -1363,18 +1442,23 @@ private:
: SymbolSlab();
trace::Span Tracer("Populate CodeCompleteResult");
// Merge Sema and Index results, score them, and pick the winners.
- auto Top = mergeResults(Recorder->Results, IndexResults);
+ auto Top =
+ mergeResults(Recorder->Results, IndexResults, /*Identifiers*/ {});
+ return toCodeCompleteResult(Top);
+ }
+
+ CodeCompleteResult
+ toCodeCompleteResult(const std::vector<ScoredBundle> &Scored) {
CodeCompleteResult Output;
// Convert the results to final form, assembling the expensive strings.
- for (auto &C : Top) {
+ for (auto &C : Scored) {
Output.Completions.push_back(toCodeCompletion(C.first));
Output.Completions.back().Score = C.second;
- Output.Completions.back().CompletionTokenRange = TextEditRange;
+ Output.Completions.back().CompletionTokenRange = ReplacedRange;
}
Output.HasMore = Incomplete;
- Output.Context = Recorder->CCContext.getKind();
-
+ Output.Context = CCContextKind;
return Output;
}
@@ -1392,6 +1476,8 @@ private:
Req.AnyScope = AllScopes;
// FIXME: we should send multiple weighted paths here.
Req.ProximityPaths.push_back(FileName);
+ if (PreferredType)
+ Req.PreferredTypes.push_back(PreferredType->raw());
vlog("Code complete: fuzzyFind({0:2})", toJSON(Req));
if (SpecFuzzyFind)
@@ -1416,23 +1502,34 @@ private:
}
// Merges Sema and Index results where possible, to form CompletionCandidates.
+ // \p Identifiers is raw idenfiers that can also be completion condidates.
+ // Identifiers are not merged with results from index or sema.
// Groups overloads if desired, to form CompletionCandidate::Bundles. The
// bundles are scored and top results are returned, best to worst.
std::vector<ScoredBundle>
mergeResults(const std::vector<CodeCompletionResult> &SemaResults,
- const SymbolSlab &IndexResults) {
+ const SymbolSlab &IndexResults,
+ const std::vector<RawIdentifier> &IdentifierResults) {
trace::Span Tracer("Merge and score results");
std::vector<CompletionCandidate::Bundle> Bundles;
llvm::DenseMap<size_t, size_t> BundleLookup;
auto AddToBundles = [&](const CodeCompletionResult *SemaResult,
- const Symbol *IndexResult) {
+ const Symbol *IndexResult,
+ const RawIdentifier *IdentifierResult) {
CompletionCandidate C;
C.SemaResult = SemaResult;
C.IndexResult = IndexResult;
- if (C.IndexResult)
+ C.IdentifierResult = IdentifierResult;
+ if (C.IndexResult) {
+ C.Name = IndexResult->Name;
C.RankedIncludeHeaders = getRankedIncludes(*C.IndexResult);
- C.Name = IndexResult ? IndexResult->Name : Recorder->getName(*SemaResult);
- if (auto OverloadSet = Opts.BundleOverloads ? C.overloadSet() : 0) {
+ } else if (C.SemaResult) {
+ C.Name = Recorder->getName(*SemaResult);
+ } else {
+ assert(IdentifierResult);
+ C.Name = IdentifierResult->Name;
+ }
+ if (auto OverloadSet = C.overloadSet(Opts)) {
auto Ret = BundleLookup.try_emplace(OverloadSet, Bundles.size());
if (Ret.second)
Bundles.emplace_back();
@@ -1456,14 +1553,17 @@ private:
return nullptr;
};
// Emit all Sema results, merging them with Index results if possible.
- for (auto &SemaResult : Recorder->Results)
- AddToBundles(&SemaResult, CorrespondingIndexResult(SemaResult));
+ for (auto &SemaResult : SemaResults)
+ AddToBundles(&SemaResult, CorrespondingIndexResult(SemaResult), nullptr);
// Now emit any Index-only results.
for (const auto &IndexResult : IndexResults) {
if (UsedIndexResults.count(&IndexResult))
continue;
- AddToBundles(/*SemaResult=*/nullptr, &IndexResult);
+ AddToBundles(/*SemaResult=*/nullptr, &IndexResult, nullptr);
}
+ // Emit identifier results.
+ for (const auto &Ident : IdentifierResults)
+ AddToBundles(/*SemaResult=*/nullptr, /*IndexResult=*/nullptr, &Ident);
// We only keep the best N results at any time, in "native" format.
TopN<ScoredBundle, ScoredBundleGreater> Top(
Opts.Limit == 0 ? std::numeric_limits<size_t>::max() : Opts.Limit);
@@ -1486,13 +1586,15 @@ private:
CompletionCandidate::Bundle Bundle) {
SymbolQualitySignals Quality;
SymbolRelevanceSignals Relevance;
- Relevance.Context = Recorder->CCContext.getKind();
+ Relevance.Context = CCContextKind;
+ Relevance.Name = Bundle.front().Name;
Relevance.Query = SymbolRelevanceSignals::CodeComplete;
Relevance.FileProximityMatch = FileProximity.getPointer();
if (ScopeProximity)
Relevance.ScopeProximityMatch = ScopeProximity.getPointer();
if (PreferredType)
Relevance.HadContextType = true;
+ Relevance.ContextWords = &ContextWords;
auto &First = Bundle.front();
if (auto FuzzyScore = fuzzyScore(First))
@@ -1527,6 +1629,11 @@ private:
}
Origin |= SymbolOrigin::AST;
}
+ if (Candidate.IdentifierResult) {
+ Quality.References = Candidate.IdentifierResult->References;
+ Relevance.Scope = SymbolRelevanceSignals::FileScope;
+ Origin |= SymbolOrigin::Identifier;
+ }
}
CodeCompletion::Scores Scores;
@@ -1544,7 +1651,8 @@ private:
NSema += bool(Origin & SymbolOrigin::AST);
NIndex += FromIndex;
- NBoth += bool(Origin & SymbolOrigin::AST) && FromIndex;
+ NSemaAndIndex += bool(Origin & SymbolOrigin::AST) && FromIndex;
+ NIdent += bool(Origin & SymbolOrigin::Identifier);
if (Candidates.push({std::move(Bundle), Scores}))
Incomplete = true;
}
@@ -1556,9 +1664,9 @@ private:
Item.SemaResult ? Recorder->codeCompletionString(*Item.SemaResult)
: nullptr;
if (!Builder)
- Builder.emplace(Recorder->CCSema->getASTContext(), Item, SemaCCS,
- QueryScopes, *Inserter, FileName,
- Recorder->CCContext.getKind(), Opts);
+ Builder.emplace(Recorder ? &Recorder->CCSema->getASTContext() : nullptr,
+ Item, SemaCCS, QueryScopes, *Inserter, FileName,
+ CCContextKind, Opts);
else
Builder->add(Item, SemaCCS);
}
@@ -1566,6 +1674,13 @@ private:
}
};
+template <class T> bool isExplicitTemplateSpecialization(const NamedDecl &ND) {
+ if (const auto *TD = dyn_cast<T>(&ND))
+ if (TD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ return true;
+ return false;
+}
+
} // namespace
clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const {
@@ -1588,41 +1703,44 @@ clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const {
return Result;
}
-llvm::Expected<llvm::StringRef>
-speculateCompletionFilter(llvm::StringRef Content, Position Pos) {
- auto Offset = positionToOffset(Content, Pos);
- if (!Offset)
- return llvm::make_error<llvm::StringError>(
- "Failed to convert position to offset in content.",
- llvm::inconvertibleErrorCode());
- if (*Offset == 0)
- return "";
+CompletionPrefix
+guessCompletionPrefix(llvm::StringRef Content, unsigned Offset) {
+ assert(Offset <= Content.size());
+ StringRef Rest = Content.take_front(Offset);
+ CompletionPrefix Result;
+
+ // Consume the unqualified name. We only handle ASCII characters.
+ // isIdentifierBody will let us match "0invalid", but we don't mind.
+ while (!Rest.empty() && isIdentifierBody(Rest.back()))
+ Rest = Rest.drop_back();
+ Result.Name = Content.slice(Rest.size(), Offset);
+
+ // Consume qualifiers.
+ while (Rest.consume_back("::") && !Rest.endswith(":")) // reject ::::
+ while (!Rest.empty() && isIdentifierBody(Rest.back()))
+ Rest = Rest.drop_back();
+ Result.Qualifier =
+ Content.slice(Rest.size(), Result.Name.begin() - Content.begin());
- // Start from the character before the cursor.
- int St = *Offset - 1;
- // FIXME(ioeric): consider UTF characters?
- auto IsValidIdentifierChar = [](char c) {
- return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
- (c >= '0' && c <= '9') || (c == '_'));
- };
- size_t Len = 0;
- for (; (St >= 0) && IsValidIdentifierChar(Content[St]); --St, ++Len) {
- }
- if (Len > 0)
- St++; // Shift to the first valid character.
- return Content.substr(St, Len);
+ return Result;
}
CodeCompleteResult
codeComplete(PathRef FileName, const tooling::CompileCommand &Command,
const PreambleData *Preamble, llvm::StringRef Contents,
Position Pos, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
- std::shared_ptr<PCHContainerOperations> PCHs,
CodeCompleteOptions Opts, SpeculativeFuzzyFind *SpecFuzzyFind) {
- return CodeCompleteFlow(FileName,
- Preamble ? Preamble->Includes : IncludeStructure(),
- SpecFuzzyFind, Opts)
- .run({FileName, Command, Preamble, Contents, Pos, VFS, PCHs});
+ auto Offset = positionToOffset(Contents, Pos);
+ if (!Offset) {
+ elog("Code completion position was invalid {0}", Offset.takeError());
+ return CodeCompleteResult();
+ }
+ auto Flow = CodeCompleteFlow(
+ FileName, Preamble ? Preamble->Includes : IncludeStructure(),
+ SpecFuzzyFind, Opts);
+ return Preamble ? std::move(Flow).run(
+ {FileName, Command, Preamble, Contents, *Offset, VFS})
+ : std::move(Flow).runWithoutSema(Contents, *Offset, VFS);
}
SignatureHelp signatureHelp(PathRef FileName,
@@ -1630,8 +1748,12 @@ SignatureHelp signatureHelp(PathRef FileName,
const PreambleData *Preamble,
llvm::StringRef Contents, Position Pos,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
- std::shared_ptr<PCHContainerOperations> PCHs,
const SymbolIndex *Index) {
+ auto Offset = positionToOffset(Contents, Pos);
+ if (!Offset) {
+ elog("Code completion position was invalid {0}", Offset.takeError());
+ return SignatureHelp();
+ }
SignatureHelp Result;
clang::CodeCompleteOptions Options;
Options.IncludeGlobals = false;
@@ -1642,8 +1764,7 @@ SignatureHelp signatureHelp(PathRef FileName,
semaCodeComplete(
llvm::make_unique<SignatureHelpCollector>(Options, Index, Result),
Options,
- {FileName, Command, Preamble, Contents, Pos, std::move(VFS),
- std::move(PCHs)});
+ {FileName, Command, Preamble, Contents, *Offset, std::move(VFS)});
return Result;
}
@@ -1659,6 +1780,13 @@ bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx) {
};
return false;
};
+ // We only complete symbol's name, which is the same as the name of the
+ // *primary* template in case of template specializations.
+ if (isExplicitTemplateSpecialization<FunctionDecl>(ND) ||
+ isExplicitTemplateSpecialization<CXXRecordDecl>(ND) ||
+ isExplicitTemplateSpecialization<VarDecl>(ND))
+ return false;
+
if (InTopLevelScope(ND))
return true;
@@ -1695,7 +1823,7 @@ CompletionItem CodeCompletion::render(const CodeCompleteOptions &Opts) const {
// is mainly to help LSP clients again, so that changes do not effect each
// other.
for (const auto &FixIt : FixIts) {
- if (IsRangeConsecutive(FixIt.range, LSP.textEdit->range)) {
+ if (isRangeConsecutive(FixIt.range, LSP.textEdit->range)) {
LSP.textEdit->newText = FixIt.newText + LSP.textEdit->newText;
LSP.textEdit->range.start = FixIt.range.start;
} else {
diff --git a/clangd/CodeComplete.h b/clangd/CodeComplete.h
index 4d324142..2dc7f22c 100644
--- a/clangd/CodeComplete.h
+++ b/clangd/CodeComplete.h
@@ -1,9 +1,8 @@
//===--- CodeComplete.h ------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -22,6 +21,8 @@
#include "Path.h"
#include "Protocol.h"
#include "index/Index.h"
+#include "index/Symbol.h"
+#include "index/SymbolOrigin.h"
#include "clang/Frontend/PrecompiledPreamble.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/CodeCompleteOptions.h"
@@ -34,7 +35,6 @@
namespace clang {
class NamedDecl;
-class PCHContainerOperations;
namespace clangd {
struct CodeCompleteOptions {
@@ -68,6 +68,11 @@ struct CodeCompleteOptions {
/// If more results are available, we set CompletionList.isIncomplete.
size_t Limit = 0;
+ enum IncludeInsertion {
+ IWYU,
+ NeverInsert,
+ } InsertIncludes = IncludeInsertion::IWYU;
+
/// A visual indicator to prepend to the completion label to indicate whether
/// completion result would trigger an #include insertion or not.
struct IncludeInsertionIndicator {
@@ -109,6 +114,12 @@ struct CodeCompleteOptions {
///
/// Such completions can insert scope qualifiers.
bool AllScopes = false;
+
+ /// Whether to allow falling back to code completion without compiling files
+ /// (using identifiers in the current file and symbol indexes), when file
+ /// cannot be built (e.g. missing compile command), or the build is not ready
+ /// (e.g. preamble is still being built).
+ bool AllowFallback = false;
};
// Semi-structured representation of a code-complete suggestion for our C++ API.
@@ -196,6 +207,9 @@ struct CodeCompleteResult {
std::vector<CodeCompletion> Completions;
bool HasMore = false;
CodeCompletionContext::Kind Context = CodeCompletionContext::CCC_Other;
+ // Usually the source will be parsed with a real C++ parser.
+ // But heuristics may be used instead if e.g. the preamble is not ready.
+ bool RanParser = true;
};
raw_ostream &operator<<(raw_ostream &, const CodeCompleteResult &);
@@ -214,7 +228,11 @@ struct SpeculativeFuzzyFind {
std::future<SymbolSlab> Result;
};
-/// Get code completions at a specified \p Pos in \p FileName.
+/// Gets code completions at a specified \p Pos in \p FileName.
+///
+/// If \p Preamble is nullptr, this runs code completion without compiling the
+/// code.
+///
/// If \p SpecFuzzyFind is set, a speculative and asynchronous fuzzy find index
/// request (based on cached request) will be run before parsing sema. In case
/// the speculative result is used by code completion (e.g. speculation failed),
@@ -225,7 +243,6 @@ CodeCompleteResult codeComplete(PathRef FileName,
const PreambleData *Preamble,
StringRef Contents, Position Pos,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
- std::shared_ptr<PCHContainerOperations> PCHs,
CodeCompleteOptions Opts,
SpeculativeFuzzyFind *SpecFuzzyFind = nullptr);
@@ -235,7 +252,6 @@ SignatureHelp signatureHelp(PathRef FileName,
const PreambleData *Preamble, StringRef Contents,
Position Pos,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
- std::shared_ptr<PCHContainerOperations> PCHs,
const SymbolIndex *Index);
// For index-based completion, we only consider:
@@ -250,10 +266,21 @@ SignatureHelp signatureHelp(PathRef FileName,
// completion.
bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx);
-/// Retrives a speculative code completion filter text before the cursor.
-/// Exposed for testing only.
-llvm::Expected<llvm::StringRef>
-speculateCompletionFilter(llvm::StringRef Content, Position Pos);
+// Text immediately before the completion point that should be completed.
+// This is heuristically derived from the source code, and is used when:
+// - semantic analysis fails
+// - semantic analysis may be slow, and we speculatively query the index
+struct CompletionPrefix {
+ // The unqualified partial name.
+ // If there is none, begin() == end() == completion position.
+ llvm::StringRef Name;
+ // The spelled scope qualifier, such as Foo::.
+ // If there is none, begin() == end() == Name.begin().
+ llvm::StringRef Qualifier;
+};
+// Heuristically parses before Offset to determine what should be completed.
+CompletionPrefix guessCompletionPrefix(llvm::StringRef Content,
+ unsigned Offset);
} // namespace clangd
} // namespace clang
diff --git a/clangd/CodeCompletionStrings.cpp b/clangd/CodeCompletionStrings.cpp
index 42a8693f..586be67e 100644
--- a/clangd/CodeCompletionStrings.cpp
+++ b/clangd/CodeCompletionStrings.cpp
@@ -1,9 +1,8 @@
//===--- CodeCompletionStrings.cpp -------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/CodeCompletionStrings.h b/clangd/CodeCompletionStrings.h
index bf44cbda..153e0af1 100644
--- a/clangd/CodeCompletionStrings.h
+++ b/clangd/CodeCompletionStrings.h
@@ -1,9 +1,8 @@
//===--- CodeCompletionStrings.h ---------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clangd/Compiler.cpp b/clangd/Compiler.cpp
index c94ef755..7758e039 100644
--- a/clangd/Compiler.cpp
+++ b/clangd/Compiler.cpp
@@ -1,9 +1,8 @@
//===--- Compiler.cpp --------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -11,6 +10,7 @@
#include "Logger.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Serialization/PCHContainerOperations.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
@@ -40,11 +40,38 @@ void IgnoreDiagnostics::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
IgnoreDiagnostics::log(DiagLevel, Info);
}
+std::unique_ptr<CompilerInvocation>
+buildCompilerInvocation(const ParseInputs &Inputs) {
+ std::vector<const char *> ArgStrs;
+ for (const auto &S : Inputs.CompileCommand.CommandLine)
+ ArgStrs.push_back(S.c_str());
+
+ if (Inputs.FS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
+ log("Couldn't set working directory when creating compiler invocation.");
+ // We proceed anyway, our lit-tests rely on results for non-existing working
+ // dirs.
+ }
+
+ // FIXME(ibiryukov): store diagnostics from CommandLine when we start
+ // reporting them.
+ IgnoreDiagnostics IgnoreDiagnostics;
+ llvm::IntrusiveRefCntPtr<DiagnosticsEngine> CommandLineDiagsEngine =
+ CompilerInstance::createDiagnostics(new DiagnosticOptions,
+ &IgnoreDiagnostics, false);
+ std::unique_ptr<CompilerInvocation> CI = createInvocationFromCommandLine(
+ ArgStrs, CommandLineDiagsEngine, Inputs.FS);
+ if (!CI)
+ return nullptr;
+ // createInvocationFromCommandLine sets DisableFree.
+ CI->getFrontendOpts().DisableFree = false;
+ CI->getLangOpts()->CommentOpts.ParseAllComments = true;
+ return CI;
+}
+
std::unique_ptr<CompilerInstance>
prepareCompilerInstance(std::unique_ptr<clang::CompilerInvocation> CI,
const PrecompiledPreamble *Preamble,
std::unique_ptr<llvm::MemoryBuffer> Buffer,
- std::shared_ptr<PCHContainerOperations> PCHs,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
DiagnosticConsumer &DiagsClient) {
assert(VFS && "VFS is null");
@@ -61,14 +88,15 @@ prepareCompilerInstance(std::unique_ptr<clang::CompilerInvocation> CI,
CI->getFrontendOpts().Inputs[0].getFile(), Buffer.get());
}
- auto Clang = llvm::make_unique<CompilerInstance>(PCHs);
+ auto Clang = llvm::make_unique<CompilerInstance>(
+ std::make_shared<PCHContainerOperations>());
Clang->setInvocation(std::move(CI));
Clang->createDiagnostics(&DiagsClient, false);
if (auto VFSWithRemapping = createVFSFromCompilerInvocation(
Clang->getInvocation(), Clang->getDiagnostics(), VFS))
VFS = VFSWithRemapping;
- Clang->setVirtualFileSystem(VFS);
+ Clang->createFileManager(VFS);
Clang->setTarget(TargetInfo::CreateTargetInfo(
Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
diff --git a/clangd/Compiler.h b/clangd/Compiler.h
index 7a3c43d6..c24ea354 100644
--- a/clangd/Compiler.h
+++ b/clangd/Compiler.h
@@ -1,9 +1,8 @@
//===--- Compiler.h ----------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -16,9 +15,12 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_COMPILER_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_COMPILER_H
+#include "../clang-tidy/ClangTidyOptions.h"
+#include "GlobalCompilationDatabase.h"
+#include "index/Index.h"
#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/PrecompiledPreamble.h"
+#include "clang/Tooling/CompilationDatabase.h"
namespace clang {
namespace clangd {
@@ -32,6 +34,26 @@ public:
const clang::Diagnostic &Info) override;
};
+// Options to run clang e.g. when parsing AST.
+struct ParseOptions {
+ tidy::ClangTidyOptions ClangTidyOpts;
+ bool SuggestMissingIncludes = false;
+};
+
+/// Information required to run clang, e.g. to parse AST or do code completion.
+struct ParseInputs {
+ tooling::CompileCommand CompileCommand;
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
+ std::string Contents;
+ // Used to recover from diagnostics (e.g. find missing includes for symbol).
+ const SymbolIndex *Index = nullptr;
+ ParseOptions Opts;
+};
+
+/// Builds compiler invocation that could be used to build AST or preamble.
+std::unique_ptr<CompilerInvocation>
+buildCompilerInvocation(const ParseInputs &Inputs);
+
/// Creates a compiler instance, configured so that:
/// - Contents of the parsed file are remapped to \p MainFile.
/// - Preamble is overriden to use PCH passed to this function. It means the
@@ -45,7 +67,6 @@ public:
std::unique_ptr<CompilerInstance> prepareCompilerInstance(
std::unique_ptr<clang::CompilerInvocation>, const PrecompiledPreamble *,
std::unique_ptr<llvm::MemoryBuffer> MainFile,
- std::shared_ptr<PCHContainerOperations>,
IntrusiveRefCntPtr<llvm::vfs::FileSystem>, DiagnosticConsumer &);
} // namespace clangd
diff --git a/clangd/Context.cpp b/clangd/Context.cpp
index 66654c47..8e8bba6e 100644
--- a/clangd/Context.cpp
+++ b/clangd/Context.cpp
@@ -1,9 +1,8 @@
//===--- Context.cpp ---------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/Context.h b/clangd/Context.h
index 7e14f86c..0bb4cbd9 100644
--- a/clangd/Context.h
+++ b/clangd/Context.h
@@ -1,9 +1,8 @@
//===--- Context.h - Mechanism for passing implicit data --------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clangd/Diagnostics.cpp b/clangd/Diagnostics.cpp
index 1cd52ad3..c004fa32 100644
--- a/clangd/Diagnostics.cpp
+++ b/clangd/Diagnostics.cpp
@@ -1,27 +1,59 @@
//===--- Diagnostics.cpp -----------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "Diagnostics.h"
+#include "../clang-tidy/ClangTidyDiagnosticConsumer.h"
#include "Compiler.h"
#include "Logger.h"
+#include "Protocol.h"
#include "SourceCode.h"
+#include "clang/Basic/AllDiagnostics.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/Capacity.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/Signals.h"
#include <algorithm>
namespace clang {
namespace clangd {
-
namespace {
+const char *getDiagnosticCode(unsigned ID) {
+ switch (ID) {
+#define DIAG(ENUM, CLASS, DEFAULT_MAPPING, DESC, GROPU, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ case clang::diag::ENUM: \
+ return #ENUM;
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+#include "clang/Basic/DiagnosticCommentKinds.inc"
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#include "clang/Basic/DiagnosticRefactoringKinds.inc"
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#include "clang/Basic/DiagnosticSerializationKinds.inc"
+#undef DIAG
+ default:
+ return nullptr;
+ }
+}
+
bool mentionsMainFile(const Diag &D) {
if (D.InsideMainFile)
return true;
@@ -77,6 +109,39 @@ Range diagnosticRange(const clang::Diagnostic &D, const LangOptions &L) {
return halfOpenToRange(M, R);
}
+void adjustDiagFromHeader(Diag &D, const clang::Diagnostic &Info,
+ const LangOptions &LangOpts) {
+ const SourceLocation &DiagLoc = Info.getLocation();
+ const SourceManager &SM = Info.getSourceManager();
+ SourceLocation IncludeInMainFile;
+ auto GetIncludeLoc = [&SM](SourceLocation SLoc) {
+ return SM.getIncludeLoc(SM.getFileID(SLoc));
+ };
+ for (auto IncludeLocation = GetIncludeLoc(DiagLoc); IncludeLocation.isValid();
+ IncludeLocation = GetIncludeLoc(IncludeLocation))
+ IncludeInMainFile = IncludeLocation;
+ if (IncludeInMainFile.isInvalid())
+ return;
+
+ // Update diag to point at include inside main file.
+ D.File = SM.getFileEntryForID(SM.getMainFileID())->getName().str();
+ D.Range.start = sourceLocToPosition(SM, IncludeInMainFile);
+ D.Range.end = sourceLocToPosition(
+ SM, Lexer::getLocForEndOfToken(IncludeInMainFile, 0, SM, LangOpts));
+
+ // Add a note that will point to real diagnostic.
+ const auto *FE = SM.getFileEntryForID(SM.getFileID(DiagLoc));
+ D.Notes.emplace_back();
+ Note &N = D.Notes.back();
+ N.AbsFile = FE->tryGetRealPathName();
+ N.File = FE->getName();
+ N.Message = "error occurred here";
+ N.Range = diagnosticRange(Info, LangOpts);
+
+ // Update message to mention original file.
+ D.Message = llvm::Twine("in included file: ", D.Message).str();
+}
+
bool isInsideMainFile(const SourceLocation Loc, const SourceManager &M) {
return Loc.isValid() && M.isWrittenInMainFile(M.getFileLoc(Loc));
}
@@ -151,9 +216,7 @@ std::string capitalize(std::string Message) {
}
/// Returns a message sent to LSP for the main diagnostic in \p D.
-/// The message includes all the notes with their corresponding locations.
-/// However, notes with fix-its are excluded as those usually only contain a
-/// fix-it message and just add noise if included in the message for diagnostic.
+/// This message may include notes, if they're not emited in some other way.
/// Example output:
///
/// no matching function for call to 'foo'
@@ -162,27 +225,34 @@ std::string capitalize(std::string Message) {
///
/// dir1/dir2/dir3/../../dir4/header.h:12:23
/// note: candidate function not viable: requires 3 arguments
-std::string mainMessage(const Diag &D) {
+std::string mainMessage(const Diag &D, const ClangdDiagnosticOptions &Opts) {
std::string Result;
llvm::raw_string_ostream OS(Result);
OS << D.Message;
- for (auto &Note : D.Notes) {
- OS << "\n\n";
- printDiag(OS, Note);
- }
+ if (Opts.DisplayFixesCount && !D.Fixes.empty())
+ OS << " (" << (D.Fixes.size() > 1 ? "fixes" : "fix") << " available)";
+ // If notes aren't emitted as structured info, add them to the message.
+ if (!Opts.EmitRelatedLocations)
+ for (auto &Note : D.Notes) {
+ OS << "\n\n";
+ printDiag(OS, Note);
+ }
OS.flush();
return capitalize(std::move(Result));
}
/// Returns a message sent to LSP for the note of the main diagnostic.
-/// The message includes the main diagnostic to provide the necessary context
-/// for the user to understand the note.
-std::string noteMessage(const Diag &Main, const DiagBase &Note) {
+std::string noteMessage(const Diag &Main, const DiagBase &Note,
+ const ClangdDiagnosticOptions &Opts) {
std::string Result;
llvm::raw_string_ostream OS(Result);
OS << Note.Message;
- OS << "\n\n";
- printDiag(OS, Main);
+ // If the client doesn't support structured links between the note and the
+ // original diagnostic, then emit the main diagnostic to give context.
+ if (!Opts.EmitRelatedLocations) {
+ OS << "\n\n";
+ printDiag(OS, Main);
+ }
OS.flush();
return capitalize(std::move(Result));
}
@@ -249,27 +319,54 @@ void toLSPDiags(
return Res;
};
- {
- clangd::Diagnostic Main = FillBasicFields(D);
- Main.message = mainMessage(D);
- if (Opts.EmbedFixesInDiagnostics) {
- Main.codeActions.emplace();
- for (const auto &Fix : D.Fixes)
- Main.codeActions->push_back(toCodeAction(Fix, File));
- }
- if (Opts.SendDiagnosticCategory && !D.Category.empty())
- Main.category = D.Category;
-
- OutFn(std::move(Main), D.Fixes);
+ clangd::Diagnostic Main = FillBasicFields(D);
+ Main.code = D.Name;
+ switch (D.Source) {
+ case Diag::Clang:
+ Main.source = "clang";
+ break;
+ case Diag::ClangTidy:
+ Main.source = "clang-tidy";
+ break;
+ case Diag::Unknown:
+ break;
+ }
+ if (Opts.EmbedFixesInDiagnostics) {
+ Main.codeActions.emplace();
+ for (const auto &Fix : D.Fixes)
+ Main.codeActions->push_back(toCodeAction(Fix, File));
}
+ if (Opts.SendDiagnosticCategory && !D.Category.empty())
+ Main.category = D.Category;
- for (auto &Note : D.Notes) {
- if (!Note.InsideMainFile)
- continue;
- clangd::Diagnostic Res = FillBasicFields(Note);
- Res.message = noteMessage(D, Note);
- OutFn(std::move(Res), llvm::ArrayRef<Fix>());
+ Main.message = mainMessage(D, Opts);
+ if (Opts.EmitRelatedLocations) {
+ Main.relatedInformation.emplace();
+ for (auto &Note : D.Notes) {
+ if (!Note.AbsFile) {
+ vlog("Dropping note from unknown file: {0}", Note);
+ continue;
+ }
+ DiagnosticRelatedInformation RelInfo;
+ RelInfo.location.range = Note.Range;
+ RelInfo.location.uri =
+ URIForFile::canonicalize(*Note.AbsFile, File.file());
+ RelInfo.message = noteMessage(D, Note, Opts);
+ Main.relatedInformation->push_back(std::move(RelInfo));
+ }
}
+ OutFn(std::move(Main), D.Fixes);
+
+ // If we didn't emit the notes as relatedLocations, emit separate diagnostics
+ // so the user can find the locations easily.
+ if (!Opts.EmitRelatedLocations)
+ for (auto &Note : D.Notes) {
+ if (!Note.InsideMainFile)
+ continue;
+ clangd::Diagnostic Res = FillBasicFields(Note);
+ Res.message = noteMessage(D, Note, Opts);
+ OutFn(std::move(Res), llvm::ArrayRef<Fix>());
+ }
}
int getSeverity(DiagnosticsEngine::Level L) {
@@ -289,7 +386,46 @@ int getSeverity(DiagnosticsEngine::Level L) {
llvm_unreachable("Unknown diagnostic level!");
}
-std::vector<Diag> StoreDiags::take() { return std::move(Output); }
+std::vector<Diag> StoreDiags::take(const clang::tidy::ClangTidyContext *Tidy) {
+ // Fill in name/source now that we have all the context needed to map them.
+ for (auto &Diag : Output) {
+ if (const char *ClangDiag = getDiagnosticCode(Diag.ID)) {
+ // Warnings controlled by -Wfoo are better recognized by that name.
+ StringRef Warning = DiagnosticIDs::getWarningOptionForDiag(Diag.ID);
+ if (!Warning.empty()) {
+ Diag.Name = ("-W" + Warning).str();
+ } else {
+ StringRef Name(ClangDiag);
+ // Almost always an error, with a name like err_enum_class_reference.
+ // Drop the err_ prefix for brevity.
+ Name.consume_front("err_");
+ Diag.Name = Name;
+ }
+ Diag.Source = Diag::Clang;
+ continue;
+ }
+ if (Tidy != nullptr) {
+ std::string TidyDiag = Tidy->getCheckName(Diag.ID);
+ if (!TidyDiag.empty()) {
+ Diag.Name = std::move(TidyDiag);
+ Diag.Source = Diag::ClangTidy;
+ // clang-tidy bakes the name into diagnostic messages. Strip it out.
+ // It would be much nicer to make clang-tidy not do this.
+ auto CleanMessage = [&](std::string &Msg) {
+ StringRef Rest(Msg);
+ if (Rest.consume_back("]") && Rest.consume_back(Diag.Name) &&
+ Rest.consume_back(" ["))
+ Msg.resize(Rest.size());
+ };
+ CleanMessage(Diag.Message);
+ for (auto &Note : Diag.Notes)
+ CleanMessage(Note.Message);
+ continue;
+ }
+ }
+ }
+ return std::move(Output);
+}
void StoreDiags::BeginSourceFile(const LangOptions &Opts,
const Preprocessor *) {
@@ -319,6 +455,9 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
D.Message = Message.str();
D.InsideMainFile = InsideMainFile;
D.File = Info.getSourceManager().getFilename(Info.getLocation());
+ auto &SM = Info.getSourceManager();
+ D.AbsFile = getCanonicalPath(
+ SM.getFileEntryForID(SM.getFileID(Info.getLocation())), SM);
D.Severity = DiagLevel;
D.Category = DiagnosticIDs::getCategoryNameFromID(
DiagnosticIDs::getCategoryNumberForDiag(Info.getID()))
@@ -334,6 +473,11 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
llvm::SmallVector<TextEdit, 1> Edits;
for (auto &FixIt : Info.getFixItHints()) {
+ // Follow clang's behavior, don't apply FixIt to the code in macros,
+ // we are less certain it is the right fix.
+ if (FixIt.RemoveRange.getBegin().isMacroID() ||
+ FixIt.RemoveRange.getEnd().isMacroID())
+ return false;
if (!isInsideMainFile(FixIt.RemoveRange.getBegin(),
Info.getSourceManager()))
return false;
@@ -371,10 +515,17 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
flushLastDiag();
LastDiag = Diag();
+ LastDiag->ID = Info.getID();
FillDiagBase(*LastDiag);
+ adjustDiagFromHeader(*LastDiag, Info, *LangOpts);
if (!Info.getFixItHints().empty())
AddFix(true /* try to invent a message instead of repeating the diag */);
+ if (Fixer) {
+ auto ExtraFixes = Fixer(DiagLevel, Info);
+ LastDiag->Fixes.insert(LastDiag->Fixes.end(), ExtraFixes.begin(),
+ ExtraFixes.end());
+ }
} else {
// Handle a note to an existing diagnostic.
if (!LastDiag) {
@@ -401,11 +552,15 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
void StoreDiags::flushLastDiag() {
if (!LastDiag)
return;
- if (mentionsMainFile(*LastDiag))
+ // Only keeps diagnostics inside main file or the first one coming from a
+ // header.
+ if (mentionsMainFile(*LastDiag) ||
+ (LastDiag->Severity >= DiagnosticsEngine::Level::Error &&
+ IncludeLinesWithErrors.insert(LastDiag->Range.start.line).second)) {
Output.push_back(std::move(*LastDiag));
- else
- log("Dropped diagnostic outside main file: {0}: {1}", LastDiag->File,
- LastDiag->Message);
+ } else {
+ vlog("Dropped diagnostic: {0}: {1}", LastDiag->File, LastDiag->Message);
+ }
LastDiag.reset();
}
diff --git a/clangd/Diagnostics.h b/clangd/Diagnostics.h
index 6318e88f..a0ab7c66 100644
--- a/clangd/Diagnostics.h
+++ b/clangd/Diagnostics.h
@@ -1,9 +1,8 @@
//===--- Diagnostics.h -------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -15,12 +14,18 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSet.h"
#include <cassert>
#include <string>
namespace clang {
+namespace tidy {
+class ClangTidyContext;
+} // namespace tidy
namespace clangd {
struct ClangdDiagnosticOptions {
@@ -28,11 +33,20 @@ struct ClangdDiagnosticOptions {
/// diagnostics that are sent to the client.
bool EmbedFixesInDiagnostics = false;
+ /// If true, Clangd uses the relatedInformation field to include other
+ /// locations (in particular attached notes).
+ /// Otherwise, these are flattened into the diagnostic message.
+ bool EmitRelatedLocations = false;
+
/// If true, Clangd uses an LSP extension to send the diagnostic's
/// category to the client. The category typically describes the compilation
/// stage during which the issue was produced, e.g. "Semantic Issue" or "Parse
/// Issue".
bool SendDiagnosticCategory = false;
+
+ /// If true, Clangd will add a number of available fixes to the diagnostic's
+ /// message.
+ bool DisplayFixesCount = true;
};
/// Contains basic information about a diagnostic.
@@ -41,6 +55,9 @@ struct DiagBase {
// Intended to be used only in error messages.
// May be relative, absolute or even artifically constructed.
std::string File;
+ // Absolute path to containing file, if available.
+ llvm::Optional<std::string> AbsFile;
+
clangd::Range Range;
DiagnosticsEngine::Level Severity = DiagnosticsEngine::Note;
std::string Category;
@@ -65,6 +82,14 @@ struct Note : DiagBase {};
/// A top-level diagnostic that may have Notes and Fixes.
struct Diag : DiagBase {
+ unsigned ID; // e.g. member of clang::diag, or clang-tidy assigned ID.
+ std::string Name; // if ID was recognized.
+ // The source of this diagnostic.
+ enum {
+ Unknown,
+ Clang,
+ ClangTidy,
+ } Source = Unknown;
/// Elaborate on the problem, usually pointing to a related piece of code.
std::vector<Note> Notes;
/// *Alternative* fixes for this diagnostic, one should be chosen.
@@ -93,19 +118,27 @@ int getSeverity(DiagnosticsEngine::Level L);
/// the diag itself nor its notes are in the main file).
class StoreDiags : public DiagnosticConsumer {
public:
- std::vector<Diag> take();
+ // The ClangTidyContext populates Source and Name for clang-tidy diagnostics.
+ std::vector<Diag> take(const clang::tidy::ClangTidyContext *Tidy = nullptr);
void BeginSourceFile(const LangOptions &Opts, const Preprocessor *) override;
void EndSourceFile() override;
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic &Info) override;
+ using DiagFixer = std::function<std::vector<Fix>(DiagnosticsEngine::Level,
+ const clang::Diagnostic &)>;
+ /// If set, possibly adds fixes for diagnostics using \p Fixer.
+ void contributeFixes(DiagFixer Fixer) { this->Fixer = Fixer; }
+
private:
void flushLastDiag();
+ DiagFixer Fixer = nullptr;
std::vector<Diag> Output;
llvm::Optional<LangOptions> LangOpts;
llvm::Optional<Diag> LastDiag;
+ llvm::DenseSet<int> IncludeLinesWithErrors;
};
} // namespace clangd
diff --git a/clangd/DraftStore.cpp b/clangd/DraftStore.cpp
index 9b6c1fc4..16d7ddee 100644
--- a/clangd/DraftStore.cpp
+++ b/clangd/DraftStore.cpp
@@ -1,9 +1,8 @@
//===--- DraftStore.cpp - File contents container ---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/DraftStore.h b/clangd/DraftStore.h
index 90a2d2cf..1578ce9f 100644
--- a/clangd/DraftStore.h
+++ b/clangd/DraftStore.h
@@ -1,9 +1,8 @@
//===--- DraftStore.h - File contents container -----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/ExpectedTypes.cpp b/clangd/ExpectedTypes.cpp
index 4bbf0651..886b5db0 100644
--- a/clangd/ExpectedTypes.cpp
+++ b/clangd/ExpectedTypes.cpp
@@ -1,3 +1,11 @@
+//===--- ExpectedTypes.cpp ---------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
#include "ExpectedTypes.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
@@ -35,8 +43,10 @@ static llvm::Optional<QualType>
typeOfCompletion(const CodeCompletionResult &R) {
auto *VD = dyn_cast_or_null<ValueDecl>(R.Declaration);
if (!VD)
- return None; // We handle only variables and functions below.
+ return llvm::None; // We handle only variables and functions below.
auto T = VD->getType();
+ if (T.isNull())
+ return llvm::None;
if (auto FuncT = T->getAs<FunctionType>()) {
// Functions are a special case. They are completed as 'foo()' and we want
// to match their return type rather than the function type itself.
diff --git a/clangd/ExpectedTypes.h b/clangd/ExpectedTypes.h
index 2f231283..36b7cce1 100644
--- a/clangd/ExpectedTypes.h
+++ b/clangd/ExpectedTypes.h
@@ -1,9 +1,8 @@
//===--- ExpectedTypes.h - Simplified C++ types -----------------*- C++-*--===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
// A simplified model of C++ types that can be used to check whether they are
diff --git a/clangd/FS.cpp b/clangd/FS.cpp
index 5d690c86..aae15b55 100644
--- a/clangd/FS.cpp
+++ b/clangd/FS.cpp
@@ -1,9 +1,8 @@
//===--- FS.cpp - File system related utils ----------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/FS.h b/clangd/FS.h
index d4003040..e23b3ff1 100644
--- a/clangd/FS.h
+++ b/clangd/FS.h
@@ -1,9 +1,8 @@
//===--- FS.h - File system related utils ------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/FSProvider.cpp b/clangd/FSProvider.cpp
index 81a1adab..5d1434bf 100644
--- a/clangd/FSProvider.cpp
+++ b/clangd/FSProvider.cpp
@@ -1,9 +1,8 @@
//===--- FSProvider.cpp - VFS provider for ClangdServer -------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -75,9 +74,10 @@ clang::clangd::RealFileSystemProvider::getFileSystem() const {
// FIXME: Try to use a similar approach in Sema instead of relying on
// propagation of the 'isVolatile' flag through all layers.
#ifdef _WIN32
- return new VolatileFileSystem(llvm::vfs::getRealFileSystem());
+ return new VolatileFileSystem(
+ llvm::vfs::createPhysicalFileSystem().release());
#else
- return llvm::vfs::getRealFileSystem();
+ return llvm::vfs::createPhysicalFileSystem().release();
#endif
}
} // namespace clangd
diff --git a/clangd/FSProvider.h b/clangd/FSProvider.h
index 67d2ec15..22957892 100644
--- a/clangd/FSProvider.h
+++ b/clangd/FSProvider.h
@@ -1,9 +1,8 @@
//===--- FSProvider.h - VFS provider for ClangdServer ------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/FileDistance.cpp b/clangd/FileDistance.cpp
index 7bac2516..a6a65ab7 100644
--- a/clangd/FileDistance.cpp
+++ b/clangd/FileDistance.cpp
@@ -1,9 +1,8 @@
//===--- FileDistance.cpp - File contents container -------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clangd/FileDistance.h b/clangd/FileDistance.h
index 2623ce76..e7174bcc 100644
--- a/clangd/FileDistance.h
+++ b/clangd/FileDistance.h
@@ -1,9 +1,8 @@
//===--- FileDistance.h - File proximity scoring -----------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clangd/FindSymbols.cpp b/clangd/FindSymbols.cpp
index 208e78c6..b2bd1662 100644
--- a/clangd/FindSymbols.cpp
+++ b/clangd/FindSymbols.cpp
@@ -1,9 +1,8 @@
//===--- FindSymbols.cpp ------------------------------------*- C++-*------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "FindSymbols.h"
@@ -27,67 +26,8 @@
namespace clang {
namespace clangd {
-namespace {
-
-// Convert a index::SymbolKind to clangd::SymbolKind (LSP)
-// Note, some are not perfect matches and should be improved when this LSP
-// issue is addressed:
-// https://github.com/Microsoft/language-server-protocol/issues/344
-SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind) {
- switch (Kind) {
- case index::SymbolKind::Unknown:
- return SymbolKind::Variable;
- case index::SymbolKind::Module:
- return SymbolKind::Module;
- case index::SymbolKind::Namespace:
- return SymbolKind::Namespace;
- case index::SymbolKind::NamespaceAlias:
- return SymbolKind::Namespace;
- case index::SymbolKind::Macro:
- return SymbolKind::String;
- case index::SymbolKind::Enum:
- return SymbolKind::Enum;
- case index::SymbolKind::Struct:
- return SymbolKind::Struct;
- case index::SymbolKind::Class:
- return SymbolKind::Class;
- case index::SymbolKind::Protocol:
- return SymbolKind::Interface;
- case index::SymbolKind::Extension:
- return SymbolKind::Interface;
- case index::SymbolKind::Union:
- return SymbolKind::Class;
- case index::SymbolKind::TypeAlias:
- return SymbolKind::Class;
- case index::SymbolKind::Function:
- return SymbolKind::Function;
- case index::SymbolKind::Variable:
- return SymbolKind::Variable;
- case index::SymbolKind::Field:
- return SymbolKind::Field;
- case index::SymbolKind::EnumConstant:
- return SymbolKind::EnumMember;
- case index::SymbolKind::InstanceMethod:
- case index::SymbolKind::ClassMethod:
- case index::SymbolKind::StaticMethod:
- return SymbolKind::Method;
- case index::SymbolKind::InstanceProperty:
- case index::SymbolKind::ClassProperty:
- case index::SymbolKind::StaticProperty:
- return SymbolKind::Property;
- case index::SymbolKind::Constructor:
- case index::SymbolKind::Destructor:
- return SymbolKind::Method;
- case index::SymbolKind::ConversionFunction:
- return SymbolKind::Function;
- case index::SymbolKind::Parameter:
- return SymbolKind::Variable;
- case index::SymbolKind::Using:
- return SymbolKind::Namespace;
- }
- llvm_unreachable("invalid symbol kind");
-}
+namespace {
using ScoredSymbolInfo = std::pair<float, SymbolInformation>;
struct ScoredSymbolGreater {
bool operator()(const ScoredSymbolInfo &L, const ScoredSymbolInfo &R) {
@@ -154,11 +94,13 @@ getWorkspaceSymbols(llvm::StringRef Query, int Limit,
std::string Scope = Sym.Scope;
llvm::StringRef ScopeRef = Scope;
ScopeRef.consume_back("::");
- SymbolInformation Info = {Sym.Name, SK, L, ScopeRef};
+ SymbolInformation Info = {(Sym.Name + Sym.TemplateSpecializationArgs).str(),
+ SK, L, ScopeRef};
SymbolQualitySignals Quality;
Quality.merge(Sym);
SymbolRelevanceSignals Relevance;
+ Relevance.Name = Sym.Name;
Relevance.Query = SymbolRelevanceSignals::Generic;
if (auto NameMatch = Filter.match(Sym.Name))
Relevance.NameMatch = *NameMatch;
diff --git a/clangd/FindSymbols.h b/clangd/FindSymbols.h
index a9c8c998..e4980c97 100644
--- a/clangd/FindSymbols.h
+++ b/clangd/FindSymbols.h
@@ -1,9 +1,8 @@
//===--- FindSymbols.h --------------------------------------*- C++-*------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -22,9 +21,10 @@ class ParsedAST;
class SymbolIndex;
/// Searches for the symbols matching \p Query. The syntax of \p Query can be
-/// the non-qualified name or fully qualified of a symbol. For example, "vector"
-/// will match the symbol std::vector and "std::vector" would also match it.
-/// Direct children of scopes (namepaces, etc) can be listed with a trailing
+/// the non-qualified name or fully qualified of a symbol. For example,
+/// "vector" will match the symbol std::vector and "std::vector" would also
+/// match it. Direct children of scopes (namepaces, etc) can be listed with a
+/// trailing
/// "::". For example, "std::" will list all children of the std namespace and
/// "::" alone will list all children of the global namespace.
/// \p Limit limits the number of results returned (0 means no limit).
diff --git a/clangd/Function.h b/clangd/Function.h
index c91b9cbe..6d91136b 100644
--- a/clangd/Function.h
+++ b/clangd/Function.h
@@ -1,9 +1,8 @@
//===--- Function.h - Utility callable wrappers -----------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clangd/FuzzyMatch.cpp b/clangd/FuzzyMatch.cpp
index 433242e6..57f9554a 100644
--- a/clangd/FuzzyMatch.cpp
+++ b/clangd/FuzzyMatch.cpp
@@ -1,9 +1,8 @@
//===--- FuzzyMatch.h - Approximate identifier matching ---------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -72,7 +71,7 @@ static char lower(char C) { return C >= 'A' && C <= 'Z' ? C + ('a' - 'A') : C; }
// Score field is 15 bits wide, min value is -2^14, we use half of that.
static constexpr int AwfulScore = -(1 << 13);
static bool isAwful(int S) { return S < AwfulScore / 2; }
-static constexpr int PerfectBonus = 3; // Perfect per-pattern-char score.
+static constexpr int PerfectBonus = 4; // Perfect per-pattern-char score.
FuzzyMatcher::FuzzyMatcher(llvm::StringRef Pattern)
: PatN(std::min<int>(MaxPat, Pattern.size())),
@@ -268,24 +267,31 @@ bool FuzzyMatcher::allowMatch(int P, int W, Action Last) const {
}
int FuzzyMatcher::skipPenalty(int W, Action Last) const {
- int S = 0;
+ if (W == 0) // Skipping the first character.
+ return 3;
if (WordRole[W] == Head) // Skipping a segment.
- S += 1;
- if (Last == Match) // Non-consecutive match.
- S += 2; // We'd rather skip a segment than split our match.
- return S;
+ return 1; // We want to keep this lower than a consecutive match bonus.
+ // Instead of penalizing non-consecutive matches, we give a bonus to a
+ // consecutive match in matchBonus. This produces a better score distribution
+ // than penalties in case of small patterns, e.g. 'up' for 'unique_ptr'.
+ return 0;
}
int FuzzyMatcher::matchBonus(int P, int W, Action Last) const {
assert(LowPat[P] == LowWord[W]);
int S = 1;
- // Bonus: pattern so far is a (case-insensitive) prefix of the word.
- if (P == W) // We can't skip pattern characters, so we must have matched all.
- ++S;
+ bool IsPatSingleCase =
+ (PatTypeSet == 1 << Lower) || (PatTypeSet == 1 << Upper);
// Bonus: case matches, or a Head in the pattern aligns with one in the word.
- if ((Pat[P] == Word[W] && ((PatTypeSet & 1 << Upper) || P == W)) ||
- (PatRole[P] == Head && WordRole[W] == Head))
+ // Single-case patterns lack segmentation signals and we assume any character
+ // can be a head of a segment.
+ if (Pat[P] == Word[W] ||
+ (WordRole[W] == Head && (IsPatSingleCase || PatRole[P] == Head)))
++S;
+ // Bonus: a consecutive match. First character match also gets a bonus to
+ // ensure prefix final match score normalizes to 1.0.
+ if (W == 0 || Last == Match)
+ S += 2;
// Penalty: matching inside a segment (and previous char wasn't matched).
if (WordRole[W] == Tail && P && Last == Miss)
S -= 3;
diff --git a/clangd/FuzzyMatch.h b/clangd/FuzzyMatch.h
index f0c7e722..81c2edb8 100644
--- a/clangd/FuzzyMatch.h
+++ b/clangd/FuzzyMatch.h
@@ -1,9 +1,8 @@
//===--- FuzzyMatch.h - Approximate identifier matching ---------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clangd/GlobalCompilationDatabase.cpp b/clangd/GlobalCompilationDatabase.cpp
index c2fff7b2..50f5408c 100644
--- a/clangd/GlobalCompilationDatabase.cpp
+++ b/clangd/GlobalCompilationDatabase.cpp
@@ -1,20 +1,49 @@
//===--- GlobalCompilationDatabase.cpp ---------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "GlobalCompilationDatabase.h"
#include "Logger.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Tooling/CompilationDatabase.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
namespace clang {
namespace clangd {
+namespace {
+
+void adjustArguments(tooling::CompileCommand &Cmd,
+ llvm::StringRef ResourceDir) {
+ tooling::ArgumentsAdjuster ArgsAdjuster = tooling::combineAdjusters(
+ // clangd should not write files to disk, including dependency files
+ // requested on the command line.
+ tooling::getClangStripDependencyFileAdjuster(),
+ // Strip plugin related command line arguments. Clangd does
+ // not support plugins currently. Therefore it breaks if
+ // compiler tries to load plugins.
+ tooling::combineAdjusters(tooling::getStripPluginsAdjuster(),
+ tooling::getClangSyntaxOnlyAdjuster()));
+
+ Cmd.CommandLine = ArgsAdjuster(Cmd.CommandLine, Cmd.Filename);
+ // Inject the resource dir.
+ // FIXME: Don't overwrite it if it's already there.
+ if (!ResourceDir.empty())
+ Cmd.CommandLine.push_back(("-resource-dir=" + ResourceDir).str());
+}
+
+std::string getStandardResourceDir() {
+ static int Dummy; // Just an address in this process.
+ return CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy);
+}
+
+} // namespace
static std::string getFallbackClangPath() {
static int Dummy;
@@ -34,10 +63,11 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
if (llvm::sys::path::extension(File) == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(File);
- return tooling::CompileCommand(llvm::sys::path::parent_path(File),
- llvm::sys::path::filename(File),
- std::move(Argv),
- /*Output=*/"");
+ tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ llvm::sys::path::filename(File), std::move(Argv),
+ /*Output=*/"");
+ Cmd.Heuristic = "clangd fallback";
+ return Cmd;
}
DirectoryBasedGlobalCompilationDatabase::
@@ -106,8 +136,11 @@ DirectoryBasedGlobalCompilationDatabase::getCDBForFile(
}
OverlayCDB::OverlayCDB(const GlobalCompilationDatabase *Base,
- std::vector<std::string> FallbackFlags)
- : Base(Base), FallbackFlags(std::move(FallbackFlags)) {
+ std::vector<std::string> FallbackFlags,
+ llvm::Optional<std::string> ResourceDir)
+ : Base(Base), ResourceDir(ResourceDir ? std::move(*ResourceDir)
+ : getStandardResourceDir()),
+ FallbackFlags(std::move(FallbackFlags)) {
if (Base)
BaseChanged = Base->watch([this](const std::vector<std::string> Changes) {
OnCommandChanged.broadcast(Changes);
@@ -116,16 +149,22 @@ OverlayCDB::OverlayCDB(const GlobalCompilationDatabase *Base,
llvm::Optional<tooling::CompileCommand>
OverlayCDB::getCompileCommand(PathRef File, ProjectInfo *Project) const {
+ llvm::Optional<tooling::CompileCommand> Cmd;
{
std::lock_guard<std::mutex> Lock(Mutex);
auto It = Commands.find(File);
if (It != Commands.end()) {
if (Project)
Project->SourceRoot = "";
- return It->second;
+ Cmd = It->second;
}
}
- return Base ? Base->getCompileCommand(File, Project) : None;
+ if (!Cmd && Base)
+ Cmd = Base->getCompileCommand(File, Project);
+ if (!Cmd)
+ return llvm::None;
+ adjustArguments(*Cmd, ResourceDir);
+ return Cmd;
}
tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
diff --git a/clangd/GlobalCompilationDatabase.h b/clangd/GlobalCompilationDatabase.h
index 181b1781..0a97a30e 100644
--- a/clangd/GlobalCompilationDatabase.h
+++ b/clangd/GlobalCompilationDatabase.h
@@ -1,9 +1,8 @@
//===--- GlobalCompilationDatabase.h -----------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -12,6 +11,7 @@
#include "Function.h"
#include "Path.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
#include <memory>
#include <mutex>
@@ -98,7 +98,8 @@ public:
// Base may be null, in which case no entries are inherited.
// FallbackFlags are added to the fallback compile command.
OverlayCDB(const GlobalCompilationDatabase *Base,
- std::vector<std::string> FallbackFlags = {});
+ std::vector<std::string> FallbackFlags = {},
+ llvm::Optional<std::string> ResourceDir = llvm::None);
llvm::Optional<tooling::CompileCommand>
getCompileCommand(PathRef File, ProjectInfo * = nullptr) const override;
@@ -113,6 +114,7 @@ private:
mutable std::mutex Mutex;
llvm::StringMap<tooling::CompileCommand> Commands; /* GUARDED_BY(Mut) */
const GlobalCompilationDatabase *Base;
+ std::string ResourceDir;
std::vector<std::string> FallbackFlags;
CommandChanged::Subscription BaseChanged;
};
diff --git a/clangd/Headers.cpp b/clangd/Headers.cpp
index 06f822b3..8d209714 100644
--- a/clangd/Headers.cpp
+++ b/clangd/Headers.cpp
@@ -1,9 +1,8 @@
//===--- Headers.cpp - Include headers ---------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -74,6 +73,41 @@ bool HeaderFile::valid() const {
(!Verbatim && llvm::sys::path::is_absolute(File));
}
+llvm::Expected<HeaderFile> toHeaderFile(llvm::StringRef Header,
+ llvm::StringRef HintPath) {
+ if (isLiteralInclude(Header))
+ return HeaderFile{Header.str(), /*Verbatim=*/true};
+ auto U = URI::parse(Header);
+ if (!U)
+ return U.takeError();
+
+ auto IncludePath = URI::includeSpelling(*U);
+ if (!IncludePath)
+ return IncludePath.takeError();
+ if (!IncludePath->empty())
+ return HeaderFile{std::move(*IncludePath), /*Verbatim=*/true};
+
+ auto Resolved = URI::resolve(*U, HintPath);
+ if (!Resolved)
+ return Resolved.takeError();
+ return HeaderFile{std::move(*Resolved), /*Verbatim=*/false};
+}
+
+llvm::SmallVector<llvm::StringRef, 1> getRankedIncludes(const Symbol &Sym) {
+ auto Includes = Sym.IncludeHeaders;
+ // Sort in descending order by reference count and header length.
+ llvm::sort(Includes, [](const Symbol::IncludeHeaderWithReferences &LHS,
+ const Symbol::IncludeHeaderWithReferences &RHS) {
+ if (LHS.References == RHS.References)
+ return LHS.IncludeHeader.size() < RHS.IncludeHeader.size();
+ return LHS.References > RHS.References;
+ });
+ llvm::SmallVector<llvm::StringRef, 1> Headers;
+ for (const auto &Include : Includes)
+ Headers.push_back(Include.IncludeHeader);
+ return Headers;
+}
+
std::unique_ptr<PPCallbacks>
collectIncludeStructureCallback(const SourceManager &SM,
IncludeStructure *Out) {
@@ -139,24 +173,27 @@ void IncludeInserter::addExisting(const Inclusion &Inc) {
/// FIXME(ioeric): we might not want to insert an absolute include path if the
/// path is not shortened.
bool IncludeInserter::shouldInsertInclude(
- const HeaderFile &DeclaringHeader, const HeaderFile &InsertedHeader) const {
- assert(DeclaringHeader.valid() && InsertedHeader.valid());
- if (FileName == DeclaringHeader.File || FileName == InsertedHeader.File)
+ PathRef DeclaringHeader, const HeaderFile &InsertedHeader) const {
+ assert(InsertedHeader.valid());
+ if (!HeaderSearchInfo && !InsertedHeader.Verbatim)
+ return false;
+ if (FileName == DeclaringHeader || FileName == InsertedHeader.File)
return false;
auto Included = [&](llvm::StringRef Header) {
return IncludedHeaders.find(Header) != IncludedHeaders.end();
};
- return !Included(DeclaringHeader.File) && !Included(InsertedHeader.File);
+ return !Included(DeclaringHeader) && !Included(InsertedHeader.File);
}
std::string
-IncludeInserter::calculateIncludePath(const HeaderFile &DeclaringHeader,
- const HeaderFile &InsertedHeader) const {
- assert(DeclaringHeader.valid() && InsertedHeader.valid());
+IncludeInserter::calculateIncludePath(const HeaderFile &InsertedHeader) const {
+ assert(InsertedHeader.valid());
if (InsertedHeader.Verbatim)
return InsertedHeader.File;
bool IsSystem = false;
- std::string Suggested = HeaderSearchInfo.suggestPathToFileForDiagnostics(
+ if (!HeaderSearchInfo)
+ return "\"" + InsertedHeader.File + "\"";
+ std::string Suggested = HeaderSearchInfo->suggestPathToFileForDiagnostics(
InsertedHeader.File, BuildDir, &IsSystem);
if (IsSystem)
Suggested = "<" + Suggested + ">";
diff --git a/clangd/Headers.h b/clangd/Headers.h
index 6f0eb807..f2eaf081 100644
--- a/clangd/Headers.h
+++ b/clangd/Headers.h
@@ -1,9 +1,8 @@
//===--- Headers.h - Include headers -----------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -13,10 +12,12 @@
#include "Path.h"
#include "Protocol.h"
#include "SourceCode.h"
+#include "index/Symbol.h"
#include "clang/Format/Format.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Tooling/Inclusions/HeaderIncludes.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Error.h"
@@ -38,6 +39,15 @@ struct HeaderFile {
bool valid() const;
};
+/// Creates a `HeaderFile` from \p Header which can be either a URI or a literal
+/// include.
+llvm::Expected<HeaderFile> toHeaderFile(llvm::StringRef Header,
+ llvm::StringRef HintPath);
+
+// Returns include headers for \p Sym sorted by popularity. If two headers are
+// equally popular, prefer the shorter one.
+llvm::SmallVector<llvm::StringRef, 1> getRankedIncludes(const Symbol &Sym);
+
// An #include directive that we found in the main file.
struct Inclusion {
Range R; // Inclusion range.
@@ -109,9 +119,12 @@ collectIncludeStructureCallback(const SourceManager &SM, IncludeStructure *Out);
// Calculates insertion edit for including a new header in a file.
class IncludeInserter {
public:
+ // If \p HeaderSearchInfo is nullptr (e.g. when compile command is
+ // infeasible), this will only try to insert verbatim headers, and
+ // include path of non-verbatim header will not be shortened.
IncludeInserter(StringRef FileName, StringRef Code,
const format::FormatStyle &Style, StringRef BuildDir,
- HeaderSearch &HeaderSearchInfo)
+ HeaderSearch *HeaderSearchInfo)
: FileName(FileName), Code(Code), BuildDir(BuildDir),
HeaderSearchInfo(HeaderSearchInfo),
Inserter(FileName, Code, Style.IncludeStyle) {}
@@ -124,25 +137,22 @@ public:
/// in \p Inclusions (including those included via different paths).
/// - \p DeclaringHeader or \p InsertedHeader is the same as \p File.
///
- /// \param DeclaringHeader is the original header corresponding to \p
+ /// \param DeclaringHeader is path of the original header corresponding to \p
/// InsertedHeader e.g. the header that declares a symbol.
/// \param InsertedHeader The preferred header to be inserted. This could be
/// the same as DeclaringHeader but must be provided.
- bool shouldInsertInclude(const HeaderFile &DeclaringHeader,
+ bool shouldInsertInclude(PathRef DeclaringHeader,
const HeaderFile &InsertedHeader) const;
/// Determines the preferred way to #include a file, taking into account the
/// search path. Usually this will prefer a shorter representation like
/// 'Foo/Bar.h' over a longer one like 'Baz/include/Foo/Bar.h'.
///
- /// \param DeclaringHeader is the original header corresponding to \p
- /// InsertedHeader e.g. the header that declares a symbol.
/// \param InsertedHeader The preferred header to be inserted. This could be
/// the same as DeclaringHeader but must be provided.
///
/// \return A quoted "path" or <path> to be included.
- std::string calculateIncludePath(const HeaderFile &DeclaringHeader,
- const HeaderFile &InsertedHeader) const;
+ std::string calculateIncludePath(const HeaderFile &InsertedHeader) const;
/// Calculates an edit that inserts \p VerbatimHeader into code. If the header
/// is already included, this returns None.
@@ -152,7 +162,7 @@ private:
StringRef FileName;
StringRef Code;
StringRef BuildDir;
- HeaderSearch &HeaderSearchInfo;
+ HeaderSearch *HeaderSearchInfo = nullptr;
llvm::StringSet<> IncludedHeaders; // Both written and resolved.
tooling::HeaderIncludes Inserter; // Computers insertion replacement.
};
diff --git a/clangd/IncludeFixer.cpp b/clangd/IncludeFixer.cpp
new file mode 100644
index 00000000..f58ddba2
--- /dev/null
+++ b/clangd/IncludeFixer.cpp
@@ -0,0 +1,454 @@
+//===--- IncludeFixer.cpp ----------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "IncludeFixer.h"
+#include "AST.h"
+#include "Diagnostics.h"
+#include "Logger.h"
+#include "SourceCode.h"
+#include "Trace.h"
+#include "index/Index.h"
+#include "index/Symbol.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticSema.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/TypoCorrection.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FormatVariadic.h"
+#include <vector>
+
+namespace clang {
+namespace clangd {
+
+namespace {
+
+// Collects contexts visited during a Sema name lookup.
+class VisitedContextCollector : public VisibleDeclConsumer {
+public:
+ void EnteredContext(DeclContext *Ctx) override { Visited.push_back(Ctx); }
+
+ void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+ bool InBaseClass) override {}
+
+ std::vector<DeclContext *> takeVisitedContexts() {
+ return std::move(Visited);
+ }
+
+private:
+ std::vector<DeclContext *> Visited;
+};
+
+} // namespace
+
+std::vector<Fix> IncludeFixer::fix(DiagnosticsEngine::Level DiagLevel,
+ const clang::Diagnostic &Info) const {
+ switch (Info.getID()) {
+ case diag::err_incomplete_type:
+ case diag::err_incomplete_member_access:
+ case diag::err_incomplete_base_class:
+ case diag::err_incomplete_nested_name_spec:
+ // Incomplete type diagnostics should have a QualType argument for the
+ // incomplete type.
+ for (unsigned Idx = 0; Idx < Info.getNumArgs(); ++Idx) {
+ if (Info.getArgKind(Idx) == DiagnosticsEngine::ak_qualtype) {
+ auto QT = QualType::getFromOpaquePtr((void *)Info.getRawArg(Idx));
+ if (const Type *T = QT.getTypePtrOrNull())
+ if (T->isIncompleteType())
+ return fixIncompleteType(*T);
+ }
+ }
+ break;
+ case diag::err_unknown_typename:
+ case diag::err_unknown_typename_suggest:
+ case diag::err_typename_nested_not_found:
+ case diag::err_no_template:
+ case diag::err_no_template_suggest:
+ case diag::err_undeclared_use:
+ case diag::err_undeclared_use_suggest:
+ case diag::err_undeclared_var_use:
+ case diag::err_undeclared_var_use_suggest:
+ case diag::err_no_member: // Could be no member in namespace.
+ case diag::err_no_member_suggest:
+ if (LastUnresolvedName) {
+ // Try to fix unresolved name caused by missing declaraion.
+ // E.g.
+ // clang::SourceManager SM;
+ // ~~~~~~~~~~~~~
+ // UnresolvedName
+ // or
+ // namespace clang { SourceManager SM; }
+ // ~~~~~~~~~~~~~
+ // UnresolvedName
+ // We only attempt to recover a diagnostic if it has the same location as
+ // the last seen unresolved name.
+ if (DiagLevel >= DiagnosticsEngine::Error &&
+ LastUnresolvedName->Loc == Info.getLocation())
+ return fixUnresolvedName();
+ }
+ }
+ return {};
+}
+
+std::vector<Fix> IncludeFixer::fixIncompleteType(const Type &T) const {
+ // Only handle incomplete TagDecl type.
+ const TagDecl *TD = T.getAsTagDecl();
+ if (!TD)
+ return {};
+ std::string TypeName = printQualifiedName(*TD);
+ trace::Span Tracer("Fix include for incomplete type");
+ SPAN_ATTACH(Tracer, "type", TypeName);
+ vlog("Trying to fix include for incomplete type {0}", TypeName);
+
+ auto ID = getSymbolID(TD);
+ if (!ID)
+ return {};
+ llvm::Optional<const SymbolSlab *> Symbols = lookupCached(*ID);
+ if (!Symbols)
+ return {};
+ const SymbolSlab &Syms = **Symbols;
+ std::vector<Fix> Fixes;
+ if (!Syms.empty()) {
+ auto &Matched = *Syms.begin();
+ if (!Matched.IncludeHeaders.empty() && Matched.Definition &&
+ Matched.CanonicalDeclaration.FileURI == Matched.Definition.FileURI)
+ Fixes = fixesForSymbols(Syms);
+ }
+ return Fixes;
+}
+
+std::vector<Fix> IncludeFixer::fixesForSymbols(const SymbolSlab &Syms) const {
+ auto Inserted = [&](const Symbol &Sym, llvm::StringRef Header)
+ -> llvm::Expected<std::pair<std::string, bool>> {
+ auto DeclaringURI = URI::parse(Sym.CanonicalDeclaration.FileURI);
+ if (!DeclaringURI)
+ return DeclaringURI.takeError();
+ auto ResolvedDeclaring = URI::resolve(*DeclaringURI, File);
+ if (!ResolvedDeclaring)
+ return ResolvedDeclaring.takeError();
+ auto ResolvedInserted = toHeaderFile(Header, File);
+ if (!ResolvedInserted)
+ return ResolvedInserted.takeError();
+ return std::make_pair(
+ Inserter->calculateIncludePath(*ResolvedInserted),
+ Inserter->shouldInsertInclude(*ResolvedDeclaring, *ResolvedInserted));
+ };
+
+ std::vector<Fix> Fixes;
+ // Deduplicate fixes by include headers. This doesn't distiguish symbols in
+ // different scopes from the same header, but this case should be rare and is
+ // thus ignored.
+ llvm::StringSet<> InsertedHeaders;
+ for (const auto &Sym : Syms) {
+ for (const auto &Inc : getRankedIncludes(Sym)) {
+ if (auto ToInclude = Inserted(Sym, Inc)) {
+ if (ToInclude->second) {
+ auto I = InsertedHeaders.try_emplace(ToInclude->first);
+ if (!I.second)
+ continue;
+ if (auto Edit = Inserter->insert(ToInclude->first))
+ Fixes.push_back(
+ Fix{llvm::formatv("Add include {0} for symbol {1}{2}",
+ ToInclude->first, Sym.Scope, Sym.Name),
+ {std::move(*Edit)}});
+ }
+ } else {
+ vlog("Failed to calculate include insertion for {0} into {1}: {2}", Inc,
+ File, ToInclude.takeError());
+ }
+ }
+ }
+ return Fixes;
+}
+
+// Returns the identifiers qualified by an unresolved name. \p Loc is the
+// start location of the unresolved name. For the example below, this returns
+// "::X::Y" that is qualified by unresolved name "clangd":
+// clang::clangd::X::Y
+// ~
+llvm::Optional<std::string> qualifiedByUnresolved(const SourceManager &SM,
+ SourceLocation Loc,
+ const LangOptions &LangOpts) {
+ std::string Result;
+
+ SourceLocation NextLoc = Loc;
+ while (auto CCTok = Lexer::findNextToken(NextLoc, SM, LangOpts)) {
+ if (!CCTok->is(tok::coloncolon))
+ break;
+ auto IDTok = Lexer::findNextToken(CCTok->getLocation(), SM, LangOpts);
+ if (!IDTok || !IDTok->is(tok::raw_identifier))
+ break;
+ Result.append(("::" + IDTok->getRawIdentifier()).str());
+ NextLoc = IDTok->getLocation();
+ }
+ if (Result.empty())
+ return llvm::None;
+ return Result;
+}
+
+// An unresolved name and its scope information that can be extracted cheaply.
+struct CheapUnresolvedName {
+ std::string Name;
+ // This is the part of what was typed that was resolved, and it's in its
+ // resolved form not its typed form (think `namespace clang { clangd::x }` -->
+ // `clang::clangd::`).
+ llvm::Optional<std::string> ResolvedScope;
+
+ // Unresolved part of the scope. When the unresolved name is a specifier, we
+ // use the name that comes after it as the alternative name to resolve and use
+ // the specifier as the extra scope in the accessible scopes.
+ llvm::Optional<std::string> UnresolvedScope;
+};
+
+// Extracts unresolved name and scope information around \p Unresolved.
+// FIXME: try to merge this with the scope-wrangling code in CodeComplete.
+llvm::Optional<CheapUnresolvedName> extractUnresolvedNameCheaply(
+ const SourceManager &SM, const DeclarationNameInfo &Unresolved,
+ CXXScopeSpec *SS, const LangOptions &LangOpts, bool UnresolvedIsSpecifier) {
+ bool Invalid = false;
+ llvm::StringRef Code = SM.getBufferData(
+ SM.getDecomposedLoc(Unresolved.getBeginLoc()).first, &Invalid);
+ if (Invalid)
+ return llvm::None;
+ CheapUnresolvedName Result;
+ Result.Name = Unresolved.getAsString();
+ if (SS && SS->isNotEmpty()) { // "::" or "ns::"
+ if (auto *Nested = SS->getScopeRep()) {
+ if (Nested->getKind() == NestedNameSpecifier::Global)
+ Result.ResolvedScope = "";
+ else if (const auto *NS = Nested->getAsNamespace()) {
+ auto SpecifiedNS = printNamespaceScope(*NS);
+
+ // Check the specifier spelled in the source.
+ // If the resolved scope doesn't end with the spelled scope. The
+ // resolved scope can come from a sema typo correction. For example,
+ // sema assumes that "clangd::" is a typo of "clang::" and uses
+ // "clang::" as the specified scope in:
+ // namespace clang { clangd::X; }
+ // In this case, we use the "typo" specifier as extra scope instead
+ // of using the scope assumed by sema.
+ auto B = SM.getFileOffset(SS->getBeginLoc());
+ auto E = SM.getFileOffset(SS->getEndLoc());
+ std::string Spelling = (Code.substr(B, E - B) + "::").str();
+ if (llvm::StringRef(SpecifiedNS).endswith(Spelling))
+ Result.ResolvedScope = SpecifiedNS;
+ else
+ Result.UnresolvedScope = Spelling;
+ } else if (const auto *ANS = Nested->getAsNamespaceAlias()) {
+ Result.ResolvedScope = printNamespaceScope(*ANS->getNamespace());
+ } else {
+ // We don't fix symbols in scopes that are not top-level e.g. class
+ // members, as we don't collect includes for them.
+ return llvm::None;
+ }
+ }
+ }
+
+ if (UnresolvedIsSpecifier) {
+ // If the unresolved name is a specifier e.g.
+ // clang::clangd::X
+ // ~~~~~~
+ // We try to resolve clang::clangd::X instead of clang::clangd.
+ // FIXME: We won't be able to fix include if the specifier is what we
+ // should resolve (e.g. it's a class scope specifier). Collecting include
+ // headers for nested types could make this work.
+
+ // Not using the end location as it doesn't always point to the end of
+ // identifier.
+ if (auto QualifiedByUnresolved =
+ qualifiedByUnresolved(SM, Unresolved.getBeginLoc(), LangOpts)) {
+ auto Split = splitQualifiedName(*QualifiedByUnresolved);
+ if (!Result.UnresolvedScope)
+ Result.UnresolvedScope.emplace();
+ // If UnresolvedSpecifiedScope is already set, we simply append the
+ // extra scope. Suppose the unresolved name is "index" in the following
+ // example:
+ // namespace clang { clangd::index::X; }
+ // ~~~~~~ ~~~~~
+ // "clangd::" is assumed to be clang:: by Sema, and we would have used
+ // it as extra scope. With "index" being a specifier, we append "index::"
+ // to the extra scope.
+ Result.UnresolvedScope->append((Result.Name + Split.first).str());
+ Result.Name = Split.second;
+ }
+ }
+ return Result;
+}
+
+class IncludeFixer::UnresolvedNameRecorder : public ExternalSemaSource {
+public:
+ UnresolvedNameRecorder(llvm::Optional<UnresolvedName> &LastUnresolvedName)
+ : LastUnresolvedName(LastUnresolvedName) {}
+
+ void InitializeSema(Sema &S) override { this->SemaPtr = &S; }
+
+ // Captures the latest typo and treat it as an unresolved name that can
+ // potentially be fixed by adding #includes.
+ TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, int LookupKind,
+ Scope *S, CXXScopeSpec *SS,
+ CorrectionCandidateCallback &CCC,
+ DeclContext *MemberContext, bool EnteringContext,
+ const ObjCObjectPointerType *OPT) override {
+ assert(SemaPtr && "Sema must have been set.");
+ if (SemaPtr->isSFINAEContext())
+ return TypoCorrection();
+ if (!SemaPtr->SourceMgr.isWrittenInMainFile(Typo.getLoc()))
+ return clang::TypoCorrection();
+
+ // This is not done lazily because `SS` can get out of scope and it's
+ // relatively cheap.
+ auto Extracted = extractUnresolvedNameCheaply(
+ SemaPtr->SourceMgr, Typo, SS, SemaPtr->LangOpts,
+ static_cast<Sema::LookupNameKind>(LookupKind) ==
+ Sema::LookupNameKind::LookupNestedNameSpecifierName);
+ if (!Extracted)
+ return TypoCorrection();
+ auto CheapUnresolved = std::move(*Extracted);
+ UnresolvedName Unresolved;
+ Unresolved.Name = CheapUnresolved.Name;
+ Unresolved.Loc = Typo.getBeginLoc();
+
+ if (!CheapUnresolved.ResolvedScope && !S) // Give up if no scope available.
+ return TypoCorrection();
+
+ auto *Sem = SemaPtr; // Avoid capturing `this`.
+ Unresolved.GetScopes = [Sem, CheapUnresolved, S, LookupKind]() {
+ std::vector<std::string> Scopes;
+ if (CheapUnresolved.ResolvedScope) {
+ Scopes.push_back(*CheapUnresolved.ResolvedScope);
+ } else {
+ assert(S);
+ // No scope specifier is specified. Collect all accessible scopes in the
+ // context.
+ VisitedContextCollector Collector;
+ Sem->LookupVisibleDecls(
+ S, static_cast<Sema::LookupNameKind>(LookupKind), Collector,
+ /*IncludeGlobalScope=*/false,
+ /*LoadExternal=*/false);
+
+ Scopes.push_back("");
+ for (const auto *Ctx : Collector.takeVisitedContexts())
+ if (isa<NamespaceDecl>(Ctx))
+ Scopes.push_back(printNamespaceScope(*Ctx));
+ }
+
+ if (CheapUnresolved.UnresolvedScope)
+ for (auto &Scope : Scopes)
+ Scope.append(*CheapUnresolved.UnresolvedScope);
+ return Scopes;
+ };
+ LastUnresolvedName = std::move(Unresolved);
+
+ // Never return a valid correction to try to recover. Our suggested fixes
+ // always require a rebuild.
+ return TypoCorrection();
+ }
+
+private:
+ Sema *SemaPtr = nullptr;
+
+ llvm::Optional<UnresolvedName> &LastUnresolvedName;
+};
+
+llvm::IntrusiveRefCntPtr<ExternalSemaSource>
+IncludeFixer::unresolvedNameRecorder() {
+ return new UnresolvedNameRecorder(LastUnresolvedName);
+}
+
+std::vector<Fix> IncludeFixer::fixUnresolvedName() const {
+ assert(LastUnresolvedName.hasValue());
+ auto &Unresolved = *LastUnresolvedName;
+ std::vector<std::string> Scopes = Unresolved.GetScopes();
+ vlog("Trying to fix unresolved name \"{0}\" in scopes: [{1}]",
+ Unresolved.Name, llvm::join(Scopes.begin(), Scopes.end(), ", "));
+
+ FuzzyFindRequest Req;
+ Req.AnyScope = false;
+ Req.Query = Unresolved.Name;
+ Req.Scopes = Scopes;
+ Req.RestrictForCodeCompletion = true;
+ Req.Limit = 100;
+
+ if (llvm::Optional<const SymbolSlab *> Syms = fuzzyFindCached(Req))
+ return fixesForSymbols(**Syms);
+
+ return {};
+}
+
+
+llvm::Optional<const SymbolSlab *>
+IncludeFixer::fuzzyFindCached(const FuzzyFindRequest &Req) const {
+ auto ReqStr = llvm::formatv("{0}", toJSON(Req)).str();
+ auto I = FuzzyFindCache.find(ReqStr);
+ if (I != FuzzyFindCache.end())
+ return &I->second;
+
+ if (IndexRequestCount >= IndexRequestLimit)
+ return llvm::None;
+ IndexRequestCount++;
+
+ SymbolSlab::Builder Matches;
+ Index.fuzzyFind(Req, [&](const Symbol &Sym) {
+ if (Sym.Name != Req.Query)
+ return;
+ if (!Sym.IncludeHeaders.empty())
+ Matches.insert(Sym);
+ });
+ auto Syms = std::move(Matches).build();
+ auto E = FuzzyFindCache.try_emplace(ReqStr, std::move(Syms));
+ return &E.first->second;
+}
+
+llvm::Optional<const SymbolSlab *>
+IncludeFixer::lookupCached(const SymbolID &ID) const {
+ LookupRequest Req;
+ Req.IDs.insert(ID);
+
+ auto I = LookupCache.find(ID);
+ if (I != LookupCache.end())
+ return &I->second;
+
+ if (IndexRequestCount >= IndexRequestLimit)
+ return llvm::None;
+ IndexRequestCount++;
+
+ // FIXME: consider batching the requests for all diagnostics.
+ SymbolSlab::Builder Matches;
+ Index.lookup(Req, [&](const Symbol &Sym) { Matches.insert(Sym); });
+ auto Syms = std::move(Matches).build();
+
+ std::vector<Fix> Fixes;
+ if (!Syms.empty()) {
+ auto &Matched = *Syms.begin();
+ if (!Matched.IncludeHeaders.empty() && Matched.Definition &&
+ Matched.CanonicalDeclaration.FileURI == Matched.Definition.FileURI)
+ Fixes = fixesForSymbols(Syms);
+ }
+ auto E = LookupCache.try_emplace(ID, std::move(Syms));
+ return &E.first->second;
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/clangd/IncludeFixer.h b/clangd/IncludeFixer.h
new file mode 100644
index 00000000..aafb384b
--- /dev/null
+++ b/clangd/IncludeFixer.h
@@ -0,0 +1,100 @@
+//===--- IncludeFixer.h ------------------------------------------*- 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_CLANGD_INCLUDE_FIXER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDE_FIXER_H
+
+#include "Diagnostics.h"
+#include "Headers.h"
+#include "index/Index.h"
+#include "index/Symbol.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <memory>
+
+namespace clang {
+namespace clangd {
+
+/// Attempts to recover from error diagnostics by suggesting include insertion
+/// fixes. For example, member access into incomplete type can be fixes by
+/// include headers with the definition.
+class IncludeFixer {
+public:
+ IncludeFixer(llvm::StringRef File, std::shared_ptr<IncludeInserter> Inserter,
+ const SymbolIndex &Index, unsigned IndexRequestLimit)
+ : File(File), Inserter(std::move(Inserter)), Index(Index),
+ IndexRequestLimit(IndexRequestLimit) {}
+
+ /// Returns include insertions that can potentially recover the diagnostic.
+ std::vector<Fix> fix(DiagnosticsEngine::Level DiagLevel,
+ const clang::Diagnostic &Info) const;
+
+ /// Returns an ExternalSemaSource that records failed name lookups in Sema.
+ /// This allows IncludeFixer to suggest inserting headers that define those
+ /// names.
+ llvm::IntrusiveRefCntPtr<ExternalSemaSource> unresolvedNameRecorder();
+
+private:
+ /// Attempts to recover diagnostic caused by an incomplete type \p T.
+ std::vector<Fix> fixIncompleteType(const Type &T) const;
+
+ /// Generates header insertion fixes for all symbols. Fixes are deduplicated.
+ std::vector<Fix> fixesForSymbols(const SymbolSlab &Syms) const;
+
+ struct UnresolvedName {
+ std::string Name; // E.g. "X" in foo::X.
+ SourceLocation Loc; // Start location of the unresolved name.
+ // Lazily get the possible scopes of the unresolved name. `Sema` must be
+ // alive when this is called.
+ std::function<std::vector<std::string>()> GetScopes;
+ };
+
+ /// Records the last unresolved name seen by Sema.
+ class UnresolvedNameRecorder;
+
+ /// Attempts to fix the unresolved name associated with the current
+ /// diagnostic. We assume a diagnostic is caused by a unresolved name when
+ /// they have the same source location and the unresolved name is the last
+ /// one we've seen during the Sema run.
+ std::vector<Fix> fixUnresolvedName() const;
+
+ std::string File;
+ std::shared_ptr<IncludeInserter> Inserter;
+ const SymbolIndex &Index;
+ const unsigned IndexRequestLimit; // Make at most 5 index requests.
+ mutable unsigned IndexRequestCount = 0;
+
+ // These collect the last unresolved name so that we can associate it with the
+ // diagnostic.
+ llvm::Optional<UnresolvedName> LastUnresolvedName;
+
+ // There can be multiple diagnostics that are caused by the same unresolved
+ // name or incomplete type in one parse, especially when code is
+ // copy-and-pasted without #includes. We cache the index results based on
+ // index requests.
+ mutable llvm::StringMap<SymbolSlab> FuzzyFindCache;
+ mutable llvm::DenseMap<SymbolID, SymbolSlab> LookupCache;
+ // Returns None if the number of index requests has reached the limit.
+ llvm::Optional<const SymbolSlab *>
+ fuzzyFindCached(const FuzzyFindRequest &Req) const;
+ llvm::Optional<const SymbolSlab *> lookupCached(const SymbolID &ID) const;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDE_FIXER_H
diff --git a/clangd/JSONTransport.cpp b/clangd/JSONTransport.cpp
index 7189b23c..17310777 100644
--- a/clangd/JSONTransport.cpp
+++ b/clangd/JSONTransport.cpp
@@ -1,9 +1,8 @@
//===--- JSONTransport.cpp - sending and receiving LSP messages over JSON -===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "Logger.h"
diff --git a/clangd/Logger.cpp b/clangd/Logger.cpp
index 9d4e7b93..7b8c9a3e 100644
--- a/clangd/Logger.cpp
+++ b/clangd/Logger.cpp
@@ -1,9 +1,8 @@
//===--- Logger.cpp - Logger interface for clangd -------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/Logger.h b/clangd/Logger.h
index 8572ca15..7a5d5140 100644
--- a/clangd/Logger.h
+++ b/clangd/Logger.h
@@ -1,9 +1,8 @@
//===--- Logger.h - Logger interface for clangd ------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/Path.h b/clangd/Path.h
index b4c93357..eaa72245 100644
--- a/clangd/Path.h
+++ b/clangd/Path.h
@@ -1,9 +1,8 @@
//===--- Path.h - Helper typedefs --------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/Protocol.cpp b/clangd/Protocol.cpp
index cf3c6fd3..a8b1c437 100644
--- a/clangd/Protocol.cpp
+++ b/clangd/Protocol.cpp
@@ -1,9 +1,8 @@
//===--- Protocol.cpp - Language Server Protocol Implementation -----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -14,10 +13,10 @@
#include "Protocol.h"
#include "Logger.h"
#include "URI.h"
-#include "index/Index.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/JSON.h"
@@ -213,6 +212,61 @@ SymbolKind adjustKindToCapability(SymbolKind Kind,
}
}
+SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind) {
+ switch (Kind) {
+ case index::SymbolKind::Unknown:
+ return SymbolKind::Variable;
+ case index::SymbolKind::Module:
+ return SymbolKind::Module;
+ case index::SymbolKind::Namespace:
+ return SymbolKind::Namespace;
+ case index::SymbolKind::NamespaceAlias:
+ return SymbolKind::Namespace;
+ case index::SymbolKind::Macro:
+ return SymbolKind::String;
+ case index::SymbolKind::Enum:
+ return SymbolKind::Enum;
+ case index::SymbolKind::Struct:
+ return SymbolKind::Struct;
+ case index::SymbolKind::Class:
+ return SymbolKind::Class;
+ case index::SymbolKind::Protocol:
+ return SymbolKind::Interface;
+ case index::SymbolKind::Extension:
+ return SymbolKind::Interface;
+ case index::SymbolKind::Union:
+ return SymbolKind::Class;
+ case index::SymbolKind::TypeAlias:
+ return SymbolKind::Class;
+ case index::SymbolKind::Function:
+ return SymbolKind::Function;
+ case index::SymbolKind::Variable:
+ return SymbolKind::Variable;
+ case index::SymbolKind::Field:
+ return SymbolKind::Field;
+ case index::SymbolKind::EnumConstant:
+ return SymbolKind::EnumMember;
+ case index::SymbolKind::InstanceMethod:
+ case index::SymbolKind::ClassMethod:
+ case index::SymbolKind::StaticMethod:
+ return SymbolKind::Method;
+ case index::SymbolKind::InstanceProperty:
+ case index::SymbolKind::ClassProperty:
+ case index::SymbolKind::StaticProperty:
+ return SymbolKind::Property;
+ case index::SymbolKind::Constructor:
+ case index::SymbolKind::Destructor:
+ return SymbolKind::Method;
+ case index::SymbolKind::ConversionFunction:
+ return SymbolKind::Function;
+ case index::SymbolKind::Parameter:
+ return SymbolKind::Variable;
+ case index::SymbolKind::Using:
+ return SymbolKind::Namespace;
+ }
+ llvm_unreachable("invalid symbol kind");
+}
+
bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R) {
const llvm::json::Object *O = Params.getAsObject();
if (!O)
@@ -223,6 +277,8 @@ bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R) {
R.DiagnosticCategory = *CategorySupport;
if (auto CodeActions = Diagnostics->getBoolean("codeActionsInline"))
R.DiagnosticFixes = *CodeActions;
+ if (auto RelatedInfo = Diagnostics->getBoolean("relatedInformation"))
+ R.DiagnosticRelatedInformation = *RelatedInfo;
}
if (auto *Completion = TextDocument->getObject("completion")) {
if (auto *Item = Completion->getObject("completionItem")) {
@@ -258,6 +314,11 @@ bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R) {
}
}
}
+ if (auto *OffsetEncoding = O->get("offsetEncoding")) {
+ R.offsetEncoding.emplace();
+ if (!fromJSON(*OffsetEncoding, *R.offsetEncoding))
+ return false;
+ }
return true;
}
@@ -360,6 +421,13 @@ bool fromJSON(const llvm::json::Value &Params, DocumentSymbolParams &R) {
return O && O.map("textDocument", R.textDocument);
}
+llvm::json::Value toJSON(const DiagnosticRelatedInformation &DRI) {
+ return llvm::json::Object{
+ {"location", DRI.location},
+ {"message", DRI.message},
+ };
+}
+
llvm::json::Value toJSON(const Diagnostic &D) {
llvm::json::Object Diag{
{"range", D.range},
@@ -370,6 +438,12 @@ llvm::json::Value toJSON(const Diagnostic &D) {
Diag["category"] = *D.category;
if (D.codeActions)
Diag["codeActions"] = D.codeActions;
+ if (!D.code.empty())
+ Diag["code"] = D.code;
+ if (!D.source.empty())
+ Diag["source"] = D.source;
+ if (D.relatedInformation)
+ Diag["relatedInformation"] = *D.relatedInformation;
return std::move(Diag);
}
@@ -379,6 +453,8 @@ bool fromJSON(const llvm::json::Value &Params, Diagnostic &R) {
return false;
O.map("severity", R.severity);
O.map("category", R.category);
+ O.map("code", R.code);
+ O.map("source", R.source);
return true;
}
@@ -422,6 +498,9 @@ bool fromJSON(const llvm::json::Value &Params, WorkspaceEdit &R) {
const llvm::StringLiteral ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND =
"clangd.applyFix";
+const llvm::StringLiteral ExecuteCommandParams::CLANGD_APPLY_TWEAK =
+ "clangd.applyTweak";
+
bool fromJSON(const llvm::json::Value &Params, ExecuteCommandParams &R) {
llvm::json::ObjectMapper O(Params);
if (!O || !O.map("command", R.command))
@@ -432,6 +511,8 @@ bool fromJSON(const llvm::json::Value &Params, ExecuteCommandParams &R) {
return Args && Args->size() == 1 &&
fromJSON(Args->front(), R.workspaceEdit);
}
+ if (R.command == ExecuteCommandParams::CLANGD_APPLY_TWEAK)
+ return Args && Args->size() == 1 && fromJSON(Args->front(), R.tweakArgs);
return false; // Unrecognized command.
}
@@ -456,25 +537,25 @@ bool operator==(const SymbolDetails &LHS, const SymbolDetails &RHS) {
}
llvm::json::Value toJSON(const SymbolDetails &P) {
- llvm::json::Object result{{"name", llvm::json::Value(nullptr)},
+ llvm::json::Object Result{{"name", llvm::json::Value(nullptr)},
{"containerName", llvm::json::Value(nullptr)},
{"usr", llvm::json::Value(nullptr)},
{"id", llvm::json::Value(nullptr)}};
if (!P.name.empty())
- result["name"] = P.name;
+ Result["name"] = P.name;
if (!P.containerName.empty())
- result["containerName"] = P.containerName;
+ Result["containerName"] = P.containerName;
if (!P.USR.empty())
- result["usr"] = P.USR;
+ Result["usr"] = P.USR;
if (P.ID.hasValue())
- result["id"] = P.ID.getValue().str();
+ Result["id"] = P.ID.getValue().str();
// Older clang cannot compile 'return Result', even though it is legal.
- return llvm::json::Value(std::move(result));
+ return llvm::json::Value(std::move(Result));
}
llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const SymbolDetails &S) {
@@ -498,10 +579,13 @@ llvm::json::Value toJSON(const Command &C) {
auto Cmd = llvm::json::Object{{"title", C.title}, {"command", C.command}};
if (C.workspaceEdit)
Cmd["arguments"] = {*C.workspaceEdit};
+ if (C.tweakArgs)
+ Cmd["arguments"] = {*C.tweakArgs};
return std::move(Cmd);
}
const llvm::StringLiteral CodeAction::QUICKFIX_KIND = "quickfix";
+const llvm::StringLiteral CodeAction::REFACTOR_KIND = "refactor";
llvm::json::Value toJSON(const CodeAction &CA) {
auto CodeAction = llvm::json::Object{{"title", CA.title}};
@@ -545,6 +629,17 @@ llvm::json::Value toJSON(const WorkspaceEdit &WE) {
return llvm::json::Object{{"changes", std::move(FileChanges)}};
}
+bool fromJSON(const llvm::json::Value &Params, TweakArgs &A) {
+ llvm::json::ObjectMapper O(Params);
+ return O && O.map("file", A.file) && O.map("selection", A.selection) &&
+ O.map("tweakID", A.tweakID);
+}
+
+llvm::json::Value toJSON(const TweakArgs &A) {
+ return llvm::json::Object{
+ {"tweakID", A.tweakID}, {"selection", A.selection}, {"file", A.file}};
+}
+
llvm::json::Value toJSON(const ApplyWorkspaceEditParams &Params) {
return llvm::json::Object{{"edit", Params.edit}};
}
@@ -560,10 +655,10 @@ bool fromJSON(const llvm::json::Value &Params, CompletionContext &R) {
if (!O)
return false;
- int triggerKind;
- if (!O.map("triggerKind", triggerKind))
+ int TriggerKind;
+ if (!O.map("triggerKind", TriggerKind))
return false;
- R.triggerKind = static_cast<CompletionTriggerKind>(triggerKind);
+ R.triggerKind = static_cast<CompletionTriggerKind>(TriggerKind);
if (auto *TC = Params.getAsObject()->get("triggerCharacter"))
return fromJSON(*TC, R.triggerCharacter);
@@ -620,11 +715,11 @@ bool fromJSON(const llvm::json::Value &E, CompletionItemKind &Out) {
CompletionItemKind
adjustKindToCapability(CompletionItemKind Kind,
- CompletionItemKindBitset &supportedCompletionItemKinds) {
+ CompletionItemKindBitset &SupportedCompletionItemKinds) {
auto KindVal = static_cast<size_t>(Kind);
if (KindVal >= CompletionItemKindMin &&
- KindVal <= supportedCompletionItemKinds.size() &&
- supportedCompletionItemKinds[KindVal])
+ KindVal <= SupportedCompletionItemKinds.size() &&
+ SupportedCompletionItemKinds[KindVal])
return Kind;
switch (Kind) {
@@ -795,10 +890,99 @@ bool fromJSON(const llvm::json::Value &Params, InitializationOptions &Opts) {
return true;
}
+bool fromJSON(const llvm::json::Value &E, TypeHierarchyDirection &Out) {
+ auto T = E.getAsInteger();
+ if (!T)
+ return false;
+ if (*T < static_cast<int>(TypeHierarchyDirection::Children) ||
+ *T > static_cast<int>(TypeHierarchyDirection::Both))
+ return false;
+ Out = static_cast<TypeHierarchyDirection>(*T);
+ return true;
+}
+
+bool fromJSON(const llvm::json::Value &Params, TypeHierarchyParams &R) {
+ llvm::json::ObjectMapper O(Params);
+ return O && O.map("textDocument", R.textDocument) &&
+ O.map("position", R.position) && O.map("resolve", R.resolve) &&
+ O.map("direction", R.direction);
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
+ const TypeHierarchyItem &I) {
+ return O << I.name << " - " << toJSON(I);
+}
+
+llvm::json::Value toJSON(const TypeHierarchyItem &I) {
+ llvm::json::Object Result{{"name", I.name},
+ {"kind", static_cast<int>(I.kind)},
+ {"range", I.range},
+ {"selectionRange", I.selectionRange},
+ {"uri", I.uri}};
+
+ if (I.detail)
+ Result["detail"] = I.detail;
+ if (I.deprecated)
+ Result["deprecated"] = I.deprecated;
+ if (I.parents)
+ Result["parents"] = I.parents;
+ if (I.children)
+ Result["children"] = I.children;
+ return std::move(Result);
+}
+
+bool fromJSON(const llvm::json::Value &Params, TypeHierarchyItem &I) {
+ llvm::json::ObjectMapper O(Params);
+
+ // Required fields.
+ if (!(O && O.map("name", I.name) && O.map("kind", I.kind) &&
+ O.map("uri", I.uri) && O.map("range", I.range) &&
+ O.map("selectionRange", I.selectionRange))) {
+ return false;
+ }
+
+ // Optional fields.
+ O.map("detail", I.detail);
+ O.map("deprecated", I.deprecated);
+ O.map("parents", I.parents);
+ O.map("children", I.children);
+
+ return true;
+}
+
bool fromJSON(const llvm::json::Value &Params, ReferenceParams &R) {
TextDocumentPositionParams &Base = R;
return fromJSON(Params, Base);
}
+static const char *toString(OffsetEncoding OE) {
+ switch (OE) {
+ case OffsetEncoding::UTF8:
+ return "utf-8";
+ case OffsetEncoding::UTF16:
+ return "utf-16";
+ case OffsetEncoding::UTF32:
+ return "utf-32";
+ case OffsetEncoding::UnsupportedEncoding:
+ return "unknown";
+ }
+ llvm_unreachable("Unknown clang.clangd.OffsetEncoding");
+}
+llvm::json::Value toJSON(const OffsetEncoding &OE) { return toString(OE); }
+bool fromJSON(const llvm::json::Value &V, OffsetEncoding &OE) {
+ auto Str = V.getAsString();
+ if (!Str)
+ return false;
+ OE = llvm::StringSwitch<OffsetEncoding>(*Str)
+ .Case("utf-8", OffsetEncoding::UTF8)
+ .Case("utf-16", OffsetEncoding::UTF16)
+ .Case("utf-32", OffsetEncoding::UTF32)
+ .Default(OffsetEncoding::UnsupportedEncoding);
+ return true;
+}
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, OffsetEncoding Enc) {
+ return OS << toString(Enc);
+}
+
} // namespace clangd
} // namespace clang
diff --git a/clangd/Protocol.h b/clangd/Protocol.h
index 17b69bde..957e2f3d 100644
--- a/clangd/Protocol.h
+++ b/clangd/Protocol.h
@@ -1,9 +1,8 @@
//===--- Protocol.h - Language Server Protocol Implementation ---*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -26,8 +25,10 @@
#include "URI.h"
#include "index/SymbolID.h"
+#include "clang/Index/IndexSymbol.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/JSON.h"
+#include "llvm/Support/raw_ostream.h"
#include <bitset>
#include <string>
#include <vector>
@@ -205,11 +206,10 @@ struct TextEdit {
/// The string to be inserted. For delete operations use an
/// empty string.
std::string newText;
-
- bool operator==(const TextEdit &rhs) const {
- return newText == rhs.newText && range == rhs.range;
- }
};
+inline bool operator==(const TextEdit &L, const TextEdit &R) {
+ return std::tie(L.newText, L.range) == std::tie(R.newText, R.range);
+}
bool fromJSON(const llvm::json::Value &, TextEdit &);
llvm::json::Value toJSON(const TextEdit &);
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const TextEdit &);
@@ -293,7 +293,7 @@ using CompletionItemKindBitset = std::bitset<CompletionItemKindMax + 1>;
bool fromJSON(const llvm::json::Value &, CompletionItemKindBitset &);
CompletionItemKind
adjustKindToCapability(CompletionItemKind Kind,
- CompletionItemKindBitset &supportedCompletionItemKinds);
+ CompletionItemKindBitset &SupportedCompletionItemKinds);
/// A symbol kind.
enum class SymbolKind {
@@ -332,6 +332,27 @@ bool fromJSON(const llvm::json::Value &, SymbolKindBitset &);
SymbolKind adjustKindToCapability(SymbolKind Kind,
SymbolKindBitset &supportedSymbolKinds);
+// Convert a index::SymbolKind to clangd::SymbolKind (LSP)
+// Note, some are not perfect matches and should be improved when this LSP
+// issue is addressed:
+// https://github.com/Microsoft/language-server-protocol/issues/344
+SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind);
+
+// Determines the encoding used to measure offsets and lengths of source in LSP.
+enum class OffsetEncoding {
+ // Any string is legal on the wire. Unrecognized encodings parse as this.
+ UnsupportedEncoding,
+ // Length counts code units of UTF-16 encoded text. (Standard LSP behavior).
+ UTF16,
+ // Length counts bytes of UTF-8 encoded text. (Clangd extension).
+ UTF8,
+ // Length counts codepoints in unicode text. (Clangd extension).
+ UTF32,
+};
+llvm::json::Value toJSON(const OffsetEncoding &);
+bool fromJSON(const llvm::json::Value &, OffsetEncoding &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, OffsetEncoding);
+
// This struct doesn't mirror LSP!
// The protocol defines deeply nested structures for client capabilities.
// Instead of mapping them all, this just parses out the bits we care about.
@@ -344,6 +365,10 @@ struct ClientCapabilities {
/// textDocument.publishDiagnostics.codeActionsInline.
bool DiagnosticFixes = false;
+ /// Whether the client accepts diagnostics with related locations.
+ /// textDocument.publishDiagnostics.relatedInformation.
+ bool DiagnosticRelatedInformation = false;
+
/// Whether the client accepts diagnostics with category attached to it
/// using the "category" extension.
/// textDocument.publishDiagnostics.categorySupport
@@ -363,6 +388,9 @@ struct ClientCapabilities {
/// Client supports CodeAction return value for textDocument/codeAction.
/// textDocument.codeAction.codeActionLiteralSupport.
bool CodeActionStructure = false;
+
+ /// Supported encodings for LSP character offsets. (clangd extension).
+ llvm::Optional<std::vector<OffsetEncoding>> offsetEncoding;
};
bool fromJSON(const llvm::json::Value &, ClientCapabilities &);
@@ -557,6 +585,18 @@ struct DocumentSymbolParams {
};
bool fromJSON(const llvm::json::Value &, DocumentSymbolParams &);
+
+/// Represents a related message and source code location for a diagnostic.
+/// This should be used to point to code locations that cause or related to a
+/// diagnostics, e.g when duplicating a symbol in a scope.
+struct DiagnosticRelatedInformation {
+ /// The location of this related diagnostic information.
+ Location location;
+ /// The message of this related diagnostic information.
+ std::string message;
+};
+llvm::json::Value toJSON(const DiagnosticRelatedInformation &);
+
struct CodeAction;
struct Diagnostic {
/// The range at which the message applies.
@@ -567,17 +607,19 @@ struct Diagnostic {
int severity = 0;
/// The diagnostic's code. Can be omitted.
- /// Note: Not currently used by clangd
- // std::string code;
+ std::string code;
/// A human-readable string describing the source of this
/// diagnostic, e.g. 'typescript' or 'super lint'.
- /// Note: Not currently used by clangd
- // std::string source;
+ std::string source;
/// The diagnostic's message.
std::string message;
+ /// An array of related diagnostic information, e.g. when symbol-names within
+ /// a scope collide all definitions can be marked via this property.
+ llvm::Optional<std::vector<DiagnosticRelatedInformation>> relatedInformation;
+
/// The diagnostic's category. Can be omitted.
/// An LSP extension that's used to send the name of the category over to the
/// client. The category typically describes the compilation stage during
@@ -632,6 +674,21 @@ struct WorkspaceEdit {
bool fromJSON(const llvm::json::Value &, WorkspaceEdit &);
llvm::json::Value toJSON(const WorkspaceEdit &WE);
+/// Arguments for the 'applyTweak' command. The server sends these commands as a
+/// response to the textDocument/codeAction request. The client can later send a
+/// command back to the server if the user requests to execute a particular code
+/// tweak.
+struct TweakArgs {
+ /// A file provided by the client on a textDocument/codeAction request.
+ URIForFile file;
+ /// A selection provided by the client on a textDocument/codeAction request.
+ Range selection;
+ /// ID of the tweak that should be executed. Corresponds to Tweak::id().
+ std::string tweakID;
+};
+bool fromJSON(const llvm::json::Value &, TweakArgs &);
+llvm::json::Value toJSON(const TweakArgs &A);
+
/// Exact commands are not specified in the protocol so we define the
/// ones supported by Clangd here. The protocol specifies the command arguments
/// to be "any[]" but to make this safer and more manageable, each command we
@@ -643,12 +700,15 @@ llvm::json::Value toJSON(const WorkspaceEdit &WE);
struct ExecuteCommandParams {
// Command to apply fix-its. Uses WorkspaceEdit as argument.
const static llvm::StringLiteral CLANGD_APPLY_FIX_COMMAND;
+ // Command to apply the code action. Uses TweakArgs as argument.
+ const static llvm::StringLiteral CLANGD_APPLY_TWEAK;
/// The command identifier, e.g. CLANGD_APPLY_FIX_COMMAND
std::string command;
// Arguments
llvm::Optional<WorkspaceEdit> workspaceEdit;
+ llvm::Optional<TweakArgs> tweakArgs;
};
bool fromJSON(const llvm::json::Value &, ExecuteCommandParams &);
@@ -670,6 +730,7 @@ struct CodeAction {
/// Used to filter code actions.
llvm::Optional<std::string> kind;
const static llvm::StringLiteral QUICKFIX_KIND;
+ const static llvm::StringLiteral REFACTOR_KIND;
/// The diagnostics that this code action resolves.
llvm::Optional<std::vector<Diagnostic>> diagnostics;
@@ -996,6 +1057,67 @@ struct DocumentHighlight {
llvm::json::Value toJSON(const DocumentHighlight &DH);
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const DocumentHighlight &);
+enum class TypeHierarchyDirection { Children = 0, Parents = 1, Both = 2 };
+bool fromJSON(const llvm::json::Value &E, TypeHierarchyDirection &Out);
+
+/// The type hierarchy params is an extension of the
+/// `TextDocumentPositionsParams` with optional properties which can be used to
+/// eagerly resolve the item when requesting from the server.
+struct TypeHierarchyParams : public TextDocumentPositionParams {
+ /// The hierarchy levels to resolve. `0` indicates no level.
+ int resolve = 0;
+
+ /// The direction of the hierarchy levels to resolve.
+ TypeHierarchyDirection direction = TypeHierarchyDirection::Parents;
+};
+bool fromJSON(const llvm::json::Value &, TypeHierarchyParams &);
+
+struct TypeHierarchyItem {
+ /// The human readable name of the hierarchy item.
+ std::string name;
+
+ /// Optional detail for the hierarchy item. It can be, for instance, the
+ /// signature of a function or method.
+ llvm::Optional<std::string> detail;
+
+ /// The kind of the hierarchy item. For instance, class or interface.
+ SymbolKind kind;
+
+ /// `true` if the hierarchy item is deprecated. Otherwise, `false`.
+ bool deprecated;
+
+ /// The URI of the text document where this type hierarchy item belongs to.
+ URIForFile uri;
+
+ /// The range enclosing this type hierarchy item not including
+ /// leading/trailing whitespace but everything else like comments. This
+ /// information is typically used to determine if the client's cursor is
+ /// inside the type hierarch item to reveal in the symbol in the UI.
+ Range range;
+
+ /// The range that should be selected and revealed when this type hierarchy
+ /// item is being picked, e.g. the name of a function. Must be contained by
+ /// the `range`.
+ Range selectionRange;
+
+ /// If this type hierarchy item is resolved, it contains the direct parents.
+ /// Could be empty if the item does not have direct parents. If not defined,
+ /// the parents have not been resolved yet.
+ llvm::Optional<std::vector<TypeHierarchyItem>> parents;
+
+ /// If this type hierarchy item is resolved, it contains the direct children
+ /// of the current item. Could be empty if the item does not have any
+ /// descendants. If not defined, the children have not been resolved.
+ llvm::Optional<std::vector<TypeHierarchyItem>> children;
+
+ /// The protocol has a slot here for an optional 'data' filed, which can
+ /// be used to identify a type hierarchy item in a resolve request. We don't
+ /// need this (the item itself is sufficient to identify what to resolve)
+ /// so don't declare it.
+};
+llvm::json::Value toJSON(const TypeHierarchyItem &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const TypeHierarchyItem &);
+
struct ReferenceParams : public TextDocumentPositionParams {
// For now, no options like context.includeDeclaration are supported.
};
diff --git a/clangd/Quality.cpp b/clangd/Quality.cpp
index cef35c4c..6307006c 100644
--- a/clangd/Quality.cpp
+++ b/clangd/Quality.cpp
@@ -1,16 +1,16 @@
//===--- Quality.cpp ---------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "Quality.h"
#include "AST.h"
#include "FileDistance.h"
#include "URI.h"
-#include "index/Index.h"
+#include "index/Symbol.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
@@ -283,12 +283,12 @@ computeScope(const NamedDecl *D) {
}
void SymbolRelevanceSignals::merge(const Symbol &IndexResult) {
- // FIXME: Index results always assumed to be at global scope. If Scope becomes
- // relevant to non-completion requests, we should recognize class members etc.
-
SymbolURI = IndexResult.CanonicalDeclaration.FileURI;
SymbolScope = IndexResult.Scope;
IsInstanceMember |= isInstanceMember(IndexResult.SymInfo);
+ if (!(IndexResult.Flags & Symbol::VisibleOutsideFile)) {
+ Scope = AccessibleScope::FileScope;
+ }
}
void SymbolRelevanceSignals::merge(const CodeCompletionResult &SemaCCResult) {
@@ -336,6 +336,15 @@ static float scopeBoost(ScopeDistance &Distance,
return std::max(0.65, 2.0 * std::pow(0.6, D / 2.0));
}
+static llvm::Optional<llvm::StringRef>
+wordMatching(llvm::StringRef Name, const llvm::StringSet<> *ContextWords) {
+ if (ContextWords)
+ for (const auto& Word : ContextWords->keys())
+ if (Name.contains_lower(Word))
+ return Word;
+ return llvm::None;
+}
+
float SymbolRelevanceSignals::evaluate() const {
float Score = 1;
@@ -357,6 +366,9 @@ float SymbolRelevanceSignals::evaluate() const {
Score *=
SemaSaysInScope ? 2.0 : scopeBoost(*ScopeProximityMatch, SymbolScope);
+ if (wordMatching(Name, ContextWords))
+ Score *= 1.5;
+
// Symbols like local variables may only be referenced within their scope.
// Conversely if we're in that scope, it's likely we'll reference them.
if (Query == CodeComplete) {
@@ -366,7 +378,7 @@ float SymbolRelevanceSignals::evaluate() const {
case GlobalScope:
break;
case FileScope:
- Score *= 1.5;
+ Score *= 1.5f;
break;
case ClassScope:
Score *= 2;
@@ -375,6 +387,19 @@ float SymbolRelevanceSignals::evaluate() const {
Score *= 4;
break;
}
+ } else {
+ // For non-completion queries, the wider the scope where a symbol is
+ // visible, the more likely it is to be relevant.
+ switch (Scope) {
+ case GlobalScope:
+ break;
+ case FileScope:
+ Score *= 0.5f;
+ break;
+ default:
+ // TODO: Handle other scopes as we start to use them for index results.
+ break;
+ }
}
if (TypeMatchesPreferred)
@@ -400,7 +425,12 @@ float SymbolRelevanceSignals::evaluate() const {
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
const SymbolRelevanceSignals &S) {
OS << llvm::formatv("=== Symbol relevance: {0}\n", S.evaluate());
+ OS << llvm::formatv("\tName: {0}\n", S.Name);
OS << llvm::formatv("\tName match: {0}\n", S.NameMatch);
+ if (S.ContextWords)
+ OS << llvm::formatv(
+ "\tMatching context word: {0}\n",
+ wordMatching(S.Name, S.ContextWords).getValueOr("<none>"));
OS << llvm::formatv("\tForbidden: {0}\n", S.Forbidden);
OS << llvm::formatv("\tNeedsFixIts: {0}\n", S.NeedsFixIts);
OS << llvm::formatv("\tIsInstanceMember: {0}\n", S.IsInstanceMember);
diff --git a/clangd/Quality.h b/clangd/Quality.h
index 9cb0c2f3..b358a919 100644
--- a/clangd/Quality.h
+++ b/clangd/Quality.h
@@ -1,9 +1,8 @@
//===--- Quality.h - Ranking alternatives for ambiguous queries --*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
@@ -33,13 +32,14 @@
#include "clang/Sema/CodeCompleteConsumer.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include <algorithm>
#include <functional>
#include <vector>
namespace llvm {
class raw_ostream;
-}
+} // namespace llvm
namespace clang {
class CodeCompletionResult;
@@ -85,8 +85,12 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &,
/// Attributes of a symbol-query pair that affect how much we like it.
struct SymbolRelevanceSignals {
+ /// The name of the symbol (for ContextWords). Must be explicitly assigned.
+ llvm::StringRef Name;
/// 0-1+ fuzzy-match score for unqualified name. Must be explicitly assigned.
float NameMatch = 1;
+ /// Lowercase words relevant to the context (e.g. near the completion point).
+ llvm::StringSet<>* ContextWords = nullptr;
bool Forbidden = false; // Unavailable (e.g const) or inaccessible (private).
/// Whether fixits needs to be applied for that completion or not.
bool NeedsFixIts = false;
diff --git a/clangd/RIFF.cpp b/clangd/RIFF.cpp
index c0bf7855..cdbae4f7 100644
--- a/clangd/RIFF.cpp
+++ b/clangd/RIFF.cpp
@@ -1,9 +1,8 @@
//===--- RIFF.cpp - Binary container file format --------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/RIFF.h b/clangd/RIFF.h
index f56d0879..d827a90f 100644
--- a/clangd/RIFF.h
+++ b/clangd/RIFF.h
@@ -1,9 +1,8 @@
//===--- RIFF.h - Binary container file format -------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clangd/Selection.cpp b/clangd/Selection.cpp
new file mode 100644
index 00000000..233a4369
--- /dev/null
+++ b/clangd/Selection.cpp
@@ -0,0 +1,300 @@
+//===--- Selection.cpp ----------------------------------------------------===//
+//
+// 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 "Selection.h"
+#include "ClangdUnit.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+using Node = SelectionTree::Node;
+using ast_type_traits::DynTypedNode;
+
+// We find the selection by visiting written nodes in the AST, looking for nodes
+// that intersect with the selected character range.
+//
+// While traversing, we maintain a parent stack. As nodes pop off the stack,
+// we decide whether to keep them or not. To be kept, they must either be
+// selected or contain some nodes that are.
+//
+// For simple cases (not inside macros) we prune subtrees that don't intersect.
+class SelectionVisitor : public RecursiveASTVisitor<SelectionVisitor> {
+public:
+ // Runs the visitor to gather selected nodes and their ancestors.
+ // If there is any selection, the root (TUDecl) is the first node.
+ static std::deque<Node> collect(ASTContext &AST, unsigned Begin,
+ unsigned End, FileID File) {
+ SelectionVisitor V(AST, Begin, End, File);
+ V.TraverseAST(AST);
+ assert(V.Stack.size() == 1 && "Unpaired push/pop?");
+ assert(V.Stack.top() == &V.Nodes.front());
+ if (V.Nodes.size() == 1) // TUDecl, but no nodes under it.
+ V.Nodes.clear();
+ return std::move(V.Nodes);
+ }
+
+ // We traverse all "well-behaved" nodes the same way:
+ // - push the node onto the stack
+ // - traverse its children recursively
+ // - pop it from the stack
+ // - hit testing: is intersection(node, selection) - union(children) empty?
+ // - attach it to the tree if it or any children hit the selection
+ //
+ // Two categories of nodes are not "well-behaved":
+ // - those without source range information, we don't record those
+ // - those that can't be stored in DynTypedNode.
+ // We're missing some interesting things like Attr due to the latter.
+ bool TraverseDecl(Decl *X) {
+ if (X && isa<TranslationUnitDecl>(X))
+ return Base::TraverseDecl(X); // Already pushed by constructor.
+ return traverseNode(X, [&] { return Base::TraverseDecl(X); });
+ }
+ bool TraverseTypeLoc(TypeLoc X) {
+ return traverseNode(&X, [&] { return Base::TraverseTypeLoc(X); });
+ }
+ bool TraverseTypeNestedNameSpecifierLoc(NestedNameSpecifierLoc X) {
+ return traverseNode(
+ &X, [&] { return Base::TraverseNestedNameSpecifierLoc(X); });
+ }
+ bool TraverseConstructorInitializer(CXXCtorInitializer *X) {
+ return traverseNode(
+ X, [&] { return Base::TraverseConstructorInitializer(X); });
+ }
+ // Stmt is the same, but this form allows the data recursion optimization.
+ bool dataTraverseStmtPre(Stmt *X) {
+ if (!X || canSafelySkipNode(X->getSourceRange()))
+ return false;
+ push(DynTypedNode::create(*X));
+ return true;
+ }
+ bool dataTraverseStmtPost(Stmt *X) {
+ pop();
+ return true;
+ }
+ // Uninteresting parts of the AST that don't have locations within them.
+ bool TraverseNestedNameSpecifier(NestedNameSpecifier *) { return true; }
+ bool TraverseType(QualType) { return true; }
+
+private:
+ using Base = RecursiveASTVisitor<SelectionVisitor>;
+ SelectionVisitor(ASTContext &AST, unsigned SelBegin, unsigned SelEnd,
+ FileID SelFile)
+ : SM(AST.getSourceManager()), LangOpts(AST.getLangOpts()),
+ SelBegin(SelBegin), SelEnd(SelEnd), SelFile(SelFile),
+ SelBeginTokenStart(SM.getFileOffset(Lexer::GetBeginningOfToken(
+ SM.getComposedLoc(SelFile, SelBegin), SM, LangOpts))) {
+ // Ensure we have a node for the TU decl, regardless of traversal scope.
+ Nodes.emplace_back();
+ Nodes.back().ASTNode = DynTypedNode::create(*AST.getTranslationUnitDecl());
+ Nodes.back().Parent = nullptr;
+ Nodes.back().Selected = SelectionTree::Unselected;
+ Stack.push(&Nodes.back());
+ }
+
+ // Generic case of TraverseFoo. Func should be the call to Base::TraverseFoo.
+ // Node is always a pointer so the generic code can handle any null checks.
+ template <typename T, typename Func>
+ bool traverseNode(T *Node, const Func &Body) {
+ if (Node == nullptr || canSafelySkipNode(Node->getSourceRange()))
+ return true;
+ push(DynTypedNode::create(*Node));
+ bool Ret = Body();
+ pop();
+ return Ret;
+ }
+
+ // An optimization for a common case: nodes outside macro expansions that
+ // don't intersect the selection may be recursively skipped.
+ bool canSafelySkipNode(SourceRange S) {
+ auto B = SM.getDecomposedLoc(S.getBegin());
+ auto E = SM.getDecomposedLoc(S.getEnd());
+ if (B.first != SelFile || E.first != SelFile)
+ return false;
+ return B.second >= SelEnd || E.second < SelBeginTokenStart;
+ }
+
+ // Pushes a node onto the ancestor stack. Pairs with pop().
+ void push(DynTypedNode Node) {
+ Nodes.emplace_back();
+ Nodes.back().ASTNode = std::move(Node);
+ Nodes.back().Parent = Stack.top();
+ Nodes.back().Selected = SelectionTree::Unselected;
+ Stack.push(&Nodes.back());
+ }
+
+ // Pops a node off the ancestor stack, and finalizes it. Pairs with push().
+ void pop() {
+ Node &N = *Stack.top();
+ N.Selected = computeSelection(N);
+ if (N.Selected || !N.Children.empty()) {
+ // Attach to the tree.
+ N.Parent->Children.push_back(&N);
+ } else {
+ // Neither N any children are selected, it doesn't belong in the tree.
+ assert(&N == &Nodes.back());
+ Nodes.pop_back();
+ }
+ Stack.pop();
+ }
+
+ // Perform hit-testing of a complete Node against the selection.
+ // This runs for every node in the AST, and must be fast in common cases.
+ // This is called from pop(), so we can take children into account.
+ SelectionTree::Selection computeSelection(const Node &N) {
+ SourceRange S = N.ASTNode.getSourceRange();
+ if (!S.isValid())
+ return SelectionTree::Unselected;
+ // getTopMacroCallerLoc() allows selection of constructs in macro args. e.g:
+ // #define LOOP_FOREVER(Body) for(;;) { Body }
+ // void IncrementLots(int &x) {
+ // LOOP_FOREVER( ++x; )
+ // }
+ // Selecting "++x" or "x" will do the right thing.
+ auto B = SM.getDecomposedLoc(SM.getTopMacroCallerLoc(S.getBegin()));
+ auto E = SM.getDecomposedLoc(SM.getTopMacroCallerLoc(S.getEnd()));
+ // Otherwise, nodes in macro expansions can't be selected.
+ if (B.first != SelFile || E.first != SelFile)
+ return SelectionTree::Unselected;
+ // Cheap test: is there any overlap at all between the selection and range?
+ // Note that E.second is the *start* of the last token, which is why we
+ // compare against the "rounded-down" SelBegin.
+ if (B.second >= SelEnd || E.second < SelBeginTokenStart)
+ return SelectionTree::Unselected;
+
+ // We hit something, need some more precise checks.
+ // Adjust [B, E) to be a half-open character range.
+ E.second += Lexer::MeasureTokenLength(S.getEnd(), SM, LangOpts);
+ // This node's own selected text is (this range ^ selection) - child ranges.
+ // If that's empty, then we've only collided with children.
+ if (nodesCoverRange(N.Children, std::max(SelBegin, B.second),
+ std::min(SelEnd, E.second)))
+ return SelectionTree::Unselected; // Hit children only.
+ // Some of our own characters are covered, this is a true hit.
+ return (B.second >= SelBegin && E.second <= SelEnd)
+ ? SelectionTree::Complete
+ : SelectionTree::Partial;
+ }
+
+ // Is the range [Begin, End) entirely covered by the union of the Nodes?
+ // (The range is a parent node's extent, and the covering nodes are children).
+ bool nodesCoverRange(llvm::ArrayRef<const Node *> Nodes, unsigned Begin,
+ unsigned End) {
+ if (Begin >= End)
+ return true;
+ if (Nodes.empty())
+ return false;
+
+ // Collect all the expansion ranges, as offsets.
+ SmallVector<std::pair<unsigned, unsigned>, 8> ChildRanges;
+ for (const Node *N : Nodes) {
+ CharSourceRange R = SM.getExpansionRange(N->ASTNode.getSourceRange());
+ auto B = SM.getDecomposedLoc(R.getBegin());
+ auto E = SM.getDecomposedLoc(R.getEnd());
+ if (B.first != SelFile || E.first != SelFile)
+ continue;
+ // Try to cover up to the next token, spaces between children don't count.
+ if (auto Tok = Lexer::findNextToken(R.getEnd(), SM, LangOpts))
+ E.second = SM.getFileOffset(Tok->getLocation());
+ else if (R.isTokenRange())
+ E.second += Lexer::MeasureTokenLength(R.getEnd(), SM, LangOpts);
+ ChildRanges.push_back({B.second, E.second});
+ }
+ llvm::sort(ChildRanges);
+
+ // Scan through the child ranges, removing as we go.
+ for (const auto R : ChildRanges) {
+ if (R.first > Begin)
+ return false; // [Begin, R.first) is not covered.
+ Begin = R.second; // Eliminate [R.first, R.second).
+ if (Begin >= End)
+ return true; // Remaining range is empty.
+ }
+ return false; // Went through all children, trailing characters remain.
+ }
+
+ SourceManager &SM;
+ const LangOptions &LangOpts;
+ std::stack<Node *> Stack;
+ std::deque<Node> Nodes; // Stable pointers as we add more nodes.
+ // Half-open selection range.
+ unsigned SelBegin;
+ unsigned SelEnd;
+ FileID SelFile;
+ // If the selection start slices a token in half, the beginning of that token.
+ // This is useful for checking whether the end of a token range overlaps
+ // the selection: range.end < SelBeginTokenStart is equivalent to
+ // range.end + measureToken(range.end) < SelBegin (assuming range.end points
+ // to a token), and it saves a lex every time.
+ unsigned SelBeginTokenStart;
+};
+
+} // namespace
+
+void SelectionTree::print(llvm::raw_ostream &OS, const SelectionTree::Node &N,
+ int Indent) const {
+ if (N.Selected)
+ OS.indent(Indent - 1) << (N.Selected == SelectionTree::Complete ? '*'
+ : '.');
+ else
+ OS.indent(Indent);
+ OS << N.ASTNode.getNodeKind().asStringRef() << " ";
+ N.ASTNode.print(OS, PrintPolicy);
+ OS << "\n";
+ for (const Node *Child : N.Children)
+ print(OS, *Child, Indent + 2);
+}
+
+// Decide which selection emulates a "point" query in between characters.
+static std::pair<unsigned, unsigned> pointBounds(unsigned Offset, FileID FID,
+ ASTContext &AST) {
+ StringRef Buf = AST.getSourceManager().getBufferData(FID);
+ // Edge-cases where the choice is forced.
+ if (Buf.size() == 0)
+ return {0, 0};
+ if (Offset == 0)
+ return {0, 1};
+ if (Offset == Buf.size())
+ return {Offset - 1, Offset};
+ // We could choose either this byte or the previous. Usually we prefer the
+ // character on the right of the cursor (or under a block cursor).
+ // But if that's whitespace, we likely want the token on the left.
+ if (isWhitespace(Buf[Offset]) && !isWhitespace(Buf[Offset - 1]))
+ return {Offset - 1, Offset};
+ return {Offset, Offset + 1};
+}
+
+SelectionTree::SelectionTree(ASTContext &AST, unsigned Begin, unsigned End)
+ : PrintPolicy(AST.getLangOpts()) {
+ // No fundamental reason the selection needs to be in the main file,
+ // but that's all clangd has needed so far.
+ FileID FID = AST.getSourceManager().getMainFileID();
+ if (Begin == End)
+ std::tie(Begin, End) = pointBounds(Begin, FID, AST);
+ PrintPolicy.TerseOutput = true;
+
+ Nodes = SelectionVisitor::collect(AST, Begin, End, FID);
+ Root = Nodes.empty() ? nullptr : &Nodes.front();
+}
+
+SelectionTree::SelectionTree(ASTContext &AST, unsigned Offset)
+ : SelectionTree(AST, Offset, Offset) {}
+
+const Node *SelectionTree::commonAncestor() const {
+ if (!Root)
+ return nullptr;
+ for (const Node *Ancestor = Root;; Ancestor = Ancestor->Children.front()) {
+ if (Ancestor->Selected || Ancestor->Children.size() > 1)
+ return Ancestor;
+ // The tree only contains ancestors of the interesting nodes.
+ assert(!Ancestor->Children.empty() && "bad node in selection tree");
+ }
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/clangd/Selection.h b/clangd/Selection.h
new file mode 100644
index 00000000..c7cee64a
--- /dev/null
+++ b/clangd/Selection.h
@@ -0,0 +1,123 @@
+//===--- Selection.h - What's under the cursor? -------------------*-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
+//
+//===----------------------------------------------------------------------===//
+// Many features are triggered at locations/ranges and operate on AST nodes.
+// (e.g. go-to-definition or code tweaks).
+// At a high level, such features need to work out which node is the correct
+// target.
+//
+// There are a few levels of ambiguity here:
+//
+// Which tokens are included:
+// int x = one + two; // what should "go to definition" do?
+// ^^^^^^
+//
+// Same token means multiple things:
+// string("foo") // class string, or a constructor?
+// ^
+//
+// Which level of the AST is interesting?
+// if (err) { // reference to 'err', or operator bool(),
+// ^ // or the if statement itself?
+//
+// Here we build and expose a data structure that allows features to resolve
+// these ambiguities in an appropriate way:
+// - we determine which low-level nodes are partly or completely covered
+// by the selection.
+// - we expose a tree of the selected nodes and their lexical parents.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SELECTION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SELECTION_H
+#include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+namespace clangd {
+class ParsedAST;
+
+// A selection can partially or completely cover several AST nodes.
+// The SelectionTree contains nodes that are covered, and their parents.
+// SelectionTree does not contain all AST nodes, rather only:
+// Decl, Stmt, TypeLoc, NestedNamespaceSpecifierLoc, CXXCtorInitializer.
+// (These are the nodes with source ranges that fit in DynTypedNode).
+//
+// Usually commonAncestor() is the place to start:
+// - it's the simplest answer to "what node is under the cursor"
+// - the selected Expr (for example) can be found by walking up the parent
+// chain and checking Node->ASTNode.
+// - if you want to traverse the selected nodes, they are all under
+// commonAncestor() in the tree.
+//
+// The SelectionTree owns the Node structures, but the ASTNode attributes
+// point back into the AST it was constructed with.
+class SelectionTree {
+public:
+ // Creates a selection tree at the given byte offset in the main file.
+ // This is approximately equivalent to a range of one character.
+ // (Usually, the character to the right of Offset, sometimes to the left).
+ SelectionTree(ASTContext &AST, unsigned Offset);
+ // Creates a selection tree for the given range in the main file.
+ // The range includes bytes [Start, End).
+ // If Start == End, uses the same heuristics as SelectionTree(AST, Start).
+ SelectionTree(ASTContext &AST, unsigned Start, unsigned End);
+
+ // Describes to what extent an AST node is covered by the selection.
+ enum Selection {
+ // The AST node owns no characters covered by the selection.
+ // Note that characters owned by children don't count:
+ // if (x == 0) scream();
+ // ^^^^^^
+ // The IfStmt would be Unselected because all the selected characters are
+ // associated with its children.
+ // (Invisible nodes like ImplicitCastExpr are always unselected).
+ Unselected,
+ // The AST node owns selected characters, but is not completely covered.
+ Partial,
+ // The AST node owns characters, and is covered by the selection.
+ Complete,
+ };
+ // An AST node that is implicated in the selection.
+ // (Either selected directly, or some descendant is selected).
+ struct Node {
+ // The parent within the selection tree. nullptr for TranslationUnitDecl.
+ Node *Parent;
+ // Direct children within the selection tree.
+ llvm::SmallVector<const Node *, 8> Children;
+ // The corresponding node from the full AST.
+ ast_type_traits::DynTypedNode ASTNode;
+ // The extent to which this node is covered by the selection.
+ Selection Selected;
+ };
+
+ // The most specific common ancestor of all the selected nodes.
+ // If there is no selection, this is nullptr.
+ const Node *commonAncestor() const;
+ // The selection node corresponding to TranslationUnitDecl.
+ // If there is no selection, this is nullptr.
+ const Node *root() const { return Root; }
+
+private:
+ std::deque<Node> Nodes; // Stable-pointer storage.
+ const Node *Root;
+ clang::PrintingPolicy PrintPolicy;
+
+ void print(llvm::raw_ostream &OS, const Node &N, int Indent) const;
+ friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const SelectionTree &T) {
+ if (auto R = T.root())
+ T.print(OS, *R, 0);
+ else
+ OS << "(empty selection)\n";
+ return OS;
+ }
+};
+
+} // namespace clangd
+} // namespace clang
+#endif
diff --git a/clangd/SourceCode.cpp b/clangd/SourceCode.cpp
index 343fc701..6c52ca6c 100644
--- a/clangd/SourceCode.cpp
+++ b/clangd/SourceCode.cpp
@@ -1,20 +1,30 @@
//===--- SourceCode.h - Manipulating source code as strings -----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "SourceCode.h"
+#include "Context.h"
+#include "FuzzyMatch.h"
#include "Logger.h"
+#include "Protocol.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
+#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
+#include <algorithm>
namespace clang {
namespace clangd {
@@ -27,6 +37,8 @@ namespace clangd {
// Returns true if CB returned true, false if we hit the end of string.
template <typename Callback>
static bool iterateCodepoints(llvm::StringRef U8, const Callback &CB) {
+ // A codepoint takes two UTF-16 code unit if it's astral (outside BMP).
+ // Astral codepoints are encoded as 4 bytes in UTF-8, starting with 11110xxx.
for (size_t I = 0; I < U8.size();) {
unsigned char C = static_cast<unsigned char>(U8[I]);
if (LLVM_LIKELY(!(C & 0x80))) { // ASCII character.
@@ -50,31 +62,75 @@ static bool iterateCodepoints(llvm::StringRef U8, const Callback &CB) {
return false;
}
-// Returns the offset into the string that matches \p Units UTF-16 code units.
-// Conceptually, this converts to UTF-16, truncates to CodeUnits, converts back
-// to UTF-8, and returns the length in bytes.
-static size_t measureUTF16(llvm::StringRef U8, int U16Units, bool &Valid) {
+// Returns the byte offset into the string that is an offset of \p Units in
+// the specified encoding.
+// Conceptually, this converts to the encoding, truncates to CodeUnits,
+// converts back to UTF-8, and returns the length in bytes.
+static size_t measureUnits(llvm::StringRef U8, int Units, OffsetEncoding Enc,
+ bool &Valid) {
+ Valid = Units >= 0;
+ if (Units <= 0)
+ return 0;
size_t Result = 0;
- Valid = U16Units == 0 || iterateCodepoints(U8, [&](int U8Len, int U16Len) {
- Result += U8Len;
- U16Units -= U16Len;
- return U16Units <= 0;
- });
- if (U16Units < 0) // Offset was into the middle of a surrogate pair.
- Valid = false;
+ switch (Enc) {
+ case OffsetEncoding::UTF8:
+ Result = Units;
+ break;
+ case OffsetEncoding::UTF16:
+ Valid = iterateCodepoints(U8, [&](int U8Len, int U16Len) {
+ Result += U8Len;
+ Units -= U16Len;
+ return Units <= 0;
+ });
+ if (Units < 0) // Offset in the middle of a surrogate pair.
+ Valid = false;
+ break;
+ case OffsetEncoding::UTF32:
+ Valid = iterateCodepoints(U8, [&](int U8Len, int U16Len) {
+ Result += U8Len;
+ Units--;
+ return Units <= 0;
+ });
+ break;
+ case OffsetEncoding::UnsupportedEncoding:
+ llvm_unreachable("unsupported encoding");
+ }
// Don't return an out-of-range index if we overran.
- return std::min(Result, U8.size());
+ if (Result > U8.size()) {
+ Valid = false;
+ return U8.size();
+ }
+ return Result;
+}
+
+Key<OffsetEncoding> kCurrentOffsetEncoding;
+static OffsetEncoding lspEncoding() {
+ auto *Enc = Context::current().get(kCurrentOffsetEncoding);
+ return Enc ? *Enc : OffsetEncoding::UTF16;
}
// Like most strings in clangd, the input is UTF-8 encoded.
size_t lspLength(llvm::StringRef Code) {
- // A codepoint takes two UTF-16 code unit if it's astral (outside BMP).
- // Astral codepoints are encoded as 4 bytes in UTF-8, starting with 11110xxx.
size_t Count = 0;
- iterateCodepoints(Code, [&](int U8Len, int U16Len) {
- Count += U16Len;
- return false;
- });
+ switch (lspEncoding()) {
+ case OffsetEncoding::UTF8:
+ Count = Code.size();
+ break;
+ case OffsetEncoding::UTF16:
+ iterateCodepoints(Code, [&](int U8Len, int U16Len) {
+ Count += U16Len;
+ return false;
+ });
+ break;
+ case OffsetEncoding::UTF32:
+ iterateCodepoints(Code, [&](int U8Len, int U16Len) {
+ ++Count;
+ return false;
+ });
+ break;
+ case OffsetEncoding::UnsupportedEncoding:
+ llvm_unreachable("unsupported encoding");
+ }
return Count;
}
@@ -97,20 +153,18 @@ llvm::Expected<size_t> positionToOffset(llvm::StringRef Code, Position P,
llvm::errc::invalid_argument);
StartOfLine = NextNL + 1;
}
+ StringRef Line =
+ Code.substr(StartOfLine).take_until([](char C) { return C == '\n'; });
- size_t NextNL = Code.find('\n', StartOfLine);
- if (NextNL == llvm::StringRef::npos)
- NextNL = Code.size();
-
+ // P.character may be in UTF-16, transcode if necessary.
bool Valid;
- size_t ByteOffsetInLine = measureUTF16(
- Code.substr(StartOfLine, NextNL - StartOfLine), P.character, Valid);
+ size_t ByteInLine = measureUnits(Line, P.character, lspEncoding(), Valid);
if (!Valid && !AllowColumnsBeyondLineLength)
return llvm::make_error<llvm::StringError>(
- llvm::formatv("UTF-16 offset {0} is invalid for line {1}", P.character,
- P.line),
+ llvm::formatv("{0} offset {1} is invalid for line {2}", lspEncoding(),
+ P.character, P.line),
llvm::errc::invalid_argument);
- return StartOfLine + ByteOffsetInLine;
+ return StartOfLine + ByteInLine;
}
Position offsetToPosition(llvm::StringRef Code, size_t Offset) {
@@ -142,6 +196,79 @@ Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc) {
return P;
}
+bool isValidFileRange(const SourceManager &Mgr, SourceRange R) {
+ if (!R.getBegin().isValid() || !R.getEnd().isValid())
+ return false;
+
+ FileID BeginFID;
+ size_t BeginOffset = 0;
+ std::tie(BeginFID, BeginOffset) = Mgr.getDecomposedLoc(R.getBegin());
+
+ FileID EndFID;
+ size_t EndOffset = 0;
+ std::tie(EndFID, EndOffset) = Mgr.getDecomposedLoc(R.getEnd());
+
+ return BeginFID.isValid() && BeginFID == EndFID && BeginOffset <= EndOffset;
+}
+
+bool halfOpenRangeContains(const SourceManager &Mgr, SourceRange R,
+ SourceLocation L) {
+ assert(isValidFileRange(Mgr, R));
+
+ FileID BeginFID;
+ size_t BeginOffset = 0;
+ std::tie(BeginFID, BeginOffset) = Mgr.getDecomposedLoc(R.getBegin());
+ size_t EndOffset = Mgr.getFileOffset(R.getEnd());
+
+ FileID LFid;
+ size_t LOffset;
+ std::tie(LFid, LOffset) = Mgr.getDecomposedLoc(L);
+ return BeginFID == LFid && BeginOffset <= LOffset && LOffset < EndOffset;
+}
+
+bool halfOpenRangeTouches(const SourceManager &Mgr, SourceRange R,
+ SourceLocation L) {
+ return L == R.getEnd() || halfOpenRangeContains(Mgr, R, L);
+}
+
+llvm::Optional<SourceRange> toHalfOpenFileRange(const SourceManager &Mgr,
+ const LangOptions &LangOpts,
+ SourceRange R) {
+ auto Begin = Mgr.getFileLoc(R.getBegin());
+ if (Begin.isInvalid())
+ return llvm::None;
+ auto End = Mgr.getFileLoc(R.getEnd());
+ if (End.isInvalid())
+ return llvm::None;
+ End = Lexer::getLocForEndOfToken(End, 0, Mgr, LangOpts);
+
+ SourceRange Result(Begin, End);
+ if (!isValidFileRange(Mgr, Result))
+ return llvm::None;
+ return Result;
+}
+
+llvm::StringRef toSourceCode(const SourceManager &SM, SourceRange R) {
+ assert(isValidFileRange(SM, R));
+ bool Invalid = false;
+ auto *Buf = SM.getBuffer(SM.getFileID(R.getBegin()), &Invalid);
+ assert(!Invalid);
+
+ size_t BeginOffset = SM.getFileOffset(R.getBegin());
+ size_t EndOffset = SM.getFileOffset(R.getEnd());
+ return Buf->getBuffer().substr(BeginOffset, EndOffset - BeginOffset);
+}
+
+llvm::Expected<SourceLocation> sourceLocationInMainFile(const SourceManager &SM,
+ Position P) {
+ llvm::StringRef Code = SM.getBuffer(SM.getMainFileID())->getBuffer();
+ auto Offset =
+ positionToOffset(Code, P, /*AllowColumnBeyondLineLength=*/false);
+ if (!Offset)
+ return Offset.takeError();
+ return SM.getLocForStartOfFile(SM.getMainFileID()).getLocWithOffset(*Offset);
+}
+
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R) {
// Clang is 1-based, LSP uses 0-based indexes.
Position Begin = sourceLocToPosition(SM, R.getBegin());
@@ -160,8 +287,7 @@ std::pair<size_t, size_t> offsetToClangLineColumn(llvm::StringRef Code,
return {Lines + 1, Offset - StartOfLine + 1};
}
-std::pair<llvm::StringRef, llvm::StringRef>
-splitQualifiedName(llvm::StringRef QName) {
+std::pair<StringRef, StringRef> splitQualifiedName(StringRef QName) {
size_t Pos = QName.rfind("::");
if (Pos == llvm::StringRef::npos)
return {llvm::StringRef(), QName};
@@ -192,7 +318,7 @@ llvm::Optional<std::string> getCanonicalPath(const FileEntry *F,
llvm::SmallString<128> FilePath = F->getName();
if (!llvm::sys::path::is_absolute(FilePath)) {
if (auto EC =
- SourceMgr.getFileManager().getVirtualFileSystem()->makeAbsolute(
+ SourceMgr.getFileManager().getVirtualFileSystem().makeAbsolute(
FilePath)) {
elog("Could not turn relative path '{0}' to absolute: {1}", FilePath,
EC.message());
@@ -232,7 +358,7 @@ TextEdit toTextEdit(const FixItHint &FixIt, const SourceManager &M,
return Result;
}
-bool IsRangeConsecutive(const Range &Left, const Range &Right) {
+bool isRangeConsecutive(const Range &Left, const Range &Right) {
return Left.end.line == Right.start.line &&
Left.end.character == Right.start.character;
}
@@ -249,5 +375,272 @@ llvm::Optional<FileDigest> digestFile(const SourceManager &SM, FileID FID) {
return digest(Content);
}
+format::FormatStyle getFormatStyleForFile(llvm::StringRef File,
+ llvm::StringRef Content,
+ llvm::vfs::FileSystem *FS) {
+ auto Style = format::getStyle(format::DefaultFormatStyle, File,
+ format::DefaultFallbackStyle, Content, FS);
+ if (!Style) {
+ log("getStyle() failed for file {0}: {1}. Fallback is LLVM style.", File,
+ Style.takeError());
+ Style = format::getLLVMStyle();
+ }
+ return *Style;
+}
+
+llvm::Expected<tooling::Replacements>
+cleanupAndFormat(StringRef Code, const tooling::Replacements &Replaces,
+ const format::FormatStyle &Style) {
+ auto CleanReplaces = cleanupAroundReplacements(Code, Replaces, Style);
+ if (!CleanReplaces)
+ return CleanReplaces;
+ return formatReplacements(Code, std::move(*CleanReplaces), Style);
+}
+
+template <typename Action>
+static void lex(llvm::StringRef Code, const format::FormatStyle &Style,
+ Action A) {
+ // FIXME: InMemoryFileAdapter crashes unless the buffer is null terminated!
+ std::string NullTerminatedCode = Code.str();
+ SourceManagerForFile FileSM("dummy.cpp", NullTerminatedCode);
+ auto &SM = FileSM.get();
+ auto FID = SM.getMainFileID();
+ Lexer Lex(FID, SM.getBuffer(FID), SM, format::getFormattingLangOpts(Style));
+ Token Tok;
+
+ while (!Lex.LexFromRawLexer(Tok))
+ A(Tok);
+}
+
+llvm::StringMap<unsigned> collectIdentifiers(llvm::StringRef Content,
+ const format::FormatStyle &Style) {
+ llvm::StringMap<unsigned> Identifiers;
+ lex(Content, Style, [&](const clang::Token &Tok) {
+ switch (Tok.getKind()) {
+ case tok::identifier:
+ ++Identifiers[Tok.getIdentifierInfo()->getName()];
+ break;
+ case tok::raw_identifier:
+ ++Identifiers[Tok.getRawIdentifier()];
+ break;
+ default:
+ break;
+ }
+ });
+ return Identifiers;
+}
+
+namespace {
+enum NamespaceEvent {
+ BeginNamespace, // namespace <ns> {. Payload is resolved <ns>.
+ EndNamespace, // } // namespace <ns>. Payload is resolved *outer* namespace.
+ UsingDirective // using namespace <ns>. Payload is unresolved <ns>.
+};
+// Scans C++ source code for constructs that change the visible namespaces.
+void parseNamespaceEvents(
+ llvm::StringRef Code, const format::FormatStyle &Style,
+ llvm::function_ref<void(NamespaceEvent, llvm::StringRef)> Callback) {
+
+ // Stack of enclosing namespaces, e.g. {"clang", "clangd"}
+ std::vector<std::string> Enclosing; // Contains e.g. "clang", "clangd"
+ // Stack counts open braces. true if the brace opened a namespace.
+ std::vector<bool> BraceStack;
+
+ enum {
+ Default,
+ Namespace, // just saw 'namespace'
+ NamespaceName, // just saw 'namespace' NSName
+ Using, // just saw 'using'
+ UsingNamespace, // just saw 'using namespace'
+ UsingNamespaceName, // just saw 'using namespace' NSName
+ } State = Default;
+ std::string NSName;
+
+ lex(Code, Style, [&](const clang::Token &Tok) {
+ switch(Tok.getKind()) {
+ case tok::raw_identifier:
+ // In raw mode, this could be a keyword or a name.
+ switch (State) {
+ case UsingNamespace:
+ case UsingNamespaceName:
+ NSName.append(Tok.getRawIdentifier());
+ State = UsingNamespaceName;
+ break;
+ case Namespace:
+ case NamespaceName:
+ NSName.append(Tok.getRawIdentifier());
+ State = NamespaceName;
+ break;
+ case Using:
+ State =
+ (Tok.getRawIdentifier() == "namespace") ? UsingNamespace : Default;
+ break;
+ case Default:
+ NSName.clear();
+ if (Tok.getRawIdentifier() == "namespace")
+ State = Namespace;
+ else if (Tok.getRawIdentifier() == "using")
+ State = Using;
+ break;
+ }
+ break;
+ case tok::coloncolon:
+ // This can come at the beginning or in the middle of a namespace name.
+ switch (State) {
+ case UsingNamespace:
+ case UsingNamespaceName:
+ NSName.append("::");
+ State = UsingNamespaceName;
+ break;
+ case NamespaceName:
+ NSName.append("::");
+ State = NamespaceName;
+ break;
+ case Namespace: // Not legal here.
+ case Using:
+ case Default:
+ State = Default;
+ break;
+ }
+ break;
+ case tok::l_brace:
+ // Record which { started a namespace, so we know when } ends one.
+ if (State == NamespaceName) {
+ // Parsed: namespace <name> {
+ BraceStack.push_back(true);
+ Enclosing.push_back(NSName);
+ Callback(BeginNamespace, llvm::join(Enclosing, "::"));
+ } else {
+ // This case includes anonymous namespaces (State = Namespace).
+ // For our purposes, they're not namespaces and we ignore them.
+ BraceStack.push_back(false);
+ }
+ State = Default;
+ break;
+ case tok::r_brace:
+ // If braces are unmatched, we're going to be confused, but don't crash.
+ if (!BraceStack.empty()) {
+ if (BraceStack.back()) {
+ // Parsed: } // namespace
+ Enclosing.pop_back();
+ Callback(EndNamespace, llvm::join(Enclosing, "::"));
+ }
+ BraceStack.pop_back();
+ }
+ break;
+ case tok::semi:
+ if (State == UsingNamespaceName)
+ // Parsed: using namespace <name> ;
+ Callback(UsingDirective, llvm::StringRef(NSName));
+ State = Default;
+ break;
+ default:
+ State = Default;
+ break;
+ }
+ });
+}
+
+// Returns the prefix namespaces of NS: {"" ... NS}.
+llvm::SmallVector<llvm::StringRef, 8> ancestorNamespaces(llvm::StringRef NS) {
+ llvm::SmallVector<llvm::StringRef, 8> Results;
+ Results.push_back(NS.take_front(0));
+ NS.split(Results, "::", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ for (llvm::StringRef &R : Results)
+ R = NS.take_front(R.end() - NS.begin());
+ return Results;
+}
+
+} // namespace
+
+std::vector<std::string> visibleNamespaces(llvm::StringRef Code,
+ const format::FormatStyle &Style) {
+ std::string Current;
+ // Map from namespace to (resolved) namespaces introduced via using directive.
+ llvm::StringMap<llvm::StringSet<>> UsingDirectives;
+
+ parseNamespaceEvents(Code, Style,
+ [&](NamespaceEvent Event, llvm::StringRef NS) {
+ switch (Event) {
+ case BeginNamespace:
+ case EndNamespace:
+ Current = NS;
+ break;
+ case UsingDirective:
+ if (NS.consume_front("::"))
+ UsingDirectives[Current].insert(NS);
+ else {
+ for (llvm::StringRef Enclosing :
+ ancestorNamespaces(Current)) {
+ if (Enclosing.empty())
+ UsingDirectives[Current].insert(NS);
+ else
+ UsingDirectives[Current].insert(
+ (Enclosing + "::" + NS).str());
+ }
+ }
+ break;
+ }
+ });
+
+ std::vector<std::string> Found;
+ for (llvm::StringRef Enclosing : ancestorNamespaces(Current)) {
+ Found.push_back(Enclosing);
+ auto It = UsingDirectives.find(Enclosing);
+ if (It != UsingDirectives.end())
+ for (const auto& Used : It->second)
+ Found.push_back(Used.getKey());
+ }
+
+
+ llvm::sort(Found, [&](const std::string &LHS, const std::string &RHS) {
+ if (Current == RHS)
+ return false;
+ if (Current == LHS)
+ return true;
+ return LHS < RHS;
+ });
+ Found.erase(std::unique(Found.begin(), Found.end()), Found.end());
+ return Found;
+}
+
+llvm::StringSet<> collectWords(llvm::StringRef Content) {
+ // We assume short words are not significant.
+ // We may want to consider other stopwords, e.g. language keywords.
+ // (A very naive implementation showed no benefit, but lexing might do better)
+ static constexpr int MinWordLength = 4;
+
+ std::vector<CharRole> Roles(Content.size());
+ calculateRoles(Content, Roles);
+
+ llvm::StringSet<> Result;
+ llvm::SmallString<256> Word;
+ auto Flush = [&] {
+ if (Word.size() >= MinWordLength) {
+ for (char &C : Word)
+ C = llvm::toLower(C);
+ Result.insert(Word);
+ }
+ Word.clear();
+ };
+ for (unsigned I = 0; I < Content.size(); ++I) {
+ switch (Roles[I]) {
+ case Head:
+ Flush();
+ LLVM_FALLTHROUGH;
+ case Tail:
+ Word.push_back(Content[I]);
+ break;
+ case Unknown:
+ case Separator:
+ Flush();
+ break;
+ }
+ }
+ Flush();
+
+ return Result;
+}
+
} // namespace clangd
} // namespace clang
diff --git a/clangd/SourceCode.h b/clangd/SourceCode.h
index b768d09a..85db9458 100644
--- a/clangd/SourceCode.h
+++ b/clangd/SourceCode.h
@@ -1,9 +1,8 @@
//===--- SourceCode.h - Manipulating source code as strings -----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -13,11 +12,16 @@
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SOURCECODE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SOURCECODE_H
+#include "Context.h"
#include "Protocol.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Format/Format.h"
#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/SHA1.h"
namespace clang {
@@ -32,8 +36,14 @@ using FileDigest = decltype(llvm::SHA1::hash({}));
FileDigest digest(StringRef Content);
Optional<FileDigest> digestFile(const SourceManager &SM, FileID FID);
+// This context variable controls the behavior of functions in this file
+// that convert between LSP offsets and native clang byte offsets.
+// If not set, defaults to UTF-16 for backwards-compatibility.
+extern Key<OffsetEncoding> kCurrentOffsetEncoding;
+
// Counts the number of UTF-16 code units needed to represent a string (LSP
// specifies string lengths in UTF-16 code units).
+// Use of UTF-16 may be overridden by kCurrentOffsetEncoding.
size_t lspLength(StringRef Code);
/// Turn a [line, column] pair into an offset in Code.
@@ -55,6 +65,51 @@ Position offsetToPosition(llvm::StringRef Code, size_t Offset);
/// FIXME: This should return an error if the location is invalid.
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc);
+/// Return the file location, corresponding to \p P. Note that one should take
+/// care to avoid comparing the result with expansion locations.
+llvm::Expected<SourceLocation> sourceLocationInMainFile(const SourceManager &SM,
+ Position P);
+
+/// Turns a token range into a half-open range and checks its correctness.
+/// The resulting range will have only valid source location on both sides, both
+/// of which are file locations.
+///
+/// File locations always point to a particular offset in a file, i.e. they
+/// never refer to a location inside a macro expansion. Turning locations from
+/// macro expansions into file locations is ambiguous - one can use
+/// SourceManager::{getExpansion|getFile|getSpelling}Loc. This function
+/// calls SourceManager::getFileLoc on both ends of \p R to do the conversion.
+///
+/// User input (e.g. cursor position) is expressed as a file location, so this
+/// function can be viewed as a way to normalize the ranges used in the clang
+/// AST so that they are comparable with ranges coming from the user input.
+llvm::Optional<SourceRange> toHalfOpenFileRange(const SourceManager &Mgr,
+ const LangOptions &LangOpts,
+ SourceRange R);
+
+/// Returns true iff all of the following conditions hold:
+/// - start and end locations are valid,
+/// - start and end locations are file locations from the same file
+/// (i.e. expansion locations are not taken into account).
+/// - start offset <= end offset.
+/// FIXME: introduce a type for source range with this invariant.
+bool isValidFileRange(const SourceManager &Mgr, SourceRange R);
+
+/// Returns true iff \p L is contained in \p R.
+/// EXPECTS: isValidFileRange(R) == true, L is a file location.
+bool halfOpenRangeContains(const SourceManager &Mgr, SourceRange R,
+ SourceLocation L);
+
+/// Returns true iff \p L is contained in \p R or \p L is equal to the end point
+/// of \p R.
+/// EXPECTS: isValidFileRange(R) == true, L is a file location.
+bool halfOpenRangeTouches(const SourceManager &Mgr, SourceRange R,
+ SourceLocation L);
+
+/// Returns the source code covered by the source range.
+/// EXPECTS: isValidFileRange(R) == true.
+llvm::StringRef toSourceCode(const SourceManager &SM, SourceRange R);
+
// Converts a half-open clang source range to an LSP range.
// Note that clang also uses closed source ranges, which this can't handle!
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R);
@@ -91,7 +146,56 @@ TextEdit toTextEdit(const FixItHint &FixIt, const SourceManager &M,
llvm::Optional<std::string> getCanonicalPath(const FileEntry *F,
const SourceManager &SourceMgr);
-bool IsRangeConsecutive(const Range &Left, const Range &Right);
+bool isRangeConsecutive(const Range &Left, const Range &Right);
+
+/// Choose the clang-format style we should apply to a certain file.
+/// This will usually use FS to look for .clang-format directories.
+/// FIXME: should we be caching the .clang-format file search?
+/// This uses format::DefaultFormatStyle and format::DefaultFallbackStyle,
+/// though the latter may have been overridden in main()!
+format::FormatStyle getFormatStyleForFile(llvm::StringRef File,
+ llvm::StringRef Content,
+ llvm::vfs::FileSystem *FS);
+
+// Cleanup and format the given replacements.
+llvm::Expected<tooling::Replacements>
+cleanupAndFormat(StringRef Code, const tooling::Replacements &Replaces,
+ const format::FormatStyle &Style);
+
+/// Collects identifiers with counts in the source code.
+llvm::StringMap<unsigned> collectIdentifiers(llvm::StringRef Content,
+ const format::FormatStyle &Style);
+
+/// Collects words from the source code.
+/// Unlike collectIdentifiers:
+/// - also finds text in comments:
+/// - splits text into words
+/// - drops stopwords like "get" and "for"
+llvm::StringSet<> collectWords(llvm::StringRef Content);
+
+/// Heuristically determine namespaces visible at a point, without parsing Code.
+/// This considers using-directives and enclosing namespace-declarations that
+/// are visible (and not obfuscated) in the file itself (not headers).
+/// Code should be truncated at the point of interest.
+///
+/// The returned vector is always non-empty.
+/// - The first element is the namespace that encloses the point: a declaration
+/// near the point would be within this namespace.
+/// - The elements are the namespaces in scope at the point: an unqualified
+/// lookup would search within these namespaces.
+///
+/// Using directives are resolved against all enclosing scopes, but no other
+/// namespace directives.
+///
+/// example:
+/// using namespace a;
+/// namespace foo {
+/// using namespace b;
+///
+/// visibleNamespaces are {"foo::", "", "a::", "b::", "foo::b::"}, not "a::b::".
+std::vector<std::string> visibleNamespaces(llvm::StringRef Code,
+ const format::FormatStyle &Style);
+
} // namespace clangd
} // namespace clang
#endif
diff --git a/clangd/StdSymbolMap.inc b/clangd/StdSymbolMap.inc
new file mode 100644
index 00000000..85fd474e
--- /dev/null
+++ b/clangd/StdSymbolMap.inc
@@ -0,0 +1,1513 @@
+//===-- gen_std.py generated file -------------------------------*- C++ -*-===//
+//
+// Used to build a lookup table (qualified names => include headers) for C++
+// Standard Library symbols.
+//
+// Automatically generated file, DO NOT EDIT!
+//
+// Generated from cppreference offline HTML book (modified on 2018-10-28).
+//===----------------------------------------------------------------------===//
+
+SYMBOL(Assignable, std::, <concepts>)
+SYMBOL(Boolean, std::, <concepts>)
+SYMBOL(Common, std::, <concepts>)
+SYMBOL(CommonReference, std::, <concepts>)
+SYMBOL(Constructible, std::, <concepts>)
+SYMBOL(ConvertibleTo, std::, <concepts>)
+SYMBOL(CopyConstructible, std::, <concepts>)
+SYMBOL(Copyable, std::, <concepts>)
+SYMBOL(DefaultConstructible, std::, <concepts>)
+SYMBOL(DerivedFrom, std::, <concepts>)
+SYMBOL(Destructible, std::, <concepts>)
+SYMBOL(EqualityComparable, std::, <concepts>)
+SYMBOL(EqualityComparableWith, std::, <concepts>)
+SYMBOL(FILE, std::, <cstdio>)
+SYMBOL(Integral, std::, <concepts>)
+SYMBOL(Invocable, std::, <concepts>)
+SYMBOL(Movable, std::, <concepts>)
+SYMBOL(MoveConstructible, std::, <concepts>)
+SYMBOL(Predicate, std::, <concepts>)
+SYMBOL(Regular, std::, <concepts>)
+SYMBOL(RegularInvocable, std::, <concepts>)
+SYMBOL(Relation, std::, <concepts>)
+SYMBOL(Same, std::, <concepts>)
+SYMBOL(Semiregular, std::, <concepts>)
+SYMBOL(SignedIntegral, std::, <concepts>)
+SYMBOL(StrictTotallyOrdered, std::, <concepts>)
+SYMBOL(StrictTotallyOrderedWith, std::, <concepts>)
+SYMBOL(StrictWeakOrder, std::, <concepts>)
+SYMBOL(Swappable, std::, <concepts>)
+SYMBOL(SwappableWith, std::, <concepts>)
+SYMBOL(UniformRandomBitGenerator, std::, <random>)
+SYMBOL(UnsignedIntegral, std::, <concepts>)
+SYMBOL(_Exit, std::, <cstdlib>)
+SYMBOL(accumulate, std::, <numeric>)
+SYMBOL(acos, std::, <cmath>)
+SYMBOL(acosh, std::, <cmath>)
+SYMBOL(add_const, std::, <type_traits>)
+SYMBOL(add_const_t, std::, <type_traits>)
+SYMBOL(add_cv, std::, <type_traits>)
+SYMBOL(add_cv_t, std::, <type_traits>)
+SYMBOL(add_lvalue_reference, std::, <type_traits>)
+SYMBOL(add_lvalue_reference_t, std::, <type_traits>)
+SYMBOL(add_pointer, std::, <type_traits>)
+SYMBOL(add_pointer_t, std::, <type_traits>)
+SYMBOL(add_rvalue_reference, std::, <type_traits>)
+SYMBOL(add_rvalue_reference_t, std::, <type_traits>)
+SYMBOL(add_volatile, std::, <type_traits>)
+SYMBOL(add_volatile_t, std::, <type_traits>)
+SYMBOL(addressof, std::, <memory>)
+SYMBOL(adjacent_difference, std::, <numeric>)
+SYMBOL(adjacent_find, std::, <algorithm>)
+SYMBOL(adopt_lock, std::, <mutex>)
+SYMBOL(adopt_lock_t, std::, <mutex>)
+SYMBOL(advance, std::, <iterator>)
+SYMBOL(align, std::, <memory>)
+SYMBOL(align_val_t, std::, <new>)
+SYMBOL(aligned_alloc, std::, <cstdlib>)
+SYMBOL(aligned_storage, std::, <type_traits>)
+SYMBOL(aligned_storage_t, std::, <type_traits>)
+SYMBOL(aligned_union, std::, <type_traits>)
+SYMBOL(aligned_union_t, std::, <type_traits>)
+SYMBOL(alignment_of, std::, <type_traits>)
+SYMBOL(alignment_of_v, std::, <type_traits>)
+SYMBOL(all_of, std::, <algorithm>)
+SYMBOL(allocate_shared, std::, <memory>)
+SYMBOL(allocator, std::, <memory>)
+SYMBOL(allocator_arg, std::, <memory>)
+SYMBOL(allocator_arg_t, std::, <memory>)
+SYMBOL(allocator_traits, std::, <memory>)
+SYMBOL(any, std::, <any>)
+SYMBOL(any_of, std::, <algorithm>)
+SYMBOL(apply, std::, <tuple>)
+SYMBOL(arg, std::, <complex>)
+SYMBOL(array, std::, <array>)
+SYMBOL(as_const, std::, <utility>)
+SYMBOL(asctime, std::, <ctime>)
+SYMBOL(asin, std::, <cmath>)
+SYMBOL(asinh, std::, <cmath>)
+SYMBOL(async, std::, <future>)
+SYMBOL(at_quick_exit, std::, <cstdlib>)
+SYMBOL(atan, std::, <cmath>)
+SYMBOL(atan2, std::, <cmath>)
+SYMBOL(atanh, std::, <cmath>)
+SYMBOL(atexit, std::, <cstdlib>)
+SYMBOL(atof, std::, <cstdlib>)
+SYMBOL(atoi, std::, <cstdlib>)
+SYMBOL(atol, std::, <cstdlib>)
+SYMBOL(atoll, std::, <cstdlib>)
+SYMBOL(atomic_compare_exchange_strong, std::, <atomic>)
+SYMBOL(atomic_compare_exchange_strong_explicit, std::, <atomic>)
+SYMBOL(atomic_compare_exchange_weak, std::, <atomic>)
+SYMBOL(atomic_compare_exchange_weak_explicit, std::, <atomic>)
+SYMBOL(atomic_exchange, std::, <atomic>)
+SYMBOL(atomic_exchange_explicit, std::, <atomic>)
+SYMBOL(atomic_fetch_add, std::, <atomic>)
+SYMBOL(atomic_fetch_add_explicit, std::, <atomic>)
+SYMBOL(atomic_fetch_and, std::, <atomic>)
+SYMBOL(atomic_fetch_and_explicit, std::, <atomic>)
+SYMBOL(atomic_fetch_or, std::, <atomic>)
+SYMBOL(atomic_fetch_or_explicit, std::, <atomic>)
+SYMBOL(atomic_fetch_sub, std::, <atomic>)
+SYMBOL(atomic_fetch_sub_explicit, std::, <atomic>)
+SYMBOL(atomic_fetch_xor, std::, <atomic>)
+SYMBOL(atomic_fetch_xor_explicit, std::, <atomic>)
+SYMBOL(atomic_flag, std::, <atomic>)
+SYMBOL(atomic_flag_clear, std::, <atomic>)
+SYMBOL(atomic_flag_clear_explicit, std::, <atomic>)
+SYMBOL(atomic_flag_test_and_set, std::, <atomic>)
+SYMBOL(atomic_flag_test_and_set_explicit, std::, <atomic>)
+SYMBOL(atomic_init, std::, <atomic>)
+SYMBOL(atomic_is_lockfree, std::, <atomic>)
+SYMBOL(atomic_load, std::, <atomic>)
+SYMBOL(atomic_load_explicit, std::, <atomic>)
+SYMBOL(atomic_ref, std::, <atomic>)
+SYMBOL(atomic_signal_fence, std::, <atomic>)
+SYMBOL(atomic_store, std::, <atomic>)
+SYMBOL(atomic_store_explicit, std::, <atomic>)
+SYMBOL(atomic_thread_fence, std::, <atomic>)
+SYMBOL(atto, std::, <ratio>)
+SYMBOL(auto_ptr, std::, <memory>)
+SYMBOL(back_insert_iterator, std::, <iterator>)
+SYMBOL(back_inserter, std::, <iterator>)
+SYMBOL(bad_alloc, std::, <new>)
+SYMBOL(bad_any_cast, std::, <any>)
+SYMBOL(bad_array_new_length, std::, <new>)
+SYMBOL(bad_cast, std::, <typeinfo>)
+SYMBOL(bad_exception, std::, <exception>)
+SYMBOL(bad_function_call, std::, <functional>)
+SYMBOL(bad_optional_access, std::, <optional>)
+SYMBOL(bad_typeid, std::, <typeinfo>)
+SYMBOL(bad_variant_access, std::, <variant>)
+SYMBOL(bad_weak_ptr, std::, <memory>)
+SYMBOL(basic_common_reference, std::, <type_traits>)
+SYMBOL(basic_filebuf, std::, <fstream>)
+SYMBOL(basic_fstream, std::, <fstream>)
+SYMBOL(basic_ifstream, std::, <fstream>)
+SYMBOL(basic_ios, std::, <ios>)
+SYMBOL(basic_iostream, std::, <istream>)
+SYMBOL(basic_istream, std::, <istream>)
+SYMBOL(basic_istringstream, std::, <sstream>)
+SYMBOL(basic_ofstream, std::, <fstream>)
+SYMBOL(basic_ostream, std::, <ostream>)
+SYMBOL(basic_ostringstream, std::, <sstream>)
+SYMBOL(basic_osyncstream, std::, <syncstream>)
+SYMBOL(basic_regex, std::, <regex>)
+SYMBOL(basic_streambuf, std::, <streambuf>)
+SYMBOL(basic_string, std::, <string>)
+SYMBOL(basic_string_view, std::, <string_view>)
+SYMBOL(basic_stringbuf, std::, <sstream>)
+SYMBOL(basic_stringstream, std::, <sstream>)
+SYMBOL(basic_syncbuf, std::, <syncstream>)
+SYMBOL(begin, std::, <iterator>)
+SYMBOL(bernoulli_distribution, std::, <random>)
+SYMBOL(bidirectional_iterator_tag, std::, <iterator>)
+SYMBOL(binary_search, std::, <algorithm>)
+SYMBOL(bind, std::, <functional>)
+SYMBOL(binomial_distribution, std::, <random>)
+SYMBOL(bit_and, std::, <functional>)
+SYMBOL(bit_cast, std::, <bit>)
+SYMBOL(bit_not, std::, <functional>)
+SYMBOL(bit_or, std::, <functional>)
+SYMBOL(bit_xor, std::, <functional>)
+SYMBOL(bitset, std::, <bitset>)
+SYMBOL(bool_constant, std::, <type_traits>)
+SYMBOL(boolalpha, std::, <ios>)
+SYMBOL(boyer_moore_horspool_searcher, std::, <functional>)
+SYMBOL(boyer_moore_searcher, std::, <functional>)
+SYMBOL(bsearch, std::, <cstdlib>)
+SYMBOL(btowc, std::, <cwchar>)
+SYMBOL(byte, std::, <cstddef>)
+SYMBOL(c16rtomb, std::, <cuchar>)
+SYMBOL(c32rtomb, std::, <cuchar>)
+SYMBOL(call_once, std::, <mutex>)
+SYMBOL(calloc, std::, <cstdlib>)
+SYMBOL(cauchy_distribution, std::, <random>)
+SYMBOL(cbegin, std::, <iterator>)
+SYMBOL(cbrt, std::, <cmath>)
+SYMBOL(ceil, std::, <cmath>)
+SYMBOL(ceil2, std::, <bit>)
+SYMBOL(cend, std::, <iterator>)
+SYMBOL(centi, std::, <ratio>)
+SYMBOL(cerr, std::, <iostream>)
+SYMBOL(char_traits, std::, <string>)
+SYMBOL(chars_format, std::, <charconv>)
+SYMBOL(chi_squared_distribution, std::, <random>)
+SYMBOL(cin, std::, <iostream>)
+SYMBOL(clamp, std::, <algorithm>)
+SYMBOL(clearerr, std::, <cstdio>)
+SYMBOL(clock, std::, <ctime>)
+SYMBOL(clock_t, std::, <ctime>)
+SYMBOL(clog, std::, <iostream>)
+SYMBOL(cmatch, std::, <regex>)
+SYMBOL(codecvt, std::, <locale>)
+SYMBOL(codecvt_base, std::, <locale>)
+SYMBOL(codecvt_byname, std::, <locale>)
+SYMBOL(codecvt_mode, std::, <codecvt>)
+SYMBOL(codecvt_utf16, std::, <codecvt>)
+SYMBOL(codecvt_utf8, std::, <codecvt>)
+SYMBOL(codecvt_utf8_utf16, std::, <codecvt>)
+SYMBOL(collate, std::, <locale>)
+SYMBOL(collate_byname, std::, <locale>)
+SYMBOL(common_comparison_category, std::, <compare>)
+SYMBOL(common_comparison_category_t, std::, <compare>)
+SYMBOL(common_reference, std::, <type_traits>)
+SYMBOL(common_reference_t, std::, <type_traits>)
+SYMBOL(common_type, std::, <type_traits>)
+SYMBOL(common_type_t, std::, <type_traits>)
+SYMBOL(compare_3way, std::, <algorithm>)
+SYMBOL(complex, std::, <complex>)
+SYMBOL(condition_variable, std::, <condition_variable>)
+SYMBOL(condition_variable_any, std::, <condition_variable>)
+SYMBOL(conditional, std::, <type_traits>)
+SYMBOL(conditional_t, std::, <type_traits>)
+SYMBOL(conj, std::, <complex>)
+SYMBOL(conjunction, std::, <type_traits>)
+SYMBOL(conjunction_v, std::, <type_traits>)
+SYMBOL(const_pointer_cast, std::, <memory>)
+SYMBOL(contract_violation, std::, <contract>)
+SYMBOL(copy, std::, <algorithm>)
+SYMBOL(copy_backward, std::, <algorithm>)
+SYMBOL(copy_if, std::, <algorithm>)
+SYMBOL(copy_n, std::, <algorithm>)
+SYMBOL(copysign, std::, <cmath>)
+SYMBOL(cos, std::, <cmath>)
+SYMBOL(cosh, std::, <cmath>)
+SYMBOL(count, std::, <algorithm>)
+SYMBOL(count_if, std::, <algorithm>)
+SYMBOL(cout, std::, <iostream>)
+SYMBOL(crbegin, std::, <iterator>)
+SYMBOL(cref, std::, <functional>)
+SYMBOL(cregex_iterator, std::, <regex>)
+SYMBOL(cregex_token_iterator, std::, <regex>)
+SYMBOL(crend, std::, <iterator>)
+SYMBOL(csub_match, std::, <regex>)
+SYMBOL(ctime, std::, <ctime>)
+SYMBOL(ctype, std::, <locale>)
+SYMBOL(ctype_base, std::, <locale>)
+SYMBOL(ctype_byname, std::, <locale>)
+SYMBOL(current_exception, std::, <exception>)
+SYMBOL(cv_status, std::, <condition_variable>)
+SYMBOL(data, std::, <iterator>)
+SYMBOL(dec, std::, <ios>)
+SYMBOL(deca, std::, <ratio>)
+SYMBOL(decay, std::, <type_traits>)
+SYMBOL(decay_t, std::, <type_traits>)
+SYMBOL(deci, std::, <ratio>)
+SYMBOL(declare_no_pointers, std::, <memory>)
+SYMBOL(declare_reachable, std::, <memory>)
+SYMBOL(declval, std::, <utility>)
+SYMBOL(default_delete, std::, <memory>)
+SYMBOL(default_random_engine, std::, <random>)
+SYMBOL(default_searcher, std::, <functional>)
+SYMBOL(defaultfloat, std::, <ios>)
+SYMBOL(defer_lock, std::, <mutex>)
+SYMBOL(defer_lock_t, std::, <mutex>)
+SYMBOL(denorm_absent, std::, <limits>)
+SYMBOL(denorm_indeterminate, std::, <limits>)
+SYMBOL(denorm_present, std::, <limits>)
+SYMBOL(deque, std::, <deque>)
+SYMBOL(destroy, std::, <memory>)
+SYMBOL(destroy_at, std::, <memory>)
+SYMBOL(destroy_n, std::, <memory>)
+SYMBOL(destroying_delete, std::, <new>)
+SYMBOL(destroying_delete_t, std::, <new>)
+SYMBOL(difftime, std::, <ctime>)
+SYMBOL(discard_block_engine, std::, <random>)
+SYMBOL(discrete_distribution, std::, <random>)
+SYMBOL(disjunction, std::, <type_traits>)
+SYMBOL(disjunction_v, std::, <type_traits>)
+SYMBOL(distance, std::, <iterator>)
+SYMBOL(div_t, std::, <cstdlib>)
+SYMBOL(divides, std::, <functional>)
+SYMBOL(domain_error, std::, <stdexcept>)
+SYMBOL(double_t, std::, <cmath>)
+SYMBOL(dynamic_extent, std::, <span>)
+SYMBOL(dynamic_pointer_cast, std::, <memory>)
+SYMBOL(emit_on_flush, std::, <ostream>)
+SYMBOL(empty, std::, <iterator>)
+SYMBOL(enable_if, std::, <type_traits>)
+SYMBOL(enable_if_t, std::, <type_traits>)
+SYMBOL(enable_shared_from_this, std::, <memory>)
+SYMBOL(end, std::, <iterator>)
+SYMBOL(endian, std::, <type_traits>)
+SYMBOL(endl, std::, <ostream>)
+SYMBOL(ends, std::, <ostream>)
+SYMBOL(equal, std::, <algorithm>)
+SYMBOL(equal_range, std::, <algorithm>)
+SYMBOL(equal_to, std::, <functional>)
+SYMBOL(erf, std::, <cmath>)
+SYMBOL(erfc, std::, <cmath>)
+SYMBOL(errc, std::, <system_error>)
+SYMBOL(error_category, std::, <system_error>)
+SYMBOL(error_code, std::, <system_error>)
+SYMBOL(error_condition, std::, <system_error>)
+SYMBOL(exa, std::, <ratio>)
+SYMBOL(exception, std::, <exception>)
+SYMBOL(exception_ptr, std::, <exception>)
+SYMBOL(exchange, std::, <utility>)
+SYMBOL(exclusive_scan, std::, <numeric>)
+SYMBOL(exit, std::, <cstdlib>)
+SYMBOL(exp, std::, <cmath>)
+SYMBOL(exp2, std::, <cmath>)
+SYMBOL(expm1, std::, <cmath>)
+SYMBOL(exponential_distribution, std::, <random>)
+SYMBOL(extent, std::, <type_traits>)
+SYMBOL(extent_v, std::, <type_traits>)
+SYMBOL(extreme_value_distribution, std::, <random>)
+SYMBOL(false_type, std::, <type_traits>)
+SYMBOL(fclose, std::, <cstdio>)
+SYMBOL(fdim, std::, <cmath>)
+SYMBOL(feclearexcept, std::, <cfenv>)
+SYMBOL(fegetenv, std::, <cfenv>)
+SYMBOL(fegetexceptflag, std::, <cfenv>)
+SYMBOL(fegetround, std::, <cfenv>)
+SYMBOL(feholdexcept, std::, <cfenv>)
+SYMBOL(femto, std::, <ratio>)
+SYMBOL(fenv_t, std::, <cfenv>)
+SYMBOL(feof, std::, <cstdio>)
+SYMBOL(feraiseexcept, std::, <cfenv>)
+SYMBOL(ferror, std::, <cstdio>)
+SYMBOL(fesetenv, std::, <cfenv>)
+SYMBOL(fesetexceptflag, std::, <cfenv>)
+SYMBOL(fesetround, std::, <cfenv>)
+SYMBOL(fetestexcept, std::, <cfenv>)
+SYMBOL(feupdateenv, std::, <cfenv>)
+SYMBOL(fexcept_t, std::, <cfenv>)
+SYMBOL(fflush, std::, <cstdio>)
+SYMBOL(fgetc, std::, <cstdio>)
+SYMBOL(fgetpos, std::, <cstdio>)
+SYMBOL(fgets, std::, <cstdio>)
+SYMBOL(fgetwc, std::, <cwchar>)
+SYMBOL(fgetws, std::, <cwchar>)
+SYMBOL(filebuf, std::, <streambuf>)
+SYMBOL(fill, std::, <algorithm>)
+SYMBOL(fill_n, std::, <algorithm>)
+SYMBOL(find, std::, <algorithm>)
+SYMBOL(find_end, std::, <algorithm>)
+SYMBOL(find_first_of, std::, <algorithm>)
+SYMBOL(find_if, std::, <algorithm>)
+SYMBOL(find_if_not, std::, <algorithm>)
+SYMBOL(fisher_f_distribution, std::, <random>)
+SYMBOL(fixed, std::, <ios>)
+SYMBOL(float_denorm_style, std::, <limits>)
+SYMBOL(float_round_style, std::, <limits>)
+SYMBOL(float_t, std::, <cmath>)
+SYMBOL(floor, std::, <cmath>)
+SYMBOL(floor2, std::, <bit>)
+SYMBOL(flush, std::, <ostream>)
+SYMBOL(flush_emit, std::, <ostream>)
+SYMBOL(fma, std::, <cmath>)
+SYMBOL(fmax, std::, <cmath>)
+SYMBOL(fmin, std::, <cmath>)
+SYMBOL(fmod, std::, <cmath>)
+SYMBOL(fopen, std::, <cstdio>)
+SYMBOL(for_each, std::, <algorithm>)
+SYMBOL(for_each_n, std::, <algorithm>)
+SYMBOL(forward, std::, <utility>)
+SYMBOL(forward_as_tuple, std::, <tuple>)
+SYMBOL(forward_iterator_tag, std::, <iterator>)
+SYMBOL(forward_list, std::, <forward_list>)
+SYMBOL(fpclassify, std::, <cmath>)
+SYMBOL(fpos, std::, <ios>)
+SYMBOL(fpos_t, std::, <cstdio>)
+SYMBOL(fprintf, std::, <cstdio>)
+SYMBOL(fputc, std::, <cstdio>)
+SYMBOL(fputs, std::, <cstdio>)
+SYMBOL(fputwc, std::, <cwchar>)
+SYMBOL(fputws, std::, <cwchar>)
+SYMBOL(fread, std::, <cstdio>)
+SYMBOL(free, std::, <cstdlib>)
+SYMBOL(freopen, std::, <cstdio>)
+SYMBOL(frexp, std::, <cmath>)
+SYMBOL(from_chars, std::, <charconv>)
+SYMBOL(front_insert_iterator, std::, <iterator>)
+SYMBOL(front_inserter, std::, <iterator>)
+SYMBOL(fscanf, std::, <cstdio>)
+SYMBOL(fseek, std::, <cstdio>)
+SYMBOL(fsetpos, std::, <cstdio>)
+SYMBOL(fstream, std::, <fstream>)
+SYMBOL(ftell, std::, <cstdio>)
+SYMBOL(function, std::, <functional>)
+SYMBOL(future, std::, <future>)
+SYMBOL(future_category, std::, <future>)
+SYMBOL(future_errc, std::, <future>)
+SYMBOL(future_error, std::, <future>)
+SYMBOL(future_status, std::, <future>)
+SYMBOL(fwide, std::, <cwchar>)
+SYMBOL(fwprintf, std::, <cwchar>)
+SYMBOL(fwrite, std::, <cstdio>)
+SYMBOL(fwscanf, std::, <cwchar>)
+SYMBOL(gamma_distribution, std::, <random>)
+SYMBOL(gcd, std::, <numeric>)
+SYMBOL(generate, std::, <algorithm>)
+SYMBOL(generate_canonical, std::, <random>)
+SYMBOL(generate_n, std::, <algorithm>)
+SYMBOL(generic_category, std::, <system_error>)
+SYMBOL(geometric_distribution, std::, <random>)
+SYMBOL(get_if, std::, <variant>)
+SYMBOL(get_money, std::, <iomanip>)
+SYMBOL(get_new_handler, std::, <new>)
+SYMBOL(get_pointer_safety, std::, <memory>)
+SYMBOL(get_terminate, std::, <exception>)
+SYMBOL(get_time, std::, <iomanip>)
+SYMBOL(getc, std::, <cstdio>)
+SYMBOL(getchar, std::, <cstdio>)
+SYMBOL(getenv, std::, <cstdlib>)
+SYMBOL(gets, std::, <cstdio>)
+SYMBOL(getwc, std::, <cwchar>)
+SYMBOL(getwchar, std::, <cwchar>)
+SYMBOL(giga, std::, <ratio>)
+SYMBOL(gmtime, std::, <ctime>)
+SYMBOL(greater, std::, <functional>)
+SYMBOL(greater_equal, std::, <functional>)
+SYMBOL(gslice, std::, <valarray>)
+SYMBOL(gslice_array, std::, <valarray>)
+SYMBOL(hardware_constructive_interference_size, std::, <new>)
+SYMBOL(hardware_destructive_interference_size, std::, <new>)
+SYMBOL(has_facet, std::, <locale>)
+SYMBOL(has_unique_object_representations, std::, <type_traits>)
+SYMBOL(has_unique_object_representations_v, std::, <type_traits>)
+SYMBOL(has_virtual_destructor, std::, <type_traits>)
+SYMBOL(has_virtual_destructor_v, std::, <type_traits>)
+SYMBOL(hash, std::, <functional>)
+SYMBOL(hecto, std::, <ratio>)
+SYMBOL(hex, std::, <ios>)
+SYMBOL(hexfloat, std::, <ios>)
+SYMBOL(holds_alternative, std::, <variant>)
+SYMBOL(hypot, std::, <cmath>)
+SYMBOL(identity, std::, <functional>)
+SYMBOL(ifstream, std::, <fstream>)
+SYMBOL(ignore, std::, <tuple>)
+SYMBOL(ilogb, std::, <cmath>)
+SYMBOL(imag, std::, <complex>)
+SYMBOL(imaxabs, std::, <cinttypes>)
+SYMBOL(imaxdiv, std::, <cinttypes>)
+SYMBOL(imaxdiv_t, std::, <cinttypes>)
+SYMBOL(in_place, std::, <utility>)
+SYMBOL(in_place_index, std::, <utility>)
+SYMBOL(in_place_index_t, std::, <utility>)
+SYMBOL(in_place_t, std::, <utility>)
+SYMBOL(in_place_type, std::, <utility>)
+SYMBOL(in_place_type_t, std::, <utility>)
+SYMBOL(includes, std::, <algorithm>)
+SYMBOL(inclusive_scan, std::, <numeric>)
+SYMBOL(independent_bits_engine, std::, <random>)
+SYMBOL(indirect_array, std::, <valarray>)
+SYMBOL(inner_product, std::, <numeric>)
+SYMBOL(inplace_merge, std::, <algorithm>)
+SYMBOL(input_iterator_tag, std::, <iterator>)
+SYMBOL(insert_iterator, std::, <iterator>)
+SYMBOL(inserter, std::, <iterator>)
+SYMBOL(integer_sequence, std::, <utility>)
+SYMBOL(integral_constant, std::, <type_traits>)
+SYMBOL(internal, std::, <ios>)
+SYMBOL(intmax_t, std::, <cstdint>)
+SYMBOL(intptr_t, std::, <cstdint>)
+SYMBOL(invalid_argument, std::, <stdexcept>)
+SYMBOL(invoke, std::, <functional>)
+SYMBOL(invoke_result, std::, <type_traits>)
+SYMBOL(invoke_result_t, std::, <type_traits>)
+SYMBOL(io_errc, std::, <ios>)
+SYMBOL(ios, std::, <ios>)
+SYMBOL(ios_base, std::, <ios>)
+SYMBOL(iostream, std::, <istream>)
+SYMBOL(iostream_category, std::, <ios>)
+SYMBOL(iota, std::, <numeric>)
+SYMBOL(is_abstract, std::, <type_traits>)
+SYMBOL(is_abstract_v, std::, <type_traits>)
+SYMBOL(is_aggregate, std::, <type_traits>)
+SYMBOL(is_aggregate_v, std::, <type_traits>)
+SYMBOL(is_arithmetic, std::, <type_traits>)
+SYMBOL(is_arithmetic_v, std::, <type_traits>)
+SYMBOL(is_array, std::, <type_traits>)
+SYMBOL(is_array_v, std::, <type_traits>)
+SYMBOL(is_assignable, std::, <type_traits>)
+SYMBOL(is_assignable_v, std::, <type_traits>)
+SYMBOL(is_base_of, std::, <type_traits>)
+SYMBOL(is_base_of_v, std::, <type_traits>)
+SYMBOL(is_bind_expression, std::, <functional>)
+SYMBOL(is_bind_expression_v, std::, <functional>)
+SYMBOL(is_class, std::, <type_traits>)
+SYMBOL(is_class_v, std::, <type_traits>)
+SYMBOL(is_compound, std::, <type_traits>)
+SYMBOL(is_compound_v, std::, <type_traits>)
+SYMBOL(is_const, std::, <type_traits>)
+SYMBOL(is_const_v, std::, <type_traits>)
+SYMBOL(is_constructible, std::, <type_traits>)
+SYMBOL(is_constructible_v, std::, <type_traits>)
+SYMBOL(is_convertible, std::, <type_traits>)
+SYMBOL(is_convertible_v, std::, <type_traits>)
+SYMBOL(is_copy_assignable, std::, <type_traits>)
+SYMBOL(is_copy_assignable_v, std::, <type_traits>)
+SYMBOL(is_copy_constructible, std::, <type_traits>)
+SYMBOL(is_copy_constructible_v, std::, <type_traits>)
+SYMBOL(is_default_constructible, std::, <type_traits>)
+SYMBOL(is_default_constructible_v, std::, <type_traits>)
+SYMBOL(is_destructible, std::, <type_traits>)
+SYMBOL(is_destructible_v, std::, <type_traits>)
+SYMBOL(is_empty, std::, <type_traits>)
+SYMBOL(is_empty_v, std::, <type_traits>)
+SYMBOL(is_enum, std::, <type_traits>)
+SYMBOL(is_enum_v, std::, <type_traits>)
+SYMBOL(is_eq, std::, <compare>)
+SYMBOL(is_error_code_enum, std::, <system_error>)
+SYMBOL(is_error_condition_enum, std::, <system_error>)
+SYMBOL(is_error_condition_enum_v, std::, <system_error>)
+SYMBOL(is_execution_policy, std::, <execution>)
+SYMBOL(is_execution_policy_v, std::, <execution>)
+SYMBOL(is_final, std::, <type_traits>)
+SYMBOL(is_final_v, std::, <type_traits>)
+SYMBOL(is_floating_point, std::, <type_traits>)
+SYMBOL(is_floating_point_v, std::, <type_traits>)
+SYMBOL(is_function, std::, <type_traits>)
+SYMBOL(is_function_v, std::, <type_traits>)
+SYMBOL(is_fundamental, std::, <type_traits>)
+SYMBOL(is_fundamental_v, std::, <type_traits>)
+SYMBOL(is_gt, std::, <compare>)
+SYMBOL(is_gteq, std::, <compare>)
+SYMBOL(is_heap, std::, <algorithm>)
+SYMBOL(is_heap_until, std::, <algorithm>)
+SYMBOL(is_integral, std::, <type_traits>)
+SYMBOL(is_integral_v, std::, <type_traits>)
+SYMBOL(is_invocable, std::, <type_traits>)
+SYMBOL(is_invocable_r, std::, <type_traits>)
+SYMBOL(is_invocable_r_v, std::, <type_traits>)
+SYMBOL(is_invocable_v, std::, <type_traits>)
+SYMBOL(is_lt, std::, <compare>)
+SYMBOL(is_lteq, std::, <compare>)
+SYMBOL(is_lvalue_reference, std::, <type_traits>)
+SYMBOL(is_lvalue_reference_v, std::, <type_traits>)
+SYMBOL(is_member_function_pointer, std::, <type_traits>)
+SYMBOL(is_member_function_pointer_v, std::, <type_traits>)
+SYMBOL(is_member_object_pointer, std::, <type_traits>)
+SYMBOL(is_member_object_pointer_v, std::, <type_traits>)
+SYMBOL(is_member_pointer, std::, <type_traits>)
+SYMBOL(is_member_pointer_v, std::, <type_traits>)
+SYMBOL(is_move_assignable, std::, <type_traits>)
+SYMBOL(is_move_assignable_v, std::, <type_traits>)
+SYMBOL(is_move_constructible, std::, <type_traits>)
+SYMBOL(is_move_constructible_v, std::, <type_traits>)
+SYMBOL(is_neq, std::, <compare>)
+SYMBOL(is_nothrow_assignable, std::, <type_traits>)
+SYMBOL(is_nothrow_assignable_v, std::, <type_traits>)
+SYMBOL(is_nothrow_constructible, std::, <type_traits>)
+SYMBOL(is_nothrow_constructible_v, std::, <type_traits>)
+SYMBOL(is_nothrow_copy_assignable, std::, <type_traits>)
+SYMBOL(is_nothrow_copy_assignable_v, std::, <type_traits>)
+SYMBOL(is_nothrow_copy_constructible, std::, <type_traits>)
+SYMBOL(is_nothrow_copy_constructible_v, std::, <type_traits>)
+SYMBOL(is_nothrow_default_constructible, std::, <type_traits>)
+SYMBOL(is_nothrow_default_constructible_v, std::, <type_traits>)
+SYMBOL(is_nothrow_destructible, std::, <type_traits>)
+SYMBOL(is_nothrow_destructible_v, std::, <type_traits>)
+SYMBOL(is_nothrow_invocable, std::, <type_traits>)
+SYMBOL(is_nothrow_invocable_r, std::, <type_traits>)
+SYMBOL(is_nothrow_invocable_r_v, std::, <type_traits>)
+SYMBOL(is_nothrow_invocable_v, std::, <type_traits>)
+SYMBOL(is_nothrow_move_assignable, std::, <type_traits>)
+SYMBOL(is_nothrow_move_assignable_v, std::, <type_traits>)
+SYMBOL(is_nothrow_move_constructible, std::, <type_traits>)
+SYMBOL(is_nothrow_move_constructible_v, std::, <type_traits>)
+SYMBOL(is_nothrow_swappable, std::, <type_traits>)
+SYMBOL(is_nothrow_swappable_v, std::, <type_traits>)
+SYMBOL(is_nothrow_swappable_with, std::, <type_traits>)
+SYMBOL(is_nothrow_swappable_with_v, std::, <type_traits>)
+SYMBOL(is_null_pointer, std::, <type_traits>)
+SYMBOL(is_null_pointer_v, std::, <type_traits>)
+SYMBOL(is_object, std::, <type_traits>)
+SYMBOL(is_object_v, std::, <type_traits>)
+SYMBOL(is_partitioned, std::, <algorithm>)
+SYMBOL(is_permutation, std::, <algorithm>)
+SYMBOL(is_placeholder, std::, <functional>)
+SYMBOL(is_placeholder_v, std::, <functional>)
+SYMBOL(is_pod, std::, <type_traits>)
+SYMBOL(is_pod_v, std::, <type_traits>)
+SYMBOL(is_pointer, std::, <type_traits>)
+SYMBOL(is_pointer_v, std::, <type_traits>)
+SYMBOL(is_polymorphic, std::, <type_traits>)
+SYMBOL(is_polymorphic_v, std::, <type_traits>)
+SYMBOL(is_reference, std::, <type_traits>)
+SYMBOL(is_reference_v, std::, <type_traits>)
+SYMBOL(is_rvalue_reference, std::, <type_traits>)
+SYMBOL(is_rvalue_reference_v, std::, <type_traits>)
+SYMBOL(is_same, std::, <type_traits>)
+SYMBOL(is_same_v, std::, <type_traits>)
+SYMBOL(is_scalar, std::, <type_traits>)
+SYMBOL(is_scalar_v, std::, <type_traits>)
+SYMBOL(is_signed, std::, <type_traits>)
+SYMBOL(is_signed_v, std::, <type_traits>)
+SYMBOL(is_sorted, std::, <algorithm>)
+SYMBOL(is_sorted_until, std::, <algorithm>)
+SYMBOL(is_standard_layout, std::, <type_traits>)
+SYMBOL(is_standard_layout_v, std::, <type_traits>)
+SYMBOL(is_swappable, std::, <type_traits>)
+SYMBOL(is_swappable_v, std::, <type_traits>)
+SYMBOL(is_swappable_with, std::, <type_traits>)
+SYMBOL(is_swappable_with_v, std::, <type_traits>)
+SYMBOL(is_trivial, std::, <type_traits>)
+SYMBOL(is_trivial_v, std::, <type_traits>)
+SYMBOL(is_trivially_assignable, std::, <type_traits>)
+SYMBOL(is_trivially_assignable_v, std::, <type_traits>)
+SYMBOL(is_trivially_constructible, std::, <type_traits>)
+SYMBOL(is_trivially_constructible_v, std::, <type_traits>)
+SYMBOL(is_trivially_copy_assignable, std::, <type_traits>)
+SYMBOL(is_trivially_copy_assignable_v, std::, <type_traits>)
+SYMBOL(is_trivially_copy_constructible, std::, <type_traits>)
+SYMBOL(is_trivially_copy_constructible_v, std::, <type_traits>)
+SYMBOL(is_trivially_copyable, std::, <type_traits>)
+SYMBOL(is_trivially_copyable_v, std::, <type_traits>)
+SYMBOL(is_trivially_default_constructible, std::, <type_traits>)
+SYMBOL(is_trivially_default_constructible_v, std::, <type_traits>)
+SYMBOL(is_trivially_destructible, std::, <type_traits>)
+SYMBOL(is_trivially_destructible_v, std::, <type_traits>)
+SYMBOL(is_trivially_move_assignable, std::, <type_traits>)
+SYMBOL(is_trivially_move_assignable_v, std::, <type_traits>)
+SYMBOL(is_trivially_move_constructible, std::, <type_traits>)
+SYMBOL(is_trivially_move_constructible_v, std::, <type_traits>)
+SYMBOL(is_union, std::, <type_traits>)
+SYMBOL(is_union_v, std::, <type_traits>)
+SYMBOL(is_unsigned, std::, <type_traits>)
+SYMBOL(is_unsigned_v, std::, <type_traits>)
+SYMBOL(is_void, std::, <type_traits>)
+SYMBOL(is_void_v, std::, <type_traits>)
+SYMBOL(is_volatile, std::, <type_traits>)
+SYMBOL(is_volatile_v, std::, <type_traits>)
+SYMBOL(isalnum, std::, <cctype>)
+SYMBOL(isalpha, std::, <cctype>)
+SYMBOL(isblank, std::, <cctype>)
+SYMBOL(iscntrl, std::, <cctype>)
+SYMBOL(isdigit, std::, <cctype>)
+SYMBOL(isfinite, std::, <cmath>)
+SYMBOL(isgraph, std::, <cctype>)
+SYMBOL(isgreater, std::, <cmath>)
+SYMBOL(isgreaterequal, std::, <cmath>)
+SYMBOL(isinf, std::, <cmath>)
+SYMBOL(isless, std::, <cmath>)
+SYMBOL(islessequal, std::, <cmath>)
+SYMBOL(islessgreater, std::, <cmath>)
+SYMBOL(islower, std::, <cctype>)
+SYMBOL(isnan, std::, <cmath>)
+SYMBOL(isnormal, std::, <cmath>)
+SYMBOL(ispow2, std::, <bit>)
+SYMBOL(isprint, std::, <cctype>)
+SYMBOL(ispunct, std::, <cctype>)
+SYMBOL(isspace, std::, <cctype>)
+SYMBOL(istream, std::, <istream>)
+SYMBOL(istream_iterator, std::, <iterator>)
+SYMBOL(istreambuf_iterator, std::, <iterator>)
+SYMBOL(istringstream, std::, <sstream>)
+SYMBOL(isunordered, std::, <cmath>)
+SYMBOL(isupper, std::, <cctype>)
+SYMBOL(iswalnum, std::, <cwctype>)
+SYMBOL(iswalpha, std::, <cwctype>)
+SYMBOL(iswblank, std::, <cwctype>)
+SYMBOL(iswcntrl, std::, <cwctype>)
+SYMBOL(iswctype, std::, <cwctype>)
+SYMBOL(iswdigit, std::, <cwctype>)
+SYMBOL(iswgraph, std::, <cwctype>)
+SYMBOL(iswlower, std::, <cwctype>)
+SYMBOL(iswprint, std::, <cwctype>)
+SYMBOL(iswpunct, std::, <cwctype>)
+SYMBOL(iswspace, std::, <cwctype>)
+SYMBOL(iswupper, std::, <cwctype>)
+SYMBOL(iswxdigit, std::, <cwctype>)
+SYMBOL(isxdigit, std::, <cctype>)
+SYMBOL(iter_swap, std::, <algorithm>)
+SYMBOL(iterator, std::, <iterator>)
+SYMBOL(iterator_traits, std::, <iterator>)
+SYMBOL(jmp_buf, std::, <csetjmp>)
+SYMBOL(kill_dependency, std::, <atomic>)
+SYMBOL(kilo, std::, <ratio>)
+SYMBOL(knuth_b, std::, <random>)
+SYMBOL(labs, std::, <cstdlib>)
+SYMBOL(launch, std::, <future>)
+SYMBOL(launder, std::, <new>)
+SYMBOL(lcm, std::, <numeric>)
+SYMBOL(lconv, std::, <clocale>)
+SYMBOL(ldexp, std::, <cmath>)
+SYMBOL(ldiv, std::, <cstdlib>)
+SYMBOL(ldiv_t, std::, <cstdlib>)
+SYMBOL(left, std::, <ios>)
+SYMBOL(length_error, std::, <stdexcept>)
+SYMBOL(less, std::, <functional>)
+SYMBOL(less_equal, std::, <functional>)
+SYMBOL(lexicographical_compare, std::, <algorithm>)
+SYMBOL(lexicographical_compare_3way, std::, <algorithm>)
+SYMBOL(lgamma, std::, <cmath>)
+SYMBOL(linear_congruential_engine, std::, <random>)
+SYMBOL(list, std::, <list>)
+SYMBOL(llabs, std::, <cstdlib>)
+SYMBOL(lldiv, std::, <cstdlib>)
+SYMBOL(lldiv_t, std::, <cstdlib>)
+SYMBOL(llrint, std::, <cmath>)
+SYMBOL(llround, std::, <cmath>)
+SYMBOL(locale, std::, <locale>)
+SYMBOL(localeconv, std::, <clocale>)
+SYMBOL(localtime, std::, <ctime>)
+SYMBOL(lock, std::, <mutex>)
+SYMBOL(lock_guard, std::, <mutex>)
+SYMBOL(log, std::, <cmath>)
+SYMBOL(log10, std::, <cmath>)
+SYMBOL(log1p, std::, <cmath>)
+SYMBOL(log2, std::, <cmath>)
+SYMBOL(log2p1, std::, <bit>)
+SYMBOL(logb, std::, <cmath>)
+SYMBOL(logic_error, std::, <stdexcept>)
+SYMBOL(logical_and, std::, <functional>)
+SYMBOL(logical_not, std::, <functional>)
+SYMBOL(logical_or, std::, <functional>)
+SYMBOL(lognormal_distribution, std::, <random>)
+SYMBOL(longjmp, std::, <csetjmp>)
+SYMBOL(lower_bound, std::, <algorithm>)
+SYMBOL(lrint, std::, <cmath>)
+SYMBOL(lround, std::, <cmath>)
+SYMBOL(make_exception_ptr, std::, <exception>)
+SYMBOL(make_from_tuple, std::, <tuple>)
+SYMBOL(make_heap, std::, <algorithm>)
+SYMBOL(make_move_iterator, std::, <iterator>)
+SYMBOL(make_optional, std::, <optional>)
+SYMBOL(make_pair, std::, <utility>)
+SYMBOL(make_reverse_iterator, std::, <iterator>)
+SYMBOL(make_shared, std::, <memory>)
+SYMBOL(make_signed, std::, <type_traits>)
+SYMBOL(make_signed_t, std::, <type_traits>)
+SYMBOL(make_tuple, std::, <tuple>)
+SYMBOL(make_unique, std::, <memory>)
+SYMBOL(make_unsigned, std::, <type_traits>)
+SYMBOL(make_unsigned_t, std::, <type_traits>)
+SYMBOL(malloc, std::, <cstdlib>)
+SYMBOL(map, std::, <map>)
+SYMBOL(mask_array, std::, <valarray>)
+SYMBOL(match_results, std::, <regex>)
+SYMBOL(max, std::, <algorithm>)
+SYMBOL(max_align_t, std::, <cstddef>)
+SYMBOL(max_element, std::, <algorithm>)
+SYMBOL(mblen, std::, <cstdlib>)
+SYMBOL(mbrlen, std::, <cwchar>)
+SYMBOL(mbrtoc16, std::, <cuchar>)
+SYMBOL(mbrtoc32, std::, <cuchar>)
+SYMBOL(mbrtowc, std::, <cwchar>)
+SYMBOL(mbsinit, std::, <cwchar>)
+SYMBOL(mbsrtowcs, std::, <cwchar>)
+SYMBOL(mbstowcs, std::, <cstdlib>)
+SYMBOL(mbtowc, std::, <cstdlib>)
+SYMBOL(mega, std::, <ratio>)
+SYMBOL(mem_fn, std::, <functional>)
+SYMBOL(memchr, std::, <cstring>)
+SYMBOL(memcmp, std::, <cstring>)
+SYMBOL(memcpy, std::, <cstring>)
+SYMBOL(memmove, std::, <cstring>)
+SYMBOL(memory_order, std::, <atomic>)
+SYMBOL(memory_order_acq_rel, std::, <atomic>)
+SYMBOL(memory_order_acquire, std::, <atomic>)
+SYMBOL(memory_order_consume, std::, <atomic>)
+SYMBOL(memory_order_relaxed, std::, <atomic>)
+SYMBOL(memory_order_release, std::, <atomic>)
+SYMBOL(memory_order_seq_cst, std::, <atomic>)
+SYMBOL(memset, std::, <cstring>)
+SYMBOL(merge, std::, <algorithm>)
+SYMBOL(mersenne_twister_engine, std::, <random>)
+SYMBOL(messages, std::, <locale>)
+SYMBOL(messages_base, std::, <locale>)
+SYMBOL(messages_byname, std::, <locale>)
+SYMBOL(micro, std::, <ratio>)
+SYMBOL(milli, std::, <ratio>)
+SYMBOL(min, std::, <algorithm>)
+SYMBOL(min_element, std::, <algorithm>)
+SYMBOL(minmax, std::, <algorithm>)
+SYMBOL(minmax_element, std::, <algorithm>)
+SYMBOL(minstd_rand, std::, <random>)
+SYMBOL(minstd_rand0, std::, <random>)
+SYMBOL(minus, std::, <functional>)
+SYMBOL(mismatch, std::, <algorithm>)
+SYMBOL(mktime, std::, <ctime>)
+SYMBOL(modf, std::, <cmath>)
+SYMBOL(modulus, std::, <functional>)
+SYMBOL(money_base, std::, <locale>)
+SYMBOL(money_get, std::, <locale>)
+SYMBOL(money_put, std::, <locale>)
+SYMBOL(moneypunct, std::, <locale>)
+SYMBOL(moneypunct_byname, std::, <locale>)
+SYMBOL(monostate, std::, <variant>)
+SYMBOL(move_backward, std::, <algorithm>)
+SYMBOL(move_if_noexcept, std::, <utility>)
+SYMBOL(move_iterator, std::, <iterator>)
+SYMBOL(mt19937, std::, <random>)
+SYMBOL(mt19937_64, std::, <random>)
+SYMBOL(multimap, std::, <map>)
+SYMBOL(multiplies, std::, <functional>)
+SYMBOL(multiset, std::, <set>)
+SYMBOL(mutex, std::, <mutex>)
+SYMBOL(nan, std::, <cmath>)
+SYMBOL(nanf, std::, <cmath>)
+SYMBOL(nanl, std::, <cmath>)
+SYMBOL(nano, std::, <ratio>)
+SYMBOL(nearbyint, std::, <cmath>)
+SYMBOL(negate, std::, <functional>)
+SYMBOL(negation, std::, <type_traits>)
+SYMBOL(negation_v, std::, <type_traits>)
+SYMBOL(negative_binomial_distribution, std::, <random>)
+SYMBOL(nested_exception, std::, <exception>)
+SYMBOL(new_handler, std::, <new>)
+SYMBOL(next, std::, <iterator>)
+SYMBOL(next_permutation, std::, <algorithm>)
+SYMBOL(nextafter, std::, <cmath>)
+SYMBOL(nexttoward, std::, <cmath>)
+SYMBOL(no_emit_on_flush, std::, <ostream>)
+SYMBOL(noboolalpha, std::, <ios>)
+SYMBOL(none_of, std::, <algorithm>)
+SYMBOL(norm, std::, <complex>)
+SYMBOL(normal_distribution, std::, <random>)
+SYMBOL(noshowbase, std::, <ios>)
+SYMBOL(noshowpoint, std::, <ios>)
+SYMBOL(noshowpos, std::, <ios>)
+SYMBOL(noskipws, std::, <ios>)
+SYMBOL(not_equal_to, std::, <functional>)
+SYMBOL(not_fn, std::, <functional>)
+SYMBOL(nothrow, std::, <new>)
+SYMBOL(nothrow_t, std::, <new>)
+SYMBOL(notify_all_at_thread_exit, std::, <condition_variable>)
+SYMBOL(nounitbuf, std::, <ios>)
+SYMBOL(nouppercase, std::, <ios>)
+SYMBOL(nth_element, std::, <algorithm>)
+SYMBOL(nullopt, std::, <optional>)
+SYMBOL(nullopt_t, std::, <optional>)
+SYMBOL(nullptr_t, std::, <cstddef>)
+SYMBOL(num_get, std::, <locale>)
+SYMBOL(num_put, std::, <locale>)
+SYMBOL(numeric_limits, std::, <limits>)
+SYMBOL(numpunct, std::, <locale>)
+SYMBOL(numpunct_byname, std::, <locale>)
+SYMBOL(oct, std::, <ios>)
+SYMBOL(ofstream, std::, <fstream>)
+SYMBOL(once_flag, std::, <mutex>)
+SYMBOL(optional, std::, <optional>)
+SYMBOL(ostream, std::, <ostream>)
+SYMBOL(ostream_iterator, std::, <iterator>)
+SYMBOL(ostreambuf_iterator, std::, <iterator>)
+SYMBOL(ostringstream, std::, <sstream>)
+SYMBOL(osyncstream, std::, <syncstream>)
+SYMBOL(out_of_range, std::, <stdexcept>)
+SYMBOL(output_iterator_tag, std::, <iterator>)
+SYMBOL(overflow_error, std::, <stdexcept>)
+SYMBOL(owner_less, std::, <memory>)
+SYMBOL(packaged_task, std::, <future>)
+SYMBOL(pair, std::, <utility>)
+SYMBOL(partial_order, std::, <compare>)
+SYMBOL(partial_ordering, std::, <compare>)
+SYMBOL(partial_sort, std::, <algorithm>)
+SYMBOL(partial_sort_copy, std::, <algorithm>)
+SYMBOL(partial_sum, std::, <numeric>)
+SYMBOL(partition, std::, <algorithm>)
+SYMBOL(partition_copy, std::, <algorithm>)
+SYMBOL(partition_point, std::, <algorithm>)
+SYMBOL(perror, std::, <cstdio>)
+SYMBOL(peta, std::, <ratio>)
+SYMBOL(pico, std::, <ratio>)
+SYMBOL(piecewise_constant_distribution, std::, <random>)
+SYMBOL(piecewise_construct_t, std::, <utility>)
+SYMBOL(piecewise_linear_distribution, std::, <random>)
+SYMBOL(plus, std::, <functional>)
+SYMBOL(pointer_safety, std::, <memory>)
+SYMBOL(pointer_traits, std::, <memory>)
+SYMBOL(poisson_distribution, std::, <random>)
+SYMBOL(polar, std::, <complex>)
+SYMBOL(polymorphic_allocator, std::, <memory_resource>)
+SYMBOL(pop_heap, std::, <algorithm>)
+SYMBOL(pow, std::, <cmath>)
+SYMBOL(prev, std::, <iterator>)
+SYMBOL(prev_permutation, std::, <algorithm>)
+SYMBOL(printf, std::, <cstdio>)
+SYMBOL(priority_queue, std::, <queue>)
+SYMBOL(proj, std::, <complex>)
+SYMBOL(promise, std::, <future>)
+SYMBOL(ptrdiff_t, std::, <cstddef>)
+SYMBOL(push_heap, std::, <algorithm>)
+SYMBOL(put_money, std::, <iomanip>)
+SYMBOL(put_time, std::, <iomanip>)
+SYMBOL(putc, std::, <cstdio>)
+SYMBOL(putchar, std::, <cstdio>)
+SYMBOL(puts, std::, <cstdio>)
+SYMBOL(putwc, std::, <cwchar>)
+SYMBOL(putwchar, std::, <cwchar>)
+SYMBOL(qsort, std::, <cstdlib>)
+SYMBOL(queue, std::, <queue>)
+SYMBOL(quick_exit, std::, <cstdlib>)
+SYMBOL(quoted, std::, <iomanip>)
+SYMBOL(raise, std::, <csignal>)
+SYMBOL(rand, std::, <cstdlib>)
+SYMBOL(random_access_iterator_tag, std::, <iterator>)
+SYMBOL(random_device, std::, <random>)
+SYMBOL(random_shuffle, std::, <algorithm>)
+SYMBOL(range_error, std::, <stdexcept>)
+SYMBOL(rank, std::, <type_traits>)
+SYMBOL(rank_v, std::, <type_traits>)
+SYMBOL(ranlux24, std::, <random>)
+SYMBOL(ranlux24_base, std::, <random>)
+SYMBOL(ranlux48, std::, <random>)
+SYMBOL(ranlux48_base, std::, <random>)
+SYMBOL(ratio, std::, <ratio>)
+SYMBOL(ratio_add, std::, <ratio>)
+SYMBOL(ratio_divide, std::, <ratio>)
+SYMBOL(ratio_equal, std::, <ratio>)
+SYMBOL(ratio_equal_v, std::, <ratio>)
+SYMBOL(ratio_greater, std::, <ratio>)
+SYMBOL(ratio_greater_equal, std::, <ratio>)
+SYMBOL(ratio_greater_equal_v, std::, <ratio>)
+SYMBOL(ratio_greater_v, std::, <ratio>)
+SYMBOL(ratio_less, std::, <ratio>)
+SYMBOL(ratio_less_equal, std::, <ratio>)
+SYMBOL(ratio_less_equal_v, std::, <ratio>)
+SYMBOL(ratio_less_v, std::, <ratio>)
+SYMBOL(ratio_multiply, std::, <ratio>)
+SYMBOL(ratio_not_equal, std::, <ratio>)
+SYMBOL(ratio_not_equal_v, std::, <ratio>)
+SYMBOL(ratio_subtract, std::, <ratio>)
+SYMBOL(rbegin, std::, <iterator>)
+SYMBOL(real, std::, <complex>)
+SYMBOL(realloc, std::, <cstdlib>)
+SYMBOL(recursive_mutex, std::, <mutex>)
+SYMBOL(recursive_timed_mutex, std::, <mutex>)
+SYMBOL(reduce, std::, <numeric>)
+SYMBOL(ref, std::, <functional>)
+SYMBOL(reference_wrapper, std::, <functional>)
+SYMBOL(regex, std::, <regex>)
+SYMBOL(regex_error, std::, <regex>)
+SYMBOL(regex_iterator, std::, <regex>)
+SYMBOL(regex_match, std::, <regex>)
+SYMBOL(regex_replace, std::, <regex>)
+SYMBOL(regex_search, std::, <regex>)
+SYMBOL(regex_token_iterator, std::, <regex>)
+SYMBOL(regex_traits, std::, <regex>)
+SYMBOL(reinterpret_pointer_cast, std::, <memory>)
+SYMBOL(remainder, std::, <cmath>)
+SYMBOL(remove, std::, <cstdio>)
+SYMBOL(remove_all_extents, std::, <type_traits>)
+SYMBOL(remove_all_extents_t, std::, <type_traits>)
+SYMBOL(remove_const, std::, <type_traits>)
+SYMBOL(remove_const_t, std::, <type_traits>)
+SYMBOL(remove_copy, std::, <algorithm>)
+SYMBOL(remove_copy_if, std::, <algorithm>)
+SYMBOL(remove_cv, std::, <type_traits>)
+SYMBOL(remove_cv_t, std::, <type_traits>)
+SYMBOL(remove_cvref, std::, <type_traits>)
+SYMBOL(remove_cvref_t, std::, <type_traits>)
+SYMBOL(remove_extent, std::, <type_traits>)
+SYMBOL(remove_extent_t, std::, <type_traits>)
+SYMBOL(remove_pointer, std::, <type_traits>)
+SYMBOL(remove_pointer_t, std::, <type_traits>)
+SYMBOL(remove_reference, std::, <type_traits>)
+SYMBOL(remove_reference_t, std::, <type_traits>)
+SYMBOL(remove_volatile, std::, <type_traits>)
+SYMBOL(remove_volatile_t, std::, <type_traits>)
+SYMBOL(remquo, std::, <cmath>)
+SYMBOL(rename, std::, <cstdio>)
+SYMBOL(rend, std::, <iterator>)
+SYMBOL(replace, std::, <algorithm>)
+SYMBOL(replace_copy, std::, <algorithm>)
+SYMBOL(replace_copy_if, std::, <algorithm>)
+SYMBOL(replace_if, std::, <algorithm>)
+SYMBOL(resetiosflags, std::, <iomanip>)
+SYMBOL(result_of, std::, <type_traits>)
+SYMBOL(result_of_t, std::, <type_traits>)
+SYMBOL(rethrow_exception, std::, <exception>)
+SYMBOL(rethrow_if_nested, std::, <exception>)
+SYMBOL(reverse, std::, <algorithm>)
+SYMBOL(reverse_copy, std::, <algorithm>)
+SYMBOL(reverse_iterator, std::, <iterator>)
+SYMBOL(rewind, std::, <cstdio>)
+SYMBOL(right, std::, <ios>)
+SYMBOL(rint, std::, <cmath>)
+SYMBOL(rotate, std::, <algorithm>)
+SYMBOL(rotate_copy, std::, <algorithm>)
+SYMBOL(round, std::, <cmath>)
+SYMBOL(round_indeterminate, std::, <limits>)
+SYMBOL(round_to_nearest, std::, <limits>)
+SYMBOL(round_toward_infinity, std::, <limits>)
+SYMBOL(round_toward_neg_infinity, std::, <limits>)
+SYMBOL(round_toward_zero, std::, <limits>)
+SYMBOL(runtime_error, std::, <stdexcept>)
+SYMBOL(sample, std::, <algorithm>)
+SYMBOL(scalbln, std::, <cmath>)
+SYMBOL(scalbn, std::, <cmath>)
+SYMBOL(scanf, std::, <cstdio>)
+SYMBOL(scientific, std::, <ios>)
+SYMBOL(scoped_allocator_adaptor, std::, <scoped_allocator>)
+SYMBOL(search, std::, <algorithm>)
+SYMBOL(search_n, std::, <algorithm>)
+SYMBOL(seed_seq, std::, <random>)
+SYMBOL(set, std::, <set>)
+SYMBOL(set_difference, std::, <algorithm>)
+SYMBOL(set_intersection, std::, <algorithm>)
+SYMBOL(set_new_handler, std::, <new>)
+SYMBOL(set_symmetric_difference, std::, <algorithm>)
+SYMBOL(set_terminate, std::, <exception>)
+SYMBOL(set_union, std::, <algorithm>)
+SYMBOL(setbase, std::, <iomanip>)
+SYMBOL(setbuf, std::, <cstdio>)
+SYMBOL(setfill, std::, <iomanip>)
+SYMBOL(setiosflags, std::, <iomanip>)
+SYMBOL(setlocale, std::, <clocale>)
+SYMBOL(setprecision, std::, <iomanip>)
+SYMBOL(setvbuf, std::, <cstdio>)
+SYMBOL(setw, std::, <iomanip>)
+SYMBOL(shared_future, std::, <future>)
+SYMBOL(shared_lock, std::, <shared_mutex>)
+SYMBOL(shared_mutex, std::, <shared_mutex>)
+SYMBOL(shared_ptr, std::, <memory>)
+SYMBOL(shared_timed_mutex, std::, <shared_mutex>)
+SYMBOL(shift_left, std::, <algorithm>)
+SYMBOL(shift_right, std::, <algorithm>)
+SYMBOL(showbase, std::, <ios>)
+SYMBOL(showpoint, std::, <ios>)
+SYMBOL(showpos, std::, <ios>)
+SYMBOL(shuffle, std::, <algorithm>)
+SYMBOL(shuffle_order_engine, std::, <random>)
+SYMBOL(sig_atomic_t, std::, <csignal>)
+SYMBOL(signal, std::, <csignal>)
+SYMBOL(signbit, std::, <cmath>)
+SYMBOL(sin, std::, <cmath>)
+SYMBOL(sinh, std::, <cmath>)
+SYMBOL(size, std::, <iterator>)
+SYMBOL(skipws, std::, <ios>)
+SYMBOL(slice, std::, <valarray>)
+SYMBOL(slice_array, std::, <valarray>)
+SYMBOL(smatch, std::, <regex>)
+SYMBOL(snprintf, std::, <cstdio>)
+SYMBOL(sort, std::, <algorithm>)
+SYMBOL(sort_heap, std::, <algorithm>)
+SYMBOL(span, std::, <span>)
+SYMBOL(sprintf, std::, <cstdio>)
+SYMBOL(sqrt, std::, <cmath>)
+SYMBOL(srand, std::, <cstdlib>)
+SYMBOL(sregex_iterator, std::, <regex>)
+SYMBOL(sregex_token_iterator, std::, <regex>)
+SYMBOL(sscanf, std::, <cstdio>)
+SYMBOL(ssub_match, std::, <regex>)
+SYMBOL(stable_partition, std::, <algorithm>)
+SYMBOL(stable_sort, std::, <algorithm>)
+SYMBOL(stack, std::, <stack>)
+SYMBOL(static_pointer_cast, std::, <memory>)
+SYMBOL(strcat, std::, <cstring>)
+SYMBOL(strchr, std::, <cstring>)
+SYMBOL(strcmp, std::, <cstring>)
+SYMBOL(strcoll, std::, <cstring>)
+SYMBOL(strcpy, std::, <cstring>)
+SYMBOL(strcspn, std::, <cstring>)
+SYMBOL(streambuf, std::, <streambuf>)
+SYMBOL(streamoff, std::, <ios>)
+SYMBOL(streampos, std::, <ios>)
+SYMBOL(streamsize, std::, <ios>)
+SYMBOL(strerror, std::, <cstring>)
+SYMBOL(strftime, std::, <ctime>)
+SYMBOL(string, std::, <string>)
+SYMBOL(string_view, std::, <string_view>)
+SYMBOL(stringbuf, std::, <sstream>)
+SYMBOL(stringstream, std::, <sstream>)
+SYMBOL(strlen, std::, <cstring>)
+SYMBOL(strncat, std::, <cstring>)
+SYMBOL(strncmp, std::, <cstring>)
+SYMBOL(strncpy, std::, <cstring>)
+SYMBOL(strong_equal, std::, <compare>)
+SYMBOL(strong_equality, std::, <compare>)
+SYMBOL(strong_order, std::, <compare>)
+SYMBOL(strong_ordering, std::, <compare>)
+SYMBOL(strpbrk, std::, <cstring>)
+SYMBOL(strrchr, std::, <cstring>)
+SYMBOL(strspn, std::, <cstring>)
+SYMBOL(strstr, std::, <cstring>)
+SYMBOL(strtod, std::, <cstdlib>)
+SYMBOL(strtof, std::, <cstdlib>)
+SYMBOL(strtoimax, std::, <cinttypes>)
+SYMBOL(strtok, std::, <cstring>)
+SYMBOL(strtol, std::, <cstdlib>)
+SYMBOL(strtold, std::, <cstdlib>)
+SYMBOL(strtoll, std::, <cstdlib>)
+SYMBOL(strtoul, std::, <cstdlib>)
+SYMBOL(strtoull, std::, <cstdlib>)
+SYMBOL(strtoumax, std::, <cinttypes>)
+SYMBOL(strxfrm, std::, <cstring>)
+SYMBOL(student_t_distribution, std::, <random>)
+SYMBOL(sub_match, std::, <regex>)
+SYMBOL(subtract_with_carry_engine, std::, <random>)
+SYMBOL(swap_ranges, std::, <algorithm>)
+SYMBOL(swprintf, std::, <cwchar>)
+SYMBOL(swscanf, std::, <cwchar>)
+SYMBOL(syncbuf, std::, <syncstream>)
+SYMBOL(system, std::, <cstdlib>)
+SYMBOL(system_category, std::, <system_error>)
+SYMBOL(system_error, std::, <system_error>)
+SYMBOL(tan, std::, <cmath>)
+SYMBOL(tanh, std::, <cmath>)
+SYMBOL(tera, std::, <ratio>)
+SYMBOL(terminate, std::, <exception>)
+SYMBOL(terminate_handler, std::, <exception>)
+SYMBOL(tgamma, std::, <cmath>)
+SYMBOL(thread, std::, <thread>)
+SYMBOL(throw_with_nested, std::, <exception>)
+SYMBOL(tie, std::, <tuple>)
+SYMBOL(time, std::, <ctime>)
+SYMBOL(time_base, std::, <locale>)
+SYMBOL(time_get, std::, <locale>)
+SYMBOL(time_get_byname, std::, <locale>)
+SYMBOL(time_put, std::, <locale>)
+SYMBOL(time_put_byname, std::, <locale>)
+SYMBOL(time_t, std::, <ctime>)
+SYMBOL(timed_mutex, std::, <mutex>)
+SYMBOL(timespec, std::, <ctime>)
+SYMBOL(timespec_get, std::, <ctime>)
+SYMBOL(tm, std::, <ctime>)
+SYMBOL(tmpfile, std::, <cstdio>)
+SYMBOL(tmpnam, std::, <cstdio>)
+SYMBOL(to_address, std::, <memory>)
+SYMBOL(to_chars, std::, <charconv>)
+SYMBOL(to_integer, std::, <cstddef>)
+SYMBOL(to_string, std::, <string>)
+SYMBOL(tolower, std::, <cctype>)
+SYMBOL(toupper, std::, <cctype>)
+SYMBOL(towctrans, std::, <cwctype>)
+SYMBOL(towlower, std::, <cwctype>)
+SYMBOL(towupper, std::, <cwctype>)
+SYMBOL(transform, std::, <algorithm>)
+SYMBOL(transform_exclusive_scan, std::, <numeric>)
+SYMBOL(transform_inclusive_scan, std::, <numeric>)
+SYMBOL(transform_reduce, std::, <numeric>)
+SYMBOL(true_type, std::, <type_traits>)
+SYMBOL(trunc, std::, <cmath>)
+SYMBOL(try_lock, std::, <mutex>)
+SYMBOL(try_to_lock, std::, <mutex>)
+SYMBOL(try_to_lock_t, std::, <mutex>)
+SYMBOL(tuple, std::, <tuple>)
+SYMBOL(tuple_cat, std::, <tuple>)
+SYMBOL(type_identity, std::, <type_traits>)
+SYMBOL(type_identity_t, std::, <type_traits>)
+SYMBOL(type_index, std::, <typeindex>)
+SYMBOL(type_info, std::, <typeinfo>)
+SYMBOL(u16streampos, std::, <ios>)
+SYMBOL(u16string, std::, <string>)
+SYMBOL(u16string_view, std::, <string_view>)
+SYMBOL(u32streampos, std::, <ios>)
+SYMBOL(u32string, std::, <string>)
+SYMBOL(u32string_view, std::, <string_view>)
+SYMBOL(uintmax_t, std::, <cstdint>)
+SYMBOL(uintptr_t, std::, <cstdint>)
+SYMBOL(uncaught_exceptions, std::, <exception>)
+SYMBOL(undeclare_no_pointers, std::, <memory>)
+SYMBOL(undeclare_reachable, std::, <memory>)
+SYMBOL(underflow_error, std::, <stdexcept>)
+SYMBOL(underlying_type, std::, <type_traits>)
+SYMBOL(underlying_type_t, std::, <type_traits>)
+SYMBOL(ungetc, std::, <cstdio>)
+SYMBOL(ungetwc, std::, <cwchar>)
+SYMBOL(uniform_int_distribution, std::, <random>)
+SYMBOL(uniform_real_distribution, std::, <random>)
+SYMBOL(uninitialized_copy, std::, <memory>)
+SYMBOL(uninitialized_copy_n, std::, <memory>)
+SYMBOL(uninitialized_default_construct, std::, <memory>)
+SYMBOL(uninitialized_default_construct_n, std::, <memory>)
+SYMBOL(uninitialized_fill, std::, <memory>)
+SYMBOL(uninitialized_fill_n, std::, <memory>)
+SYMBOL(uninitialized_move, std::, <memory>)
+SYMBOL(uninitialized_move_n, std::, <memory>)
+SYMBOL(uninitialized_value_construct, std::, <memory>)
+SYMBOL(uninitialized_value_construct_n, std::, <memory>)
+SYMBOL(unique, std::, <algorithm>)
+SYMBOL(unique_copy, std::, <algorithm>)
+SYMBOL(unique_lock, std::, <mutex>)
+SYMBOL(unique_ptr, std::, <memory>)
+SYMBOL(unitbuf, std::, <ios>)
+SYMBOL(unordered_map, std::, <unordered_map>)
+SYMBOL(unordered_multimap, std::, <unordered_map>)
+SYMBOL(unordered_multiset, std::, <unordered_set>)
+SYMBOL(unordered_set, std::, <unordered_set>)
+SYMBOL(upper_bound, std::, <algorithm>)
+SYMBOL(uppercase, std::, <ios>)
+SYMBOL(use_facet, std::, <locale>)
+SYMBOL(uses_allocator, std::, <memory>)
+SYMBOL(uses_allocator_v, std::, <memory>)
+SYMBOL(va_list, std::, <cstdarg>)
+SYMBOL(valarray, std::, <valarray>)
+SYMBOL(variant, std::, <variant>)
+SYMBOL(variant_alternative, std::, <variant>)
+SYMBOL(variant_alternative_t, std::, <variant>)
+SYMBOL(variant_npos, std::, <variant>)
+SYMBOL(variant_size, std::, <variant>)
+SYMBOL(variant_size_v, std::, <variant>)
+SYMBOL(vector, std::, <vector>)
+SYMBOL(vfprintf, std::, <cstdio>)
+SYMBOL(vfscanf, std::, <cstdio>)
+SYMBOL(vfwprintf, std::, <cwchar>)
+SYMBOL(vfwscanf, std::, <cwchar>)
+SYMBOL(visit, std::, <variant>)
+SYMBOL(void_t, std::, <type_traits>)
+SYMBOL(vprintf, std::, <cstdio>)
+SYMBOL(vscanf, std::, <cstdio>)
+SYMBOL(vsnprintf, std::, <cstdio>)
+SYMBOL(vsprintf, std::, <cstdio>)
+SYMBOL(vsscanf, std::, <cstdio>)
+SYMBOL(vswprintf, std::, <cwchar>)
+SYMBOL(vswscanf, std::, <cwchar>)
+SYMBOL(vwprintf, std::, <cwchar>)
+SYMBOL(vwscanf, std::, <cwchar>)
+SYMBOL(wbuffer_convert, std::, <locale>)
+SYMBOL(wcerr, std::, <iostream>)
+SYMBOL(wcin, std::, <iostream>)
+SYMBOL(wclog, std::, <iostream>)
+SYMBOL(wcmatch, std::, <regex>)
+SYMBOL(wcout, std::, <iostream>)
+SYMBOL(wcregex_iterator, std::, <regex>)
+SYMBOL(wcregex_token_iterator, std::, <regex>)
+SYMBOL(wcrtomb, std::, <cwchar>)
+SYMBOL(wcscat, std::, <cwchar>)
+SYMBOL(wcschr, std::, <cwchar>)
+SYMBOL(wcscmp, std::, <cwchar>)
+SYMBOL(wcscoll, std::, <cwchar>)
+SYMBOL(wcscpy, std::, <cwchar>)
+SYMBOL(wcscspn, std::, <cwchar>)
+SYMBOL(wcsftime, std::, <cwchar>)
+SYMBOL(wcslen, std::, <cwchar>)
+SYMBOL(wcsncat, std::, <cwchar>)
+SYMBOL(wcsncmp, std::, <cwchar>)
+SYMBOL(wcsncpy, std::, <cwchar>)
+SYMBOL(wcspbrk, std::, <cwchar>)
+SYMBOL(wcsrchr, std::, <cwchar>)
+SYMBOL(wcsrtombs, std::, <cwchar>)
+SYMBOL(wcsspn, std::, <cwchar>)
+SYMBOL(wcsstr, std::, <cwchar>)
+SYMBOL(wcstod, std::, <cwchar>)
+SYMBOL(wcstof, std::, <cwchar>)
+SYMBOL(wcstoimax, std::, <cinttypes>)
+SYMBOL(wcstok, std::, <cwchar>)
+SYMBOL(wcstol, std::, <cwchar>)
+SYMBOL(wcstold, std::, <cwchar>)
+SYMBOL(wcstoll, std::, <cwchar>)
+SYMBOL(wcstombs, std::, <cstdlib>)
+SYMBOL(wcstoul, std::, <cwchar>)
+SYMBOL(wcstoull, std::, <cwchar>)
+SYMBOL(wcstoumax, std::, <cinttypes>)
+SYMBOL(wcsub_match, std::, <regex>)
+SYMBOL(wcsxfrm, std::, <cwchar>)
+SYMBOL(wctob, std::, <cwchar>)
+SYMBOL(wctomb, std::, <cstdlib>)
+SYMBOL(wctrans, std::, <cwctype>)
+SYMBOL(wctrans_t, std::, <cwctype>)
+SYMBOL(wctype, std::, <cwctype>)
+SYMBOL(wctype_t, std::, <cwctype>)
+SYMBOL(weak_equal, std::, <compare>)
+SYMBOL(weak_equality, std::, <compare>)
+SYMBOL(weak_order, std::, <compare>)
+SYMBOL(weak_ordering, std::, <compare>)
+SYMBOL(weak_ptr, std::, <memory>)
+SYMBOL(weibull_distribution, std::, <random>)
+SYMBOL(wfilebuf, std::, <streambuf>)
+SYMBOL(wfstream, std::, <fstream>)
+SYMBOL(wifstream, std::, <fstream>)
+SYMBOL(wios, std::, <ios>)
+SYMBOL(wiostream, std::, <istream>)
+SYMBOL(wistream, std::, <istream>)
+SYMBOL(wistringstream, std::, <sstream>)
+SYMBOL(wmemchr, std::, <cwchar>)
+SYMBOL(wmemcmp, std::, <cwchar>)
+SYMBOL(wmemcpy, std::, <cwchar>)
+SYMBOL(wmemmove, std::, <cwchar>)
+SYMBOL(wmemset, std::, <cwchar>)
+SYMBOL(wofstream, std::, <fstream>)
+SYMBOL(wostream, std::, <ostream>)
+SYMBOL(wostringstream, std::, <sstream>)
+SYMBOL(wosyncstream, std::, <syncstream>)
+SYMBOL(wprintf, std::, <cwchar>)
+SYMBOL(wregex, std::, <regex>)
+SYMBOL(ws, std::, <istream>)
+SYMBOL(wscanf, std::, <cwchar>)
+SYMBOL(wsmatch, std::, <regex>)
+SYMBOL(wsregex_iterator, std::, <regex>)
+SYMBOL(wsregex_token_iterator, std::, <regex>)
+SYMBOL(wssub_match, std::, <regex>)
+SYMBOL(wstreambuf, std::, <streambuf>)
+SYMBOL(wstreampos, std::, <ios>)
+SYMBOL(wstring, std::, <string>)
+SYMBOL(wstring_convert, std::, <locale>)
+SYMBOL(wstring_view, std::, <string_view>)
+SYMBOL(wstringbuf, std::, <sstream>)
+SYMBOL(wstringstream, std::, <sstream>)
+SYMBOL(wsyncbuf, std::, <syncstream>)
+SYMBOL(yocto, std::, <ratio>)
+SYMBOL(yotta, std::, <ratio>)
+SYMBOL(zepto, std::, <ratio>)
+SYMBOL(zetta, std::, <ratio>)
+SYMBOL(April, std::chrono::, <chrono>)
+SYMBOL(August, std::chrono::, <chrono>)
+SYMBOL(December, std::chrono::, <chrono>)
+SYMBOL(February, std::chrono::, <chrono>)
+SYMBOL(Friday, std::chrono::, <chrono>)
+SYMBOL(January, std::chrono::, <chrono>)
+SYMBOL(July, std::chrono::, <chrono>)
+SYMBOL(June, std::chrono::, <chrono>)
+SYMBOL(March, std::chrono::, <chrono>)
+SYMBOL(May, std::chrono::, <chrono>)
+SYMBOL(Monday, std::chrono::, <chrono>)
+SYMBOL(November, std::chrono::, <chrono>)
+SYMBOL(October, std::chrono::, <chrono>)
+SYMBOL(Saturday, std::chrono::, <chrono>)
+SYMBOL(September, std::chrono::, <chrono>)
+SYMBOL(Sunday, std::chrono::, <chrono>)
+SYMBOL(Thursday, std::chrono::, <chrono>)
+SYMBOL(Tuesday, std::chrono::, <chrono>)
+SYMBOL(Wednesday, std::chrono::, <chrono>)
+SYMBOL(abs, std::chrono::, <chrono>)
+SYMBOL(ambiguous_local_time, std::chrono::, <chrono>)
+SYMBOL(ceil, std::chrono::, <chrono>)
+SYMBOL(choose, std::chrono::, <chrono>)
+SYMBOL(clock_cast, std::chrono::, <chrono>)
+SYMBOL(clock_time_conversion, std::chrono::, <chrono>)
+SYMBOL(current_zone, std::chrono::, <chrono>)
+SYMBOL(day, std::chrono::, <chrono>)
+SYMBOL(duration, std::chrono::, <chrono>)
+SYMBOL(duration_values, std::chrono::, <chrono>)
+SYMBOL(file_clock, std::chrono::, <chrono>)
+SYMBOL(file_seconds, std::chrono::, <chrono>)
+SYMBOL(file_time, std::chrono::, <chrono>)
+SYMBOL(floor, std::chrono::, <chrono>)
+SYMBOL(gps_clock, std::chrono::, <chrono>)
+SYMBOL(gps_seconds, std::chrono::, <chrono>)
+SYMBOL(gps_time, std::chrono::, <chrono>)
+SYMBOL(high_resolution_clock, std::chrono::, <chrono>)
+SYMBOL(hours, std::chrono::, <chrono>)
+SYMBOL(is_clock, std::chrono::, <chrono>)
+SYMBOL(is_clock_v, std::chrono::, <chrono>)
+SYMBOL(last, std::chrono::, <chrono>)
+SYMBOL(last_spec, std::chrono::, <chrono>)
+SYMBOL(leap, std::chrono::, <chrono>)
+SYMBOL(link, std::chrono::, <chrono>)
+SYMBOL(local_info, std::chrono::, <chrono>)
+SYMBOL(local_seconds, std::chrono::, <chrono>)
+SYMBOL(local_t, std::chrono::, <chrono>)
+SYMBOL(local_time, std::chrono::, <chrono>)
+SYMBOL(locate_zone, std::chrono::, <chrono>)
+SYMBOL(microseconds, std::chrono::, <chrono>)
+SYMBOL(milliseconds, std::chrono::, <chrono>)
+SYMBOL(minutes, std::chrono::, <chrono>)
+SYMBOL(month, std::chrono::, <chrono>)
+SYMBOL(month_day, std::chrono::, <chrono>)
+SYMBOL(month_day_last, std::chrono::, <chrono>)
+SYMBOL(month_weekday, std::chrono::, <chrono>)
+SYMBOL(month_weekday_last, std::chrono::, <chrono>)
+SYMBOL(nanoseconds, std::chrono::, <chrono>)
+SYMBOL(nonexistent_local_time, std::chrono::, <chrono>)
+SYMBOL(round, std::chrono::, <chrono>)
+SYMBOL(seconds, std::chrono::, <chrono>)
+SYMBOL(steady_clock, std::chrono::, <chrono>)
+SYMBOL(sys_days, std::chrono::, <chrono>)
+SYMBOL(sys_info, std::chrono::, <chrono>)
+SYMBOL(sys_seconds, std::chrono::, <chrono>)
+SYMBOL(sys_time, std::chrono::, <chrono>)
+SYMBOL(system_clock, std::chrono::, <chrono>)
+SYMBOL(tai_clock, std::chrono::, <chrono>)
+SYMBOL(tai_seconds, std::chrono::, <chrono>)
+SYMBOL(tai_time, std::chrono::, <chrono>)
+SYMBOL(time_of_day, std::chrono::, <chrono>)
+SYMBOL(time_point, std::chrono::, <chrono>)
+SYMBOL(time_zone, std::chrono::, <chrono>)
+SYMBOL(treat_as_floating_point, std::chrono::, <chrono>)
+SYMBOL(treat_as_floating_point_v, std::chrono::, <chrono>)
+SYMBOL(tzdb, std::chrono::, <chrono>)
+SYMBOL(tzdb_list, std::chrono::, <chrono>)
+SYMBOL(utc_clock, std::chrono::, <chrono>)
+SYMBOL(utc_seconds, std::chrono::, <chrono>)
+SYMBOL(utc_time, std::chrono::, <chrono>)
+SYMBOL(weekday, std::chrono::, <chrono>)
+SYMBOL(weekday_indexed, std::chrono::, <chrono>)
+SYMBOL(weekday_last, std::chrono::, <chrono>)
+SYMBOL(year, std::chrono::, <chrono>)
+SYMBOL(year_month, std::chrono::, <chrono>)
+SYMBOL(year_month_day, std::chrono::, <chrono>)
+SYMBOL(year_month_day_last, std::chrono::, <chrono>)
+SYMBOL(year_month_weekday, std::chrono::, <chrono>)
+SYMBOL(year_month_weekday_last, std::chrono::, <chrono>)
+SYMBOL(zoned_time, std::chrono::, <chrono>)
+SYMBOL(zoned_traits, std::chrono::, <chrono>)
+SYMBOL(absolute, std::filesystem::, <filesystem>)
+SYMBOL(canonical, std::filesystem::, <filesystem>)
+SYMBOL(copy, std::filesystem::, <filesystem>)
+SYMBOL(copy_file, std::filesystem::, <filesystem>)
+SYMBOL(copy_options, std::filesystem::, <filesystem>)
+SYMBOL(copy_symlink, std::filesystem::, <filesystem>)
+SYMBOL(create_directories, std::filesystem::, <filesystem>)
+SYMBOL(create_directory, std::filesystem::, <filesystem>)
+SYMBOL(create_directory_symlink, std::filesystem::, <filesystem>)
+SYMBOL(create_hard_link, std::filesystem::, <filesystem>)
+SYMBOL(create_symlink, std::filesystem::, <filesystem>)
+SYMBOL(current_path, std::filesystem::, <filesystem>)
+SYMBOL(directory_entry, std::filesystem::, <filesystem>)
+SYMBOL(directory_iterator, std::filesystem::, <filesystem>)
+SYMBOL(directory_options, std::filesystem::, <filesystem>)
+SYMBOL(equivalent, std::filesystem::, <filesystem>)
+SYMBOL(exists, std::filesystem::, <filesystem>)
+SYMBOL(file_size, std::filesystem::, <filesystem>)
+SYMBOL(file_status, std::filesystem::, <filesystem>)
+SYMBOL(file_time_type, std::filesystem::, <filesystem>)
+SYMBOL(file_type, std::filesystem::, <filesystem>)
+SYMBOL(filesystem_error, std::filesystem::, <filesystem>)
+SYMBOL(hard_link_count, std::filesystem::, <filesystem>)
+SYMBOL(is_block_file, std::filesystem::, <filesystem>)
+SYMBOL(is_character_file, std::filesystem::, <filesystem>)
+SYMBOL(is_directory, std::filesystem::, <filesystem>)
+SYMBOL(is_empty, std::filesystem::, <filesystem>)
+SYMBOL(is_fifo, std::filesystem::, <filesystem>)
+SYMBOL(is_other, std::filesystem::, <filesystem>)
+SYMBOL(is_regular_file, std::filesystem::, <filesystem>)
+SYMBOL(is_socket, std::filesystem::, <filesystem>)
+SYMBOL(is_symlink, std::filesystem::, <filesystem>)
+SYMBOL(last_write_time, std::filesystem::, <filesystem>)
+SYMBOL(path, std::filesystem::, <filesystem>)
+SYMBOL(perm_options, std::filesystem::, <filesystem>)
+SYMBOL(permissions, std::filesystem::, <filesystem>)
+SYMBOL(perms, std::filesystem::, <filesystem>)
+SYMBOL(proximate, std::filesystem::, <filesystem>)
+SYMBOL(read_symlink, std::filesystem::, <filesystem>)
+SYMBOL(recursive_directory_iterator, std::filesystem::, <filesystem>)
+SYMBOL(relative, std::filesystem::, <filesystem>)
+SYMBOL(remove, std::filesystem::, <filesystem>)
+SYMBOL(remove_all, std::filesystem::, <filesystem>)
+SYMBOL(rename, std::filesystem::, <filesystem>)
+SYMBOL(resize_file, std::filesystem::, <filesystem>)
+SYMBOL(space, std::filesystem::, <filesystem>)
+SYMBOL(space_info, std::filesystem::, <filesystem>)
+SYMBOL(status, std::filesystem::, <filesystem>)
+SYMBOL(status_known, std::filesystem::, <filesystem>)
+SYMBOL(symlink_status, std::filesystem::, <filesystem>)
+SYMBOL(temp_directory_path, std::filesystem::, <filesystem>)
+SYMBOL(u8path, std::filesystem::, <filesystem>)
+SYMBOL(weakly_canonical, std::filesystem::, <filesystem>)
+SYMBOL(basic_string, std::pmr::, <string>)
+SYMBOL(deque, std::pmr::, <deque>)
+SYMBOL(forward_list, std::pmr::, <forward_list>)
+SYMBOL(get_default_resource, std::pmr::, <memory_resource>)
+SYMBOL(list, std::pmr::, <list>)
+SYMBOL(map, std::pmr::, <map>)
+SYMBOL(memory_resource, std::pmr::, <memory_resource>)
+SYMBOL(monotonic_buffer_resource, std::pmr::, <memory_resource>)
+SYMBOL(multimap, std::pmr::, <map>)
+SYMBOL(multiset, std::pmr::, <set>)
+SYMBOL(new_delete_resource, std::pmr::, <memory_resource>)
+SYMBOL(null_memory_resource, std::pmr::, <memory_resource>)
+SYMBOL(polymorphic_allocator, std::pmr::, <memory_resource>)
+SYMBOL(pool_options, std::pmr::, <memory_resource>)
+SYMBOL(set, std::pmr::, <set>)
+SYMBOL(set_default_resource, std::pmr::, <memory_resource>)
+SYMBOL(string, std::pmr::, <string>)
+SYMBOL(synchronized_pool_resource, std::pmr::, <memory_resource>)
+SYMBOL(u16string, std::pmr::, <string>)
+SYMBOL(u32string, std::pmr::, <string>)
+SYMBOL(unordered_map, std::pmr::, <unordered_map>)
+SYMBOL(unordered_multimap, std::pmr::, <unordered_map>)
+SYMBOL(unordered_multiset, std::pmr::, <unordered_set>)
+SYMBOL(unordered_set, std::pmr::, <unordered_set>)
+SYMBOL(unsynchronized_pool_resource, std::pmr::, <memory_resource>)
+SYMBOL(vector, std::pmr::, <vector>)
+SYMBOL(wstring, std::pmr::, <string>)
+SYMBOL(ECMAScript, std::regex_constants::, <regex>)
+SYMBOL(awk, std::regex_constants::, <regex>)
+SYMBOL(basic, std::regex_constants::, <regex>)
+SYMBOL(collate, std::regex_constants::, <regex>)
+SYMBOL(egrep, std::regex_constants::, <regex>)
+SYMBOL(error_backref, std::regex_constants::, <regex>)
+SYMBOL(error_badbrace, std::regex_constants::, <regex>)
+SYMBOL(error_badrepeat, std::regex_constants::, <regex>)
+SYMBOL(error_brace, std::regex_constants::, <regex>)
+SYMBOL(error_brack, std::regex_constants::, <regex>)
+SYMBOL(error_collate, std::regex_constants::, <regex>)
+SYMBOL(error_complexity, std::regex_constants::, <regex>)
+SYMBOL(error_ctype, std::regex_constants::, <regex>)
+SYMBOL(error_escape, std::regex_constants::, <regex>)
+SYMBOL(error_paren, std::regex_constants::, <regex>)
+SYMBOL(error_range, std::regex_constants::, <regex>)
+SYMBOL(error_space, std::regex_constants::, <regex>)
+SYMBOL(error_stack, std::regex_constants::, <regex>)
+SYMBOL(error_type, std::regex_constants::, <regex>)
+SYMBOL(extended, std::regex_constants::, <regex>)
+SYMBOL(format_default, std::regex_constants::, <regex>)
+SYMBOL(format_first_only, std::regex_constants::, <regex>)
+SYMBOL(format_no_copy, std::regex_constants::, <regex>)
+SYMBOL(format_sed, std::regex_constants::, <regex>)
+SYMBOL(grep, std::regex_constants::, <regex>)
+SYMBOL(icase, std::regex_constants::, <regex>)
+SYMBOL(match_any, std::regex_constants::, <regex>)
+SYMBOL(match_continuous, std::regex_constants::, <regex>)
+SYMBOL(match_default, std::regex_constants::, <regex>)
+SYMBOL(match_flag_type, std::regex_constants::, <regex>)
+SYMBOL(match_not_bol, std::regex_constants::, <regex>)
+SYMBOL(match_not_bow, std::regex_constants::, <regex>)
+SYMBOL(match_not_eol, std::regex_constants::, <regex>)
+SYMBOL(match_not_eow, std::regex_constants::, <regex>)
+SYMBOL(match_not_null, std::regex_constants::, <regex>)
+SYMBOL(match_prev_avail, std::regex_constants::, <regex>)
+SYMBOL(multiline, std::regex_constants::, <regex>)
+SYMBOL(nosubs, std::regex_constants::, <regex>)
+SYMBOL(optimize, std::regex_constants::, <regex>)
+SYMBOL(syntax_option_type, std::regex_constants::, <regex>)
+SYMBOL(get_id, std::this_thread::, <thread>)
+SYMBOL(sleep_for, std::this_thread::, <thread>)
+SYMBOL(sleep_until, std::this_thread::, <thread>)
+SYMBOL(yield, std::this_thread::, <thread>)
diff --git a/clangd/TUScheduler.cpp b/clangd/TUScheduler.cpp
index 23264004..c4e555b5 100644
--- a/clangd/TUScheduler.cpp
+++ b/clangd/TUScheduler.cpp
@@ -1,9 +1,8 @@
//===--- TUScheduler.cpp -----------------------------------------*-C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
// For each file, managed by TUScheduler, we create a single ASTWorker that
@@ -44,10 +43,14 @@
#include "TUScheduler.h"
#include "Cancellation.h"
+#include "Compiler.h"
+#include "GlobalCompilationDatabase.h"
#include "Logger.h"
#include "Trace.h"
+#include "index/CanonicalIncludes.h"
#include "clang/Frontend/CompilerInvocation.h"
-#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Path.h"
@@ -62,7 +65,7 @@ using std::chrono::steady_clock;
namespace {
class ASTWorker;
-}
+} // namespace
static clang::clangd::Key<std::string> kFileBeingProcessed;
@@ -154,11 +157,10 @@ class ASTWorkerHandle;
/// worker.
class ASTWorker {
friend class ASTWorkerHandle;
- ASTWorker(PathRef FileName, TUScheduler::ASTCache &LRUCache,
- Semaphore &Barrier, bool RunSync,
- steady_clock::duration UpdateDebounce,
- std::shared_ptr<PCHContainerOperations> PCHs,
- bool StorePreamblesInMemory, ParsingCallbacks &Callbacks);
+ ASTWorker(PathRef FileName, const GlobalCompilationDatabase &CDB,
+ TUScheduler::ASTCache &LRUCache, Semaphore &Barrier, bool RunSync,
+ steady_clock::duration UpdateDebounce, bool StorePreamblesInMemory,
+ ParsingCallbacks &Callbacks);
public:
/// Create a new ASTWorker and return a handle to it.
@@ -166,13 +168,11 @@ public:
/// is null, all requests will be processed on the calling thread
/// synchronously instead. \p Barrier is acquired when processing each
/// request, it is used to limit the number of actively running threads.
- static ASTWorkerHandle create(PathRef FileName,
- TUScheduler::ASTCache &IdleASTs,
- AsyncTaskRunner *Tasks, Semaphore &Barrier,
- steady_clock::duration UpdateDebounce,
- std::shared_ptr<PCHContainerOperations> PCHs,
- bool StorePreamblesInMemory,
- ParsingCallbacks &Callbacks);
+ static ASTWorkerHandle
+ create(PathRef FileName, const GlobalCompilationDatabase &CDB,
+ TUScheduler::ASTCache &IdleASTs, AsyncTaskRunner *Tasks,
+ Semaphore &Barrier, steady_clock::duration UpdateDebounce,
+ bool StorePreamblesInMemory, ParsingCallbacks &Callbacks);
~ASTWorker();
void update(ParseInputs Inputs, WantDiagnostics);
@@ -182,10 +182,14 @@ public:
bool blockUntilIdle(Deadline Timeout) const;
std::shared_ptr<const PreambleData> getPossiblyStalePreamble() const;
+
/// Obtain a preamble reflecting all updates so far. Threadsafe.
/// It may be delivered immediately, or later on the worker thread.
void getCurrentPreamble(
llvm::unique_function<void(std::shared_ptr<const PreambleData>)>);
+ /// Returns compile command from the current file inputs.
+ tooling::CompileCommand getCurrentCompileCommand() const;
+
/// Wait for the first build of preamble to finish. Preamble itself can be
/// accessed via getPossiblyStalePreamble(). Note that this function will
/// return after an unsuccessful build of the preamble too, i.e. result of
@@ -216,6 +220,10 @@ private:
Deadline scheduleLocked();
/// Should the first task in the queue be skipped instead of run?
bool shouldSkipHeadLocked() const;
+ /// This is private because `FileInputs.FS` is not thread-safe and thus not
+ /// safe to share. Callers should make sure not to expose `FS` via a public
+ /// interface.
+ std::shared_ptr<const ParseInputs> getCurrentFileInputs() const;
struct Request {
llvm::unique_function<void()> Action;
@@ -232,24 +240,24 @@ private:
const steady_clock::duration UpdateDebounce;
/// File that ASTWorker is responsible for.
const Path FileName;
+ const GlobalCompilationDatabase &CDB;
/// Whether to keep the built preambles in memory or on disk.
const bool StorePreambleInMemory;
/// Callback invoked when preamble or main file AST is built.
ParsingCallbacks &Callbacks;
- /// Helper class required to build the ASTs.
- const std::shared_ptr<PCHContainerOperations> PCHs;
/// Only accessed by the worker thread.
TUStatus Status;
Semaphore &Barrier;
- /// Inputs, corresponding to the current state of AST.
- ParseInputs FileInputs;
/// Whether the diagnostics for the current FileInputs were reported to the
/// users before.
bool DiagsWereReported = false;
- /// Size of the last AST
/// Guards members used by both TUScheduler and the worker thread.
mutable std::mutex Mutex;
+ /// File inputs, currently being used by the worker.
+ /// Inputs are written and read by the worker thread, compile command can also
+ /// be consumed by clients of ASTWorker.
+ std::shared_ptr<const ParseInputs> FileInputs; /* GUARDED_BY(Mutex) */
std::shared_ptr<const PreambleData> LastBuiltPreamble; /* GUARDED_BY(Mutex) */
/// Becomes ready when the first preamble build finishes.
Notification PreambleWasBuilt;
@@ -310,16 +318,14 @@ private:
std::shared_ptr<ASTWorker> Worker;
};
-ASTWorkerHandle ASTWorker::create(PathRef FileName,
- TUScheduler::ASTCache &IdleASTs,
- AsyncTaskRunner *Tasks, Semaphore &Barrier,
- steady_clock::duration UpdateDebounce,
- std::shared_ptr<PCHContainerOperations> PCHs,
- bool StorePreamblesInMemory,
- ParsingCallbacks &Callbacks) {
- std::shared_ptr<ASTWorker> Worker(new ASTWorker(
- FileName, IdleASTs, Barrier, /*RunSync=*/!Tasks, UpdateDebounce,
- std::move(PCHs), StorePreamblesInMemory, Callbacks));
+ASTWorkerHandle
+ASTWorker::create(PathRef FileName, const GlobalCompilationDatabase &CDB,
+ TUScheduler::ASTCache &IdleASTs, AsyncTaskRunner *Tasks,
+ Semaphore &Barrier, steady_clock::duration UpdateDebounce,
+ bool StorePreamblesInMemory, ParsingCallbacks &Callbacks) {
+ std::shared_ptr<ASTWorker> Worker(
+ new ASTWorker(FileName, CDB, IdleASTs, Barrier, /*RunSync=*/!Tasks,
+ UpdateDebounce, StorePreamblesInMemory, Callbacks));
if (Tasks)
Tasks->runAsync("worker:" + llvm::sys::path::filename(FileName),
[Worker]() { Worker->run(); });
@@ -327,17 +333,23 @@ ASTWorkerHandle ASTWorker::create(PathRef FileName,
return ASTWorkerHandle(std::move(Worker));
}
-ASTWorker::ASTWorker(PathRef FileName, TUScheduler::ASTCache &LRUCache,
- Semaphore &Barrier, bool RunSync,
- steady_clock::duration UpdateDebounce,
- std::shared_ptr<PCHContainerOperations> PCHs,
+ASTWorker::ASTWorker(PathRef FileName, const GlobalCompilationDatabase &CDB,
+ TUScheduler::ASTCache &LRUCache, Semaphore &Barrier,
+ bool RunSync, steady_clock::duration UpdateDebounce,
bool StorePreamblesInMemory, ParsingCallbacks &Callbacks)
: IdleASTs(LRUCache), RunSync(RunSync), UpdateDebounce(UpdateDebounce),
- FileName(FileName), StorePreambleInMemory(StorePreamblesInMemory),
- Callbacks(Callbacks),
- PCHs(std::move(PCHs)), Status{TUAction(TUAction::Idle, ""),
- TUStatus::BuildDetails()},
- Barrier(Barrier), Done(false) {}
+ FileName(FileName), CDB(CDB),
+ StorePreambleInMemory(StorePreamblesInMemory),
+ Callbacks(Callbacks), Status{TUAction(TUAction::Idle, ""),
+ TUStatus::BuildDetails()},
+ Barrier(Barrier), Done(false) {
+ auto Inputs = std::make_shared<ParseInputs>();
+ // Set a fallback command because compile command can be accessed before
+ // `Inputs` is initialized. Other fields are only used after initialization
+ // from client inputs.
+ Inputs->CompileCommand = CDB.getFallbackCommand(FileName);
+ FileInputs = std::move(Inputs);
+}
ASTWorker::~ASTWorker() {
// Make sure we remove the cached AST, if any.
@@ -352,17 +364,32 @@ ASTWorker::~ASTWorker() {
void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
llvm::StringRef TaskName = "Update";
auto Task = [=]() mutable {
+ // Get the actual command as `Inputs` does not have a command.
+ // FIXME: some build systems like Bazel will take time to preparing
+ // environment to build the file, it would be nice if we could emit a
+ // "PreparingBuild" status to inform users, it is non-trivial given the
+ // current implementation.
+ if (auto Cmd = CDB.getCompileCommand(FileName))
+ Inputs.CompileCommand = *Cmd;
+ else
+ // FIXME: consider using old command if it's not a fallback one.
+ Inputs.CompileCommand = CDB.getFallbackCommand(FileName);
+ auto PrevInputs = getCurrentFileInputs();
// Will be used to check if we can avoid rebuilding the AST.
bool InputsAreTheSame =
- std::tie(FileInputs.CompileCommand, FileInputs.Contents) ==
+ std::tie(PrevInputs->CompileCommand, PrevInputs->Contents) ==
std::tie(Inputs.CompileCommand, Inputs.Contents);
- tooling::CompileCommand OldCommand = std::move(FileInputs.CompileCommand);
+ tooling::CompileCommand OldCommand = PrevInputs->CompileCommand;
bool PrevDiagsWereReported = DiagsWereReported;
- FileInputs = Inputs;
+ {
+ std::lock_guard<std::mutex> Lock(Mutex);
+ FileInputs = std::make_shared<ParseInputs>(Inputs);
+ }
DiagsWereReported = false;
emitTUStatus({TUAction::BuildingPreamble, TaskName});
- log("Updating file {0} with command [{1}] {2}", FileName,
+ log("Updating file {0} with command {1}\n[{2}]\n{3}", FileName,
+ Inputs.CompileCommand.Heuristic,
Inputs.CompileCommand.Directory,
llvm::join(Inputs.CompileCommand.CommandLine, " "));
// Rebuild the preamble and the AST.
@@ -384,10 +411,11 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
std::shared_ptr<const PreambleData> OldPreamble =
getPossiblyStalePreamble();
std::shared_ptr<const PreambleData> NewPreamble = buildPreamble(
- FileName, *Invocation, OldPreamble, OldCommand, Inputs, PCHs,
+ FileName, *Invocation, OldPreamble, OldCommand, Inputs,
StorePreambleInMemory,
- [this](ASTContext &Ctx, std::shared_ptr<clang::Preprocessor> PP) {
- Callbacks.onPreambleAST(FileName, Ctx, std::move(PP));
+ [this](ASTContext &Ctx, std::shared_ptr<clang::Preprocessor> PP,
+ const CanonicalIncludes &CanonIncludes) {
+ Callbacks.onPreambleAST(FileName, Ctx, std::move(PP), CanonIncludes);
});
bool CanReuseAST = InputsAreTheSame && (OldPreamble == NewPreamble);
@@ -440,7 +468,7 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
llvm::Optional<std::unique_ptr<ParsedAST>> AST = IdleASTs.take(this);
if (!AST) {
llvm::Optional<ParsedAST> NewAST =
- buildAST(FileName, std::move(Invocation), Inputs, NewPreamble, PCHs);
+ buildAST(FileName, std::move(Invocation), Inputs, NewPreamble);
AST = NewAST ? llvm::make_unique<ParsedAST>(std::move(*NewAST)) : nullptr;
if (!(*AST)) { // buildAST fails.
TUStatus::BuildDetails Details;
@@ -480,15 +508,16 @@ void ASTWorker::runWithAST(
if (isCancelled())
return Action(llvm::make_error<CancelledError>());
llvm::Optional<std::unique_ptr<ParsedAST>> AST = IdleASTs.take(this);
+ auto CurrentInputs = getCurrentFileInputs();
if (!AST) {
std::unique_ptr<CompilerInvocation> Invocation =
- buildCompilerInvocation(FileInputs);
+ buildCompilerInvocation(*CurrentInputs);
// Try rebuilding the AST.
llvm::Optional<ParsedAST> NewAST =
Invocation
? buildAST(FileName,
llvm::make_unique<CompilerInvocation>(*Invocation),
- FileInputs, getPossiblyStalePreamble(), PCHs)
+ *CurrentInputs, getPossiblyStalePreamble())
: None;
AST = NewAST ? llvm::make_unique<ParsedAST>(std::move(*NewAST)) : nullptr;
}
@@ -499,7 +528,7 @@ void ASTWorker::runWithAST(
if (!*AST)
return Action(llvm::make_error<llvm::StringError>(
"invalid AST", llvm::errc::invalid_argument));
- Action(InputsAndAST{FileInputs, **AST});
+ Action(InputsAndAST{*CurrentInputs, **AST});
};
startTask(Name, Bind(Task, std::move(Action)),
/*UpdateType=*/None);
@@ -541,6 +570,16 @@ void ASTWorker::getCurrentPreamble(
void ASTWorker::waitForFirstPreamble() const { PreambleWasBuilt.wait(); }
+std::shared_ptr<const ParseInputs> ASTWorker::getCurrentFileInputs() const {
+ std::unique_lock<std::mutex> Lock(Mutex);
+ return FileInputs;
+}
+
+tooling::CompileCommand ASTWorker::getCurrentCompileCommand() const {
+ std::unique_lock<std::mutex> Lock(Mutex);
+ return FileInputs->CompileCommand;
+}
+
std::size_t ASTWorker::getUsedBytes() const {
// Note that we don't report the size of ASTs currently used for processing
// the in-flight requests. We used this information for debugging purposes
@@ -779,17 +818,16 @@ FileStatus TUStatus::render(PathRef File) const {
struct TUScheduler::FileData {
/// Latest inputs, passed to TUScheduler::update().
std::string Contents;
- tooling::CompileCommand Command;
ASTWorkerHandle Worker;
};
-TUScheduler::TUScheduler(unsigned AsyncThreadsCount,
+TUScheduler::TUScheduler(const GlobalCompilationDatabase &CDB,
+ unsigned AsyncThreadsCount,
bool StorePreamblesInMemory,
std::unique_ptr<ParsingCallbacks> Callbacks,
std::chrono::steady_clock::duration UpdateDebounce,
ASTRetentionPolicy RetentionPolicy)
- : StorePreamblesInMemory(StorePreamblesInMemory),
- PCHOps(std::make_shared<PCHContainerOperations>()),
+ : CDB(CDB), StorePreamblesInMemory(StorePreamblesInMemory),
Callbacks(Callbacks ? move(Callbacks)
: llvm::make_unique<ParsingCallbacks>()),
Barrier(AsyncThreadsCount),
@@ -828,13 +866,13 @@ void TUScheduler::update(PathRef File, ParseInputs Inputs,
if (!FD) {
// Create a new worker to process the AST-related tasks.
ASTWorkerHandle Worker = ASTWorker::create(
- File, *IdleASTs, WorkerThreads ? WorkerThreads.getPointer() : nullptr,
- Barrier, UpdateDebounce, PCHOps, StorePreamblesInMemory, *Callbacks);
- FD = std::unique_ptr<FileData>(new FileData{
- Inputs.Contents, Inputs.CompileCommand, std::move(Worker)});
+ File, CDB, *IdleASTs,
+ WorkerThreads ? WorkerThreads.getPointer() : nullptr, Barrier,
+ UpdateDebounce, StorePreamblesInMemory, *Callbacks);
+ FD = std::unique_ptr<FileData>(
+ new FileData{Inputs.Contents, std::move(Worker)});
} else {
FD->Contents = Inputs.Contents;
- FD->Command = Inputs.CompileCommand;
}
FD->Worker->update(std::move(Inputs), WantDiags);
}
@@ -866,9 +904,9 @@ void TUScheduler::runWithAST(
It->second->Worker->runWithAST(Name, std::move(Action));
}
-void TUScheduler::runWithPreamble(
- llvm::StringRef Name, PathRef File, PreambleConsistency Consistency,
- llvm::unique_function<void(llvm::Expected<InputsAndPreamble>)> Action) {
+void TUScheduler::runWithPreamble(llvm::StringRef Name, PathRef File,
+ PreambleConsistency Consistency,
+ Callback<InputsAndPreamble> Action) {
auto It = Files.find(File);
if (It == Files.end()) {
Action(llvm::make_error<LSPError>(
@@ -882,7 +920,8 @@ void TUScheduler::runWithPreamble(
SPAN_ATTACH(Tracer, "file", File);
std::shared_ptr<const PreambleData> Preamble =
It->second->Worker->getPossiblyStalePreamble();
- Action(InputsAndPreamble{It->second->Contents, It->second->Command,
+ Action(InputsAndPreamble{It->second->Contents,
+ It->second->Worker->getCurrentCompileCommand(),
Preamble.get()});
return;
}
@@ -901,19 +940,21 @@ void TUScheduler::runWithPreamble(
}
std::shared_ptr<const ASTWorker> Worker = It->second->Worker.lock();
- auto Task = [Worker, this](std::string Name, std::string File,
- std::string Contents,
- tooling::CompileCommand Command, Context Ctx,
- decltype(ConsistentPreamble) ConsistentPreamble,
- decltype(Action) Action) mutable {
+ auto Task = [Worker, Consistency,
+ this](std::string Name, std::string File, std::string Contents,
+ tooling::CompileCommand Command, Context Ctx,
+ decltype(ConsistentPreamble) ConsistentPreamble,
+ decltype(Action) Action) mutable {
std::shared_ptr<const PreambleData> Preamble;
if (ConsistentPreamble.valid()) {
Preamble = ConsistentPreamble.get();
} else {
- // We don't want to be running preamble actions before the preamble was
- // built for the first time. This avoids extra work of processing the
- // preamble headers in parallel multiple times.
- Worker->waitForFirstPreamble();
+ if (Consistency != PreambleConsistency::StaleOrAbsent) {
+ // Wait until the preamble is built for the first time, if preamble is
+ // required. This avoids extra work of processing the preamble headers
+ // in parallel multiple times.
+ Worker->waitForFirstPreamble();
+ }
Preamble = Worker->getPossiblyStalePreamble();
}
@@ -927,7 +968,7 @@ void TUScheduler::runWithPreamble(
PreambleTasks->runAsync(
"task:" + llvm::sys::path::filename(File),
Bind(Task, std::string(Name), std::string(File), It->second->Contents,
- It->second->Command,
+ Worker->getCurrentCompileCommand(),
Context::current().derive(kFileBeingProcessed, File),
std::move(ConsistentPreamble), std::move(Action)));
}
diff --git a/clangd/TUScheduler.h b/clangd/TUScheduler.h
index 5ab66d80..dc477901 100644
--- a/clangd/TUScheduler.h
+++ b/clangd/TUScheduler.h
@@ -1,9 +1,8 @@
//===--- TUScheduler.h -------------------------------------------*-C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -12,8 +11,12 @@
#include "ClangdUnit.h"
#include "Function.h"
+#include "GlobalCompilationDatabase.h"
#include "Threading.h"
+#include "index/CanonicalIncludes.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include <future>
namespace clang {
@@ -32,6 +35,7 @@ struct InputsAndAST {
struct InputsAndPreamble {
llvm::StringRef Contents;
const tooling::CompileCommand &Command;
+ // This can be nullptr if no preamble is availble.
const PreambleData *Preamble;
};
@@ -92,7 +96,8 @@ public:
/// contains only AST nodes from the #include directives at the start of the
/// file. AST node in the current file should be observed on onMainAST call.
virtual void onPreambleAST(PathRef Path, ASTContext &Ctx,
- std::shared_ptr<clang::Preprocessor> PP) {}
+ std::shared_ptr<clang::Preprocessor> PP,
+ const CanonicalIncludes &) {}
/// Called on the AST built for the file itself. Note that preamble AST nodes
/// are not deserialized and should be processed in the onPreambleAST call
/// instead.
@@ -121,7 +126,8 @@ public:
/// FIXME(sammccall): pull out a scheduler options struct.
class TUScheduler {
public:
- TUScheduler(unsigned AsyncThreadsCount, bool StorePreamblesInMemory,
+ TUScheduler(const GlobalCompilationDatabase &CDB, unsigned AsyncThreadsCount,
+ bool StorePreamblesInMemory,
std::unique_ptr<ParsingCallbacks> ASTCallbacks,
std::chrono::steady_clock::duration UpdateDebounce,
ASTRetentionPolicy RetentionPolicy);
@@ -137,10 +143,11 @@ public:
std::vector<Path> getFilesWithCachedAST() const;
/// Schedule an update for \p File. Adds \p File to a list of tracked files if
- /// \p File was not part of it before.
- /// If diagnostics are requested (Yes), and the context is cancelled before
- /// they are prepared, they may be skipped if eventual-consistency permits it
- /// (i.e. WantDiagnostics is downgraded to Auto).
+ /// \p File was not part of it before. The compile command in \p Inputs is
+ /// ignored; worker queries CDB to get the actual compile command.
+ /// If diagnostics are requested (Yes), and the context is cancelled
+ /// before they are prepared, they may be skipped if eventual-consistency
+ /// permits it (i.e. WantDiagnostics is downgraded to Auto).
void update(PathRef File, ParseInputs Inputs, WantDiagnostics WD);
/// Remove \p File from the list of tracked files and schedule removal of its
@@ -177,10 +184,14 @@ public:
/// reading source code from headers.
/// This is the fastest option, usually a preamble is available immediately.
Stale,
+ /// Besides accepting stale preamble, this also allow preamble to be absent
+ /// (not ready or failed to build).
+ StaleOrAbsent,
};
+
/// Schedule an async read of the preamble.
- /// If there's no preamble yet (because the file was just opened), we'll wait
- /// for it to build. The result may be null if it fails to build or is empty.
+ /// If there's no up-to-date preamble, we follow the PreambleConsistency
+ /// policy.
/// If an error occurs, it is forwarded to the \p Action callback.
/// Context cancellation is ignored and should be handled by the Action.
/// (In practice, the Action is almost always executed immediately).
@@ -209,8 +220,8 @@ public:
static llvm::Optional<llvm::StringRef> getFileBeingProcessedInContext();
private:
+ const GlobalCompilationDatabase &CDB;
const bool StorePreamblesInMemory;
- const std::shared_ptr<PCHContainerOperations> PCHOps;
std::unique_ptr<ParsingCallbacks> Callbacks; // not nullptr
Semaphore Barrier;
llvm::StringMap<std::unique_ptr<FileData>> Files;
diff --git a/clangd/Threading.cpp b/clangd/Threading.cpp
index 139fcc2f..016a9029 100644
--- a/clangd/Threading.cpp
+++ b/clangd/Threading.cpp
@@ -7,6 +7,10 @@
#include <thread>
#ifdef __USE_POSIX
#include <pthread.h>
+#elif defined(__APPLE__)
+#include <sys/resource.h>
+#elif defined (_WIN32)
+#include <windows.h>
#endif
namespace clang {
@@ -109,22 +113,5 @@ void wait(std::unique_lock<std::mutex> &Lock, std::condition_variable &CV,
CV.wait_until(Lock, D.time());
}
-static std::atomic<bool> AvoidThreadStarvation = {false};
-
-void setCurrentThreadPriority(ThreadPriority Priority) {
- // Some *really* old glibcs are missing SCHED_IDLE.
-#if defined(__linux__) && defined(SCHED_IDLE)
- sched_param priority;
- priority.sched_priority = 0;
- pthread_setschedparam(
- pthread_self(),
- Priority == ThreadPriority::Low && !AvoidThreadStarvation ? SCHED_IDLE
- : SCHED_OTHER,
- &priority);
-#endif
-}
-
-void preventThreadStarvationInTests() { AvoidThreadStarvation = true; }
-
} // namespace clangd
} // namespace clang
diff --git a/clangd/Threading.h b/clangd/Threading.h
index 4c553288..920b2e00 100644
--- a/clangd/Threading.h
+++ b/clangd/Threading.h
@@ -1,9 +1,8 @@
//===--- ThreadPool.h --------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -118,16 +117,6 @@ private:
std::size_t InFlightTasks = 0;
};
-enum class ThreadPriority {
- Low = 0,
- Normal = 1,
-};
-void setCurrentThreadPriority(ThreadPriority Priority);
-// Avoid the use of scheduler policies that may starve low-priority threads.
-// This prevents tests from timing out on loaded systems.
-// Affects subsequent setThreadPriority() calls.
-void preventThreadStarvationInTests();
-
} // namespace clangd
} // namespace clang
#endif
diff --git a/clangd/Trace.cpp b/clangd/Trace.cpp
index e44d3a13..2318d9ca 100644
--- a/clangd/Trace.cpp
+++ b/clangd/Trace.cpp
@@ -1,9 +1,8 @@
//===--- Trace.cpp - Performance tracing facilities -----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -28,13 +27,14 @@ namespace {
// Perhaps we should replace this by something that disturbs performance less.
class JSONTracer : public EventTracer {
public:
- JSONTracer(llvm::raw_ostream &Out, bool Pretty)
- : Out(Out), Sep(""), Start(std::chrono::system_clock::now()),
- JSONFormat(Pretty ? "{0:2}" : "{0}") {
+ JSONTracer(llvm::raw_ostream &OS, bool Pretty)
+ : Out(OS, Pretty ? 2 : 0), Start(std::chrono::system_clock::now()) {
// The displayTimeUnit must be ns to avoid low-precision overlap
// calculations!
- Out << R"({"displayTimeUnit":"ns","traceEvents":[)"
- << "\n";
+ Out.objectBegin();
+ Out.attribute("displayTimeUnit", "ns");
+ Out.attributeBegin("traceEvents");
+ Out.arrayBegin();
rawEvent("M", llvm::json::Object{
{"name", "process_name"},
{"args", llvm::json::Object{{"name", "clangd"}}},
@@ -42,7 +42,9 @@ public:
}
~JSONTracer() {
- Out << "\n]}";
+ Out.arrayEnd();
+ Out.attributeEnd();
+ Out.objectEnd();
Out.flush();
}
@@ -74,7 +76,7 @@ public:
Contents["ts"] = Timestamp ? Timestamp : timestamp();
Contents["tid"] = int64_t(TID);
std::lock_guard<std::mutex> Lock(Mu);
- rawEvent(Phase, std::move(Contents));
+ rawEvent(Phase, Contents);
}
private:
@@ -146,13 +148,14 @@ private:
// Record an event. ph and pid are set.
// Contents must be a list of the other JSON key/values.
void rawEvent(llvm::StringRef Phase,
- llvm::json::Object &&Event) /*REQUIRES(Mu)*/ {
+ const llvm::json::Object &Event) /*REQUIRES(Mu)*/ {
// PID 0 represents the clangd process.
- Event["pid"] = 0;
- Event["ph"] = Phase;
- Out << Sep
- << llvm::formatv(JSONFormat, llvm::json::Value(std::move(Event)));
- Sep = ",\n";
+ Out.object([&]{
+ Out.attribute("pid", 0);
+ Out.attribute("ph", Phase);
+ for (const auto& KV : Event)
+ Out.attribute(KV.first, KV.second);
+ });
}
// If we haven't already, emit metadata describing this thread.
@@ -178,11 +181,9 @@ private:
}
std::mutex Mu;
- llvm::raw_ostream &Out /*GUARDED_BY(Mu)*/;
- const char *Sep /*GUARDED_BY(Mu)*/;
+ llvm::json::OStream Out /*GUARDED_BY(Mu)*/;
llvm::DenseSet<uint64_t> ThreadsWithMD /*GUARDED_BY(Mu)*/;
const llvm::sys::TimePoint<> Start;
- const char *JSONFormat;
};
Key<std::unique_ptr<JSONTracer::JSONSpan>> JSONTracer::SpanKey;
diff --git a/clangd/Trace.h b/clangd/Trace.h
index 4b2f72e7..a36be77a 100644
--- a/clangd/Trace.h
+++ b/clangd/Trace.h
@@ -1,9 +1,8 @@
//===--- Trace.h - Performance tracing facilities ---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clangd/Transport.h b/clangd/Transport.h
index 87fb8f98..1cca573c 100644
--- a/clangd/Transport.h
+++ b/clangd/Transport.h
@@ -1,9 +1,8 @@
//===--- Transport.h - sending and receiving LSP messages -------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -86,7 +85,7 @@ newJSONTransport(std::FILE *In, llvm::raw_ostream &Out,
llvm::raw_ostream *InMirror, bool Pretty,
JSONStreamStyle = JSONStreamStyle::Standard);
-#ifdef CLANGD_BUILD_XPC
+#if CLANGD_BUILD_XPC
// Returns a Transport for macOS based on XPC.
// Clangd with this transport is meant to be run as bundled XPC service.
std::unique_ptr<Transport> newXPCTransport();
diff --git a/clangd/URI.cpp b/clangd/URI.cpp
index 888acb7f..ed6b4d34 100644
--- a/clangd/URI.cpp
+++ b/clangd/URI.cpp
@@ -1,9 +1,8 @@
//===---- URI.h - File URIs with schemes -------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/URI.h b/clangd/URI.h
index cbde008b..110b39af 100644
--- a/clangd/URI.h
+++ b/clangd/URI.h
@@ -1,9 +1,8 @@
//===--- URI.h - File URIs with schemes --------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/XRefs.cpp b/clangd/XRefs.cpp
index 29561dfe..c51631ad 100644
--- a/clangd/XRefs.cpp
+++ b/clangd/XRefs.cpp
@@ -1,19 +1,24 @@
//===--- XRefs.cpp -----------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "XRefs.h"
#include "AST.h"
+#include "FindSymbols.h"
#include "Logger.h"
#include "SourceCode.h"
#include "URI.h"
+#include "index/Merge.h"
+#include "index/SymbolCollector.h"
+#include "index/SymbolLocation.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Type.h"
#include "clang/Index/IndexDataConsumer.h"
+#include "clang/Index/IndexSymbol.h"
#include "clang/Index/IndexingAction.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/Support/Path.h"
@@ -22,18 +27,27 @@ namespace clang {
namespace clangd {
namespace {
-// Get the definition from a given declaration `D`.
-// Return nullptr if no definition is found, or the declaration type of `D` is
-// not supported.
+// Returns the single definition of the entity declared by D, if visible.
+// In particular:
+// - for non-redeclarable kinds (e.g. local vars), return D
+// - for kinds that allow multiple definitions (e.g. namespaces), return nullptr
+// Kinds of nodes that always return nullptr here will not have definitions
+// reported by locateSymbolAt().
const Decl *getDefinition(const Decl *D) {
assert(D);
+ // Decl has one definition that we can find.
if (const auto *TD = dyn_cast<TagDecl>(D))
return TD->getDefinition();
- else if (const auto *VD = dyn_cast<VarDecl>(D))
+ if (const auto *VD = dyn_cast<VarDecl>(D))
return VD->getDefinition();
- else if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
return FD->getDefinition();
- return nullptr;
+ // Only a single declaration is allowed.
+ if (isa<ValueDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
+ isa<TemplateTemplateParmDecl>(D)) // except cases above
+ return D;
+ // Multiple definitions are allowed.
+ return nullptr; // except cases above
}
void logIfOverflow(const SymbolLocation &Loc) {
@@ -70,25 +84,40 @@ llvm::Optional<Location> toLSPLocation(const SymbolLocation &Loc,
return LSPLoc;
}
+SymbolLocation toIndexLocation(const Location &Loc, std::string &URIStorage) {
+ SymbolLocation SymLoc;
+ URIStorage = Loc.uri.uri();
+ SymLoc.FileURI = URIStorage.c_str();
+ SymLoc.Start.setLine(Loc.range.start.line);
+ SymLoc.Start.setColumn(Loc.range.start.character);
+ SymLoc.End.setLine(Loc.range.end.line);
+ SymLoc.End.setColumn(Loc.range.end.character);
+ return SymLoc;
+}
+
+// Returns the preferred location between an AST location and an index location.
+SymbolLocation getPreferredLocation(const Location &ASTLoc,
+ const SymbolLocation &IdxLoc,
+ std::string &Scratch) {
+ // Also use a dummy symbol for the index location so that other fields (e.g.
+ // definition) are not factored into the preferrence.
+ Symbol ASTSym, IdxSym;
+ ASTSym.ID = IdxSym.ID = SymbolID("dummy_id");
+ ASTSym.CanonicalDeclaration = toIndexLocation(ASTLoc, Scratch);
+ IdxSym.CanonicalDeclaration = IdxLoc;
+ auto Merged = mergeSymbol(ASTSym, IdxSym);
+ return Merged.CanonicalDeclaration;
+}
+
struct MacroDecl {
llvm::StringRef Name;
const MacroInfo *Info;
};
-struct DeclInfo {
- const Decl *D;
- // Indicates the declaration is referenced by an explicit AST node.
- bool IsReferencedExplicitly = false;
-};
-
/// Finds declarations locations that a given source location refers to.
class DeclarationAndMacrosFinder : public index::IndexDataConsumer {
std::vector<MacroDecl> MacroInfos;
- // The value of the map indicates whether the declaration has been referenced
- // explicitly in the code.
- // True means the declaration is explicitly referenced at least once; false
- // otherwise.
- llvm::DenseMap<const Decl *, bool> Decls;
+ llvm::DenseSet<const Decl *> Decls;
const SourceLocation &SearchedLocation;
const ASTContext &AST;
Preprocessor &PP;
@@ -98,22 +127,14 @@ public:
ASTContext &AST, Preprocessor &PP)
: SearchedLocation(SearchedLocation), AST(AST), PP(PP) {}
- // Get all DeclInfo of the found declarations.
- // The results are sorted by "IsReferencedExplicitly" and declaration
- // location.
- std::vector<DeclInfo> getFoundDecls() const {
- std::vector<DeclInfo> Result;
- for (auto It : Decls) {
- Result.emplace_back();
- Result.back().D = It.first;
- Result.back().IsReferencedExplicitly = It.second;
- }
+ // The results are sorted by declaration location.
+ std::vector<const Decl *> getFoundDecls() const {
+ std::vector<const Decl *> Result;
+ for (const Decl *D : Decls)
+ Result.push_back(D);
- // Sort results. Declarations being referenced explicitly come first.
- llvm::sort(Result, [](const DeclInfo &L, const DeclInfo &R) {
- if (L.IsReferencedExplicitly != R.IsReferencedExplicitly)
- return L.IsReferencedExplicitly > R.IsReferencedExplicitly;
- return L.D->getBeginLoc() < R.D->getBeginLoc();
+ llvm::sort(Result, [](const Decl *L, const Decl *R) {
+ return L->getBeginLoc() < R->getBeginLoc();
});
return Result;
}
@@ -137,29 +158,33 @@ public:
llvm::ArrayRef<index::SymbolRelation> Relations,
SourceLocation Loc,
index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
+ // Skip non-semantic references.
+ if (Roles & static_cast<unsigned>(index::SymbolRole::NameReference))
+ return true;
+
if (Loc == SearchedLocation) {
- auto isImplicitExpr = [](const Expr *E) {
+ auto IsImplicitExpr = [](const Expr *E) {
if (!E)
return false;
// We assume that a constructor expression is implict (was inserted by
// clang) if it has an invalid paren/brace location, since such
// experssion is impossible to write down.
if (const auto *CtorExpr = dyn_cast<CXXConstructExpr>(E))
- return CtorExpr->getNumArgs() > 0 &&
- CtorExpr->getParenOrBraceRange().isInvalid();
+ return CtorExpr->getParenOrBraceRange().isInvalid();
return isa<ImplicitCastExpr>(E);
};
- bool IsExplicit = !isImplicitExpr(ASTNode.OrigE);
+ if (IsImplicitExpr(ASTNode.OrigE))
+ return true;
// Find and add definition declarations (for GoToDefinition).
// We don't use parameter `D`, as Parameter `D` is the canonical
// declaration, which is the first declaration of a redeclarable
// declaration, and it could be a forward declaration.
if (const auto *Def = getDefinition(D)) {
- Decls[Def] |= IsExplicit;
+ Decls.insert(Def);
} else {
// Couldn't find a definition, fall back to use `D`.
- Decls[D] |= IsExplicit;
+ Decls.insert(D);
}
}
return true;
@@ -197,7 +222,7 @@ private:
};
struct IdentifiedSymbol {
- std::vector<DeclInfo> Decls;
+ std::vector<const Decl *> Decls;
std::vector<MacroDecl> Macros;
};
@@ -208,6 +233,8 @@ IdentifiedSymbol getSymbolAtPosition(ParsedAST &AST, SourceLocation Pos) {
IndexOpts.SystemSymbolFilter =
index::IndexingOptions::SystemSymbolFilterKind::All;
IndexOpts.IndexFunctionLocals = true;
+ IndexOpts.IndexParametersInDeclarations = true;
+ IndexOpts.IndexTemplateParameters = true;
indexTopLevelDecls(AST.getASTContext(), AST.getPreprocessor(),
AST.getLocalTopLevelDecls(), DeclMacrosFinder, IndexOpts);
@@ -241,8 +268,8 @@ llvm::Optional<Location> makeLocation(ParsedAST &AST, SourceLocation TokLoc,
} // namespace
-std::vector<Location> findDefinitions(ParsedAST &AST, Position Pos,
- const SymbolIndex *Index) {
+std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos,
+ const SymbolIndex *Index) {
const auto &SM = AST.getASTContext().getSourceManager();
auto MainFilePath =
getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
@@ -251,116 +278,99 @@ std::vector<Location> findDefinitions(ParsedAST &AST, Position Pos,
return {};
}
- std::vector<Location> Result;
- // Handle goto definition for #include.
+ // Treat #included files as symbols, to enable go-to-definition on them.
for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) {
- if (!Inc.Resolved.empty() && Inc.R.start.line == Pos.line)
- Result.push_back(
- Location{URIForFile::canonicalize(Inc.Resolved, *MainFilePath), {}});
+ if (!Inc.Resolved.empty() && Inc.R.start.line == Pos.line) {
+ LocatedSymbol File;
+ File.Name = llvm::sys::path::filename(Inc.Resolved);
+ File.PreferredDeclaration = {
+ URIForFile::canonicalize(Inc.Resolved, *MainFilePath), Range{}};
+ File.Definition = File.PreferredDeclaration;
+ // We're not going to find any further symbols on #include lines.
+ return {std::move(File)};
+ }
}
- if (!Result.empty())
- return Result;
- // Identified symbols at a specific position.
SourceLocation SourceLocationBeg =
getBeginningOfIdentifier(AST, Pos, SM.getMainFileID());
auto Symbols = getSymbolAtPosition(AST, SourceLocationBeg);
- for (auto Item : Symbols.Macros) {
- auto Loc = Item.Info->getDefinitionLoc();
- auto L = makeLocation(AST, Loc, *MainFilePath);
- if (L)
- Result.push_back(*L);
- }
-
- // Declaration and definition are different terms in C-family languages, and
- // LSP only defines the "GoToDefinition" specification, so we try to perform
- // the "most sensible" GoTo operation:
- //
- // - We use the location from AST and index (if available) to provide the
- // final results. When there are duplicate results, we prefer AST over
- // index because AST is more up-to-date.
- //
- // - For each symbol, we will return a location of the canonical declaration
- // (e.g. function declaration in header), and a location of definition if
- // they are available.
- //
- // So the work flow:
- //
- // 1. Identify the symbols being search for by traversing the AST.
- // 2. Populate one of the locations with the AST location.
- // 3. Use the AST information to query the index, and populate the index
- // location (if available).
- // 4. Return all populated locations for all symbols, definition first (
- // which we think is the users wants most often).
- struct CandidateLocation {
- llvm::Optional<Location> Def;
- llvm::Optional<Location> Decl;
- };
- // We respect the order in Symbols.Decls.
- llvm::SmallVector<CandidateLocation, 8> ResultCandidates;
- llvm::DenseMap<SymbolID, size_t> CandidatesIndex;
+ // Macros are simple: there's no declaration/definition distinction.
+ // As a consequence, there's no need to look them up in the index either.
+ std::vector<LocatedSymbol> Result;
+ for (auto M : Symbols.Macros) {
+ if (auto Loc =
+ makeLocation(AST, M.Info->getDefinitionLoc(), *MainFilePath)) {
+ LocatedSymbol Macro;
+ Macro.Name = M.Name;
+ Macro.PreferredDeclaration = *Loc;
+ Macro.Definition = Loc;
+ Result.push_back(std::move(Macro));
+ }
+ }
+
+ // Decls are more complicated.
+ // The AST contains at least a declaration, maybe a definition.
+ // These are up-to-date, and so generally preferred over index results.
+ // We perform a single batch index lookup to find additional definitions.
+
+ // Results follow the order of Symbols.Decls.
+ // Keep track of SymbolID -> index mapping, to fill in index data later.
+ llvm::DenseMap<SymbolID, size_t> ResultIndex;
// Emit all symbol locations (declaration or definition) from AST.
- for (const DeclInfo &DI : Symbols.Decls) {
- const Decl *D = DI.D;
- // Fake key for symbols don't have USR (no SymbolID).
- // Ideally, there should be a USR for each identified symbols. Symbols
- // without USR are rare and unimportant cases, we use the a fake holder to
- // minimize the invasiveness of these cases.
- SymbolID Key("");
+ for (const Decl *D : Symbols.Decls) {
+ auto Loc = makeLocation(AST, findNameLoc(D), *MainFilePath);
+ if (!Loc)
+ continue;
+
+ Result.emplace_back();
+ if (auto *ND = dyn_cast<NamedDecl>(D))
+ Result.back().Name = printName(AST.getASTContext(), *ND);
+ Result.back().PreferredDeclaration = *Loc;
+ // DeclInfo.D is always a definition if possible, so this check works.
+ if (getDefinition(D) == D)
+ Result.back().Definition = *Loc;
+
+ // Record SymbolID for index lookup later.
if (auto ID = getSymbolID(D))
- Key = *ID;
-
- auto R = CandidatesIndex.try_emplace(Key, ResultCandidates.size());
- if (R.second) // new entry
- ResultCandidates.emplace_back();
- auto &Candidate = ResultCandidates[R.first->second];
-
- auto Loc = findNameLoc(D);
- auto L = makeLocation(AST, Loc, *MainFilePath);
- // The declaration in the identified symbols is a definition if possible
- // otherwise it is declaration.
- bool IsDef = getDefinition(D) == D;
- // Populate one of the slots with location for the AST.
- if (!IsDef)
- Candidate.Decl = L;
- else
- Candidate.Def = L;
+ ResultIndex[*ID] = Result.size() - 1;
}
- if (Index) {
+ // Now query the index for all Symbol IDs we found in the AST.
+ if (Index && !ResultIndex.empty()) {
LookupRequest QueryRequest;
- // Build request for index query, using SymbolID.
- for (auto It : CandidatesIndex)
+ for (auto It : ResultIndex)
QueryRequest.IDs.insert(It.first);
- std::string TUPath;
- const FileEntry *FE = SM.getFileEntryForID(SM.getMainFileID());
- if (auto Path = getCanonicalPath(FE, SM))
- TUPath = *Path;
- // Query the index and populate the empty slot.
- Index->lookup(QueryRequest, [&TUPath, &ResultCandidates,
- &CandidatesIndex](const Symbol &Sym) {
- auto It = CandidatesIndex.find(Sym.ID);
- assert(It != CandidatesIndex.end());
- auto &Value = ResultCandidates[It->second];
-
- if (!Value.Def)
- Value.Def = toLSPLocation(Sym.Definition, TUPath);
- if (!Value.Decl)
- Value.Decl = toLSPLocation(Sym.CanonicalDeclaration, TUPath);
+ std::string Scratch;
+ Index->lookup(QueryRequest, [&](const Symbol &Sym) {
+ auto &R = Result[ResultIndex.lookup(Sym.ID)];
+
+ if (R.Definition) { // from AST
+ // Special case: if the AST yielded a definition, then it may not be
+ // the right *declaration*. Prefer the one from the index.
+ if (auto Loc = toLSPLocation(Sym.CanonicalDeclaration, *MainFilePath))
+ R.PreferredDeclaration = *Loc;
+
+ // We might still prefer the definition from the index, e.g. for
+ // generated symbols.
+ if (auto Loc = toLSPLocation(
+ getPreferredLocation(*R.Definition, Sym.Definition, Scratch),
+ *MainFilePath))
+ R.Definition = *Loc;
+ } else {
+ R.Definition = toLSPLocation(Sym.Definition, *MainFilePath);
+
+ // Use merge logic to choose AST or index declaration.
+ if (auto Loc = toLSPLocation(
+ getPreferredLocation(R.PreferredDeclaration,
+ Sym.CanonicalDeclaration, Scratch),
+ *MainFilePath))
+ R.PreferredDeclaration = *Loc;
+ }
});
}
- // Populate the results, definition first.
- for (const auto &Candidate : ResultCandidates) {
- if (Candidate.Def)
- Result.push_back(*Candidate.Def);
- if (Candidate.Decl &&
- Candidate.Decl != Candidate.Def) // Decl and Def might be the same
- Result.push_back(*Candidate.Decl);
- }
-
return Result;
}
@@ -424,6 +434,8 @@ findRefs(const std::vector<const Decl *> &Decls, ParsedAST &AST) {
IndexOpts.SystemSymbolFilter =
index::IndexingOptions::SystemSymbolFilterKind::All;
IndexOpts.IndexFunctionLocals = true;
+ IndexOpts.IndexParametersInDeclarations = true;
+ IndexOpts.IndexTemplateParameters = true;
indexTopLevelDecls(AST.getASTContext(), AST.getPreprocessor(),
AST.getLocalTopLevelDecls(), RefFinder, IndexOpts);
return std::move(RefFinder).take();
@@ -436,11 +448,7 @@ std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST,
const SourceManager &SM = AST.getASTContext().getSourceManager();
auto Symbols = getSymbolAtPosition(
AST, getBeginningOfIdentifier(AST, Pos, SM.getMainFileID()));
- std::vector<const Decl *> TargetDecls;
- for (const DeclInfo &DI : Symbols.Decls) {
- TargetDecls.push_back(DI.D);
- }
- auto References = findRefs(TargetDecls, AST);
+ auto References = findRefs(Symbols.Decls, AST);
std::vector<DocumentHighlight> Result;
for (const auto &Ref : References) {
@@ -561,13 +569,30 @@ static Hover getHoverContents(QualType T, ASTContext &ASTCtx) {
return H;
}
-/// Generate a \p Hover object given the macro \p MacroInf.
-static Hover getHoverContents(llvm::StringRef MacroName) {
- Hover H;
-
- H.contents.value = "#define ";
- H.contents.value += MacroName;
+/// Generate a \p Hover object given the macro \p MacroDecl.
+static Hover getHoverContents(MacroDecl Decl, ParsedAST &AST) {
+ SourceManager &SM = AST.getASTContext().getSourceManager();
+ std::string Definition = Decl.Name;
+
+ // Try to get the full definition, not just the name
+ SourceLocation StartLoc = Decl.Info->getDefinitionLoc();
+ SourceLocation EndLoc = Decl.Info->getDefinitionEndLoc();
+ if (EndLoc.isValid()) {
+ EndLoc = Lexer::getLocForEndOfToken(EndLoc, 0, SM,
+ AST.getASTContext().getLangOpts());
+ bool Invalid;
+ StringRef Buffer = SM.getBufferData(SM.getFileID(StartLoc), &Invalid);
+ if (!Invalid) {
+ unsigned StartOffset = SM.getFileOffset(StartLoc);
+ unsigned EndOffset = SM.getFileOffset(EndLoc);
+ if (EndOffset <= Buffer.size() && StartOffset < EndOffset)
+ Definition = Buffer.substr(StartOffset, EndOffset - StartOffset).str();
+ }
+ }
+ Hover H;
+ H.contents.kind = MarkupKind::PlainText;
+ H.contents.value = "#define " + Definition;
return H;
}
@@ -691,10 +716,10 @@ llvm::Optional<Hover> getHover(ParsedAST &AST, Position Pos) {
auto Symbols = getSymbolAtPosition(AST, SourceLocationBeg);
if (!Symbols.Macros.empty())
- return getHoverContents(Symbols.Macros[0].Name);
+ return getHoverContents(Symbols.Macros[0], AST);
if (!Symbols.Decls.empty())
- return getHoverContents(Symbols.Decls[0].D);
+ return getHoverContents(Symbols.Decls[0]);
auto DeducedType = getDeducedType(AST, SourceLocationBeg);
if (DeducedType && !DeducedType->isNull())
@@ -718,15 +743,9 @@ std::vector<Location> findReferences(ParsedAST &AST, Position Pos,
auto Loc = getBeginningOfIdentifier(AST, Pos, SM.getMainFileID());
auto Symbols = getSymbolAtPosition(AST, Loc);
- std::vector<const Decl *> TargetDecls;
- for (const DeclInfo &DI : Symbols.Decls) {
- if (DI.IsReferencedExplicitly)
- TargetDecls.push_back(DI.D);
- }
-
// We traverse the AST to find references in the main file.
// TODO: should we handle macros, too?
- auto MainFileRefs = findRefs(TargetDecls, AST);
+ auto MainFileRefs = findRefs(Symbols.Decls, AST);
for (const auto &Ref : MainFileRefs) {
Location Result;
Result.range = getTokenRange(AST, Ref.Loc);
@@ -739,7 +758,7 @@ std::vector<Location> findReferences(ParsedAST &AST, Position Pos,
RefsRequest Req;
Req.Limit = Limit;
- for (const Decl *D : TargetDecls) {
+ for (const Decl *D : Symbols.Decls) {
// Not all symbols can be referenced from outside (e.g. function-locals).
// TODO: we could skip TU-scoped symbols here (e.g. static functions) if
// we know this file isn't a header. The details might be tricky.
@@ -770,9 +789,9 @@ std::vector<SymbolDetails> getSymbolInfo(ParsedAST &AST, Position Pos) {
std::vector<SymbolDetails> Results;
- for (const auto &Sym : Symbols.Decls) {
+ for (const Decl *D : Symbols.Decls) {
SymbolDetails NewSymbol;
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(Sym.D)) {
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
std::string QName = printQualifiedName(*ND);
std::tie(NewSymbol.containerName, NewSymbol.name) =
splitQualifiedName(QName);
@@ -784,7 +803,7 @@ std::vector<SymbolDetails> getSymbolInfo(ParsedAST &AST, Position Pos) {
}
}
llvm::SmallString<32> USR;
- if (!index::generateUSRForDecl(Sym.D, USR)) {
+ if (!index::generateUSRForDecl(D, USR)) {
NewSymbol.USR = USR.str();
NewSymbol.ID = SymbolID(NewSymbol.USR);
}
@@ -795,7 +814,8 @@ std::vector<SymbolDetails> getSymbolInfo(ParsedAST &AST, Position Pos) {
SymbolDetails NewMacro;
NewMacro.name = Macro.Name;
llvm::SmallString<32> USR;
- if (!index::generateUSRForMacro(NewMacro.name, Loc, SM, USR)) {
+ if (!index::generateUSRForMacro(NewMacro.name,
+ Macro.Info->getDefinitionLoc(), SM, USR)) {
NewMacro.USR = USR.str();
NewMacro.ID = SymbolID(NewMacro.USR);
}
@@ -805,5 +825,171 @@ std::vector<SymbolDetails> getSymbolInfo(ParsedAST &AST, Position Pos) {
return Results;
}
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const LocatedSymbol &S) {
+ OS << S.Name << ": " << S.PreferredDeclaration;
+ if (S.Definition)
+ OS << " def=" << *S.Definition;
+ return OS;
+}
+
+// FIXME(nridge): Reduce duplication between this function and declToSym().
+static llvm::Optional<TypeHierarchyItem>
+declToTypeHierarchyItem(ASTContext &Ctx, const NamedDecl &ND) {
+ auto &SM = Ctx.getSourceManager();
+
+ SourceLocation NameLoc = findNameLoc(&ND);
+ // getFileLoc is a good choice for us, but we also need to make sure
+ // sourceLocToPosition won't switch files, so we call getSpellingLoc on top of
+ // that to make sure it does not switch files.
+ // FIXME: sourceLocToPosition should not switch files!
+ SourceLocation BeginLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getBeginLoc()));
+ SourceLocation EndLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getEndLoc()));
+ if (NameLoc.isInvalid() || BeginLoc.isInvalid() || EndLoc.isInvalid())
+ return llvm::None;
+
+ Position NameBegin = sourceLocToPosition(SM, NameLoc);
+ Position NameEnd = sourceLocToPosition(
+ SM, Lexer::getLocForEndOfToken(NameLoc, 0, SM, Ctx.getLangOpts()));
+
+ index::SymbolInfo SymInfo = index::getSymbolInfo(&ND);
+ // FIXME: this is not classifying constructors, destructors and operators
+ // correctly (they're all "methods").
+ SymbolKind SK = indexSymbolKindToSymbolKind(SymInfo.Kind);
+
+ TypeHierarchyItem THI;
+ THI.name = printName(Ctx, ND);
+ THI.kind = SK;
+ THI.deprecated = ND.isDeprecated();
+ THI.range =
+ Range{sourceLocToPosition(SM, BeginLoc), sourceLocToPosition(SM, EndLoc)};
+ THI.selectionRange = Range{NameBegin, NameEnd};
+ if (!THI.range.contains(THI.selectionRange)) {
+ // 'selectionRange' must be contained in 'range', so in cases where clang
+ // reports unrelated ranges we need to reconcile somehow.
+ THI.range = THI.selectionRange;
+ }
+
+ auto FilePath =
+ getCanonicalPath(SM.getFileEntryForID(SM.getFileID(BeginLoc)), SM);
+ auto TUPath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
+ if (!FilePath || !TUPath)
+ return llvm::None; // Not useful without a uri.
+ THI.uri = URIForFile::canonicalize(*FilePath, *TUPath);
+
+ return THI;
+}
+
+using RecursionProtectionSet = llvm::SmallSet<const CXXRecordDecl *, 4>;
+
+static Optional<TypeHierarchyItem>
+getTypeAncestors(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx,
+ RecursionProtectionSet &RPSet) {
+ Optional<TypeHierarchyItem> Result = declToTypeHierarchyItem(ASTCtx, CXXRD);
+ if (!Result)
+ return Result;
+
+ Result->parents.emplace();
+
+ // typeParents() will replace dependent template specializations
+ // with their class template, so to avoid infinite recursion for
+ // certain types of hierarchies, keep the templates encountered
+ // along the parent chain in a set, and stop the recursion if one
+ // starts to repeat.
+ auto *Pattern = CXXRD.getDescribedTemplate() ? &CXXRD : nullptr;
+ if (Pattern) {
+ if (!RPSet.insert(Pattern).second) {
+ return Result;
+ }
+ }
+
+ for (const CXXRecordDecl *ParentDecl : typeParents(&CXXRD)) {
+ if (Optional<TypeHierarchyItem> ParentSym =
+ getTypeAncestors(*ParentDecl, ASTCtx, RPSet)) {
+ Result->parents->emplace_back(std::move(*ParentSym));
+ }
+ }
+
+ if (Pattern) {
+ RPSet.erase(Pattern);
+ }
+
+ return Result;
+}
+
+const CXXRecordDecl *findRecordTypeAt(ParsedAST &AST, Position Pos) {
+ ASTContext &ASTCtx = AST.getASTContext();
+ const SourceManager &SourceMgr = ASTCtx.getSourceManager();
+ SourceLocation SourceLocationBeg =
+ getBeginningOfIdentifier(AST, Pos, SourceMgr.getMainFileID());
+ IdentifiedSymbol Symbols = getSymbolAtPosition(AST, SourceLocationBeg);
+ if (Symbols.Decls.empty())
+ return nullptr;
+
+ const Decl *D = Symbols.Decls[0];
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ // If this is a variable, use the type of the variable.
+ return VD->getType().getTypePtr()->getAsCXXRecordDecl();
+ }
+
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ // If this is a method, use the type of the class.
+ return Method->getParent();
+ }
+
+ // We don't handle FieldDecl because it's not clear what behaviour
+ // the user would expect: the enclosing class type (as with a
+ // method), or the field's type (as with a variable).
+
+ return dyn_cast<CXXRecordDecl>(D);
+}
+
+std::vector<const CXXRecordDecl *> typeParents(const CXXRecordDecl *CXXRD) {
+ std::vector<const CXXRecordDecl *> Result;
+
+ for (auto Base : CXXRD->bases()) {
+ const CXXRecordDecl *ParentDecl = nullptr;
+
+ const Type *Type = Base.getType().getTypePtr();
+ if (const RecordType *RT = Type->getAs<RecordType>()) {
+ ParentDecl = RT->getAsCXXRecordDecl();
+ }
+
+ if (!ParentDecl) {
+ // Handle a dependent base such as "Base<T>" by using the primary
+ // template.
+ if (const TemplateSpecializationType *TS =
+ Type->getAs<TemplateSpecializationType>()) {
+ TemplateName TN = TS->getTemplateName();
+ if (TemplateDecl *TD = TN.getAsTemplateDecl()) {
+ ParentDecl = dyn_cast<CXXRecordDecl>(TD->getTemplatedDecl());
+ }
+ }
+ }
+
+ if (ParentDecl)
+ Result.push_back(ParentDecl);
+ }
+
+ return Result;
+}
+
+llvm::Optional<TypeHierarchyItem>
+getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels,
+ TypeHierarchyDirection Direction) {
+ const CXXRecordDecl *CXXRD = findRecordTypeAt(AST, Pos);
+ if (!CXXRD)
+ return llvm::None;
+
+ RecursionProtectionSet RPSet;
+ Optional<TypeHierarchyItem> Result =
+ getTypeAncestors(*CXXRD, AST.getASTContext(), RPSet);
+
+ // FIXME(nridge): Resolve type descendants if direction is Children or Both,
+ // and ResolveLevels > 0.
+
+ return Result;
+}
+
} // namespace clangd
} // namespace clang
diff --git a/clangd/XRefs.h b/clangd/XRefs.h
index 631879d6..008bba50 100644
--- a/clangd/XRefs.h
+++ b/clangd/XRefs.h
@@ -1,9 +1,8 @@
//===--- XRefs.h -------------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -23,9 +22,25 @@
namespace clang {
namespace clangd {
+// Describes where a symbol is declared and defined (as far as clangd knows).
+// There are three cases:
+// - a declaration only, no definition is known (e.g. only header seen)
+// - a declaration and a distinct definition (e.g. function declared in header)
+// - a declaration and an equal definition (e.g. inline function, or class)
+// For some types of symbol, e.g. macros, definition == declaration always.
+struct LocatedSymbol {
+ // The (unqualified) name of the symbol.
+ std::string Name;
+ // The canonical or best declaration: where most users find its interface.
+ Location PreferredDeclaration;
+ // Where the symbol is defined, if known. May equal PreferredDeclaration.
+ llvm::Optional<Location> Definition;
+};
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const LocatedSymbol &);
/// Get definition of symbol at a specified \p Pos.
-std::vector<Location> findDefinitions(ParsedAST &AST, Position Pos,
- const SymbolIndex *Index = nullptr);
+/// Multiple locations may be returned, corresponding to distinct symbols.
+std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos,
+ const SymbolIndex *Index = nullptr);
/// Returns highlights for all usages of a symbol at \p Pos.
std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST,
@@ -43,6 +58,17 @@ std::vector<Location> findReferences(ParsedAST &AST, Position Pos,
/// Get info about symbols at \p Pos.
std::vector<SymbolDetails> getSymbolInfo(ParsedAST &AST, Position Pos);
+/// Find the record type references at \p Pos.
+const CXXRecordDecl *findRecordTypeAt(ParsedAST &AST, Position Pos);
+
+/// Given a record type declaration, find its base (parent) types.
+std::vector<const CXXRecordDecl *> typeParents(const CXXRecordDecl *CXXRD);
+
+/// Get type hierarchy information at \p Pos.
+llvm::Optional<TypeHierarchyItem>
+getTypeHierarchy(ParsedAST &AST, Position Pos, int Resolve,
+ TypeHierarchyDirection Direction);
+
} // namespace clangd
} // namespace clang
diff --git a/clangd/benchmarks/IndexBenchmark.cpp b/clangd/benchmarks/IndexBenchmark.cpp
index d71f8fec..439ac9c6 100644
--- a/clangd/benchmarks/IndexBenchmark.cpp
+++ b/clangd/benchmarks/IndexBenchmark.cpp
@@ -1,9 +1,8 @@
//===--- IndexBenchmark.cpp - Clangd index benchmarks -----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/clients/clangd-vscode/.gitignore b/clangd/clients/clangd-vscode/.gitignore
index 1294fe26..5df8049b 100644
--- a/clangd/clients/clangd-vscode/.gitignore
+++ b/clangd/clients/clangd-vscode/.gitignore
@@ -1,3 +1,2 @@
out
node_modules
-package-lock.json
diff --git a/clangd/clients/clangd-vscode/package-lock.json b/clangd/clients/clangd-vscode/package-lock.json
new file mode 100644
index 00000000..90685912
--- /dev/null
+++ b/clangd/clients/clangd-vscode/package-lock.json
@@ -0,0 +1,2027 @@
+{
+ "name": "vscode-clangd",
+ "version": "0.0.10",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@types/mocha": {
+ "version": "2.2.48",
+ "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.48.tgz",
+ "integrity": "sha512-nlK/iyETgafGli8Zh9zJVCTicvU3iajSkRwOh3Hhiva598CMqNJ4NcVCGMTGKpGpTYj/9R8RLzS9NAykSSCqGw==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "6.14.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.2.tgz",
+ "integrity": "sha512-JWB3xaVfsfnFY8Ofc9rTB/op0fqqTSqy4vBcVk1LuRJvta7KTX+D//fCkiTMeLGhdr2EbFZzQjC97gvmPilk9Q==",
+ "dev": true
+ },
+ "ajv": {
+ "version": "6.8.1",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.8.1.tgz",
+ "integrity": "sha512-eqxCp82P+JfqL683wwsL73XmFs1eG6qjw+RD3YHx+Jll1r0jNd4dh8QG9NYAeNGA/hnZjeEDgtTskgJULbxpWQ==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-cyan": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz",
+ "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=",
+ "dev": true,
+ "requires": {
+ "ansi-wrap": "0.1.0"
+ }
+ },
+ "ansi-red": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz",
+ "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=",
+ "dev": true,
+ "requires": {
+ "ansi-wrap": "0.1.0"
+ }
+ },
+ "ansi-wrap": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
+ "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=",
+ "dev": true
+ },
+ "append-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz",
+ "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=",
+ "dev": true,
+ "requires": {
+ "buffer-equal": "^1.0.0"
+ }
+ },
+ "arr-diff": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz",
+ "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.0.1",
+ "array-slice": "^0.2.3"
+ }
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+ "dev": true
+ },
+ "arr-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz",
+ "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=",
+ "dev": true
+ },
+ "array-differ": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
+ "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=",
+ "dev": true
+ },
+ "array-slice": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz",
+ "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=",
+ "dev": true
+ },
+ "array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+ "dev": true,
+ "requires": {
+ "array-uniq": "^1.0.1"
+ }
+ },
+ "array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+ "dev": true
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ },
+ "asn1": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+ "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+ "dev": true
+ },
+ "aws4": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
+ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "dev": true,
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "block-stream": {
+ "version": "0.0.9",
+ "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+ "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+ "dev": true,
+ "requires": {
+ "inherits": "~2.0.0"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "browser-stdout": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz",
+ "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=",
+ "dev": true
+ },
+ "buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
+ "dev": true
+ },
+ "buffer-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz",
+ "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=",
+ "dev": true
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+ "dev": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+ "dev": true
+ },
+ "clone": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz",
+ "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=",
+ "dev": true
+ },
+ "clone-buffer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz",
+ "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=",
+ "dev": true
+ },
+ "clone-stats": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz",
+ "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=",
+ "dev": true
+ },
+ "cloneable-readable": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz",
+ "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "process-nextick-args": "^2.0.0",
+ "readable-stream": "^2.3.5"
+ }
+ },
+ "combined-stream": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
+ "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "commander": {
+ "version": "2.15.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
+ "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz",
+ "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "deep-assign": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-1.0.0.tgz",
+ "integrity": "sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s=",
+ "dev": true,
+ "requires": {
+ "is-obj": "^1.0.0"
+ }
+ },
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "dev": true,
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true
+ },
+ "diff": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "dev": true
+ },
+ "duplexer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
+ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
+ "dev": true
+ },
+ "duplexify": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
+ "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "dev": true,
+ "requires": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "end-of-stream": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+ "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+ "dev": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "event-stream": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
+ "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=",
+ "dev": true,
+ "requires": {
+ "duplexer": "~0.1.1",
+ "from": "~0",
+ "map-stream": "~0.1.0",
+ "pause-stream": "0.0.11",
+ "split": "0.3",
+ "stream-combiner": "~0.0.4",
+ "through": "~2.3.1"
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "extend-shallow": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz",
+ "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^1.1.0"
+ }
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+ "dev": true
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
+ "dev": true
+ },
+ "fd-slicer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+ "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
+ "dev": true,
+ "requires": {
+ "pend": "~1.2.0"
+ }
+ },
+ "flush-write-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.0.tgz",
+ "integrity": "sha512-6MHED/cmsyux1G4/Cek2Z776y9t7WCNd3h2h/HW91vFeU7pzMhA8XvAlDhHcanG5IWuIh/xcC7JASY4WQpG6xg==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz",
+ "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+ "dev": true
+ },
+ "form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "from": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
+ "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=",
+ "dev": true
+ },
+ "fs-mkdirp-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz",
+ "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "through2": "^2.0.3"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "fstream": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
+ "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "inherits": "~2.0.0",
+ "mkdirp": ">=0.5 0",
+ "rimraf": "2"
+ }
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "dev": true,
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ }
+ },
+ "glob-stream": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz",
+ "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=",
+ "dev": true,
+ "requires": {
+ "extend": "^3.0.0",
+ "glob": "^7.1.1",
+ "glob-parent": "^3.1.0",
+ "is-negated-glob": "^1.0.0",
+ "ordered-read-streams": "^1.0.0",
+ "pumpify": "^1.3.5",
+ "readable-stream": "^2.1.5",
+ "remove-trailing-separator": "^1.0.1",
+ "to-absolute-glob": "^2.0.0",
+ "unique-stream": "^2.0.2"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+ "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ }
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.15",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
+ "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
+ "dev": true
+ },
+ "growl": {
+ "version": "1.10.5",
+ "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
+ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
+ "dev": true
+ },
+ "gulp-chmod": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/gulp-chmod/-/gulp-chmod-2.0.0.tgz",
+ "integrity": "sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw=",
+ "dev": true,
+ "requires": {
+ "deep-assign": "^1.0.0",
+ "stat-mode": "^0.2.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "gulp-filter": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.1.0.tgz",
+ "integrity": "sha1-oF4Rr/sHz33PQafeHLe2OsN4PnM=",
+ "dev": true,
+ "requires": {
+ "multimatch": "^2.0.0",
+ "plugin-error": "^0.1.2",
+ "streamfilter": "^1.0.5"
+ }
+ },
+ "gulp-gunzip": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/gulp-gunzip/-/gulp-gunzip-1.0.0.tgz",
+ "integrity": "sha1-FbdBFF6Dqcb1CIYkG1fMWHHxUak=",
+ "dev": true,
+ "requires": {
+ "through2": "~0.6.5",
+ "vinyl": "~0.4.6"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "1.0.34",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.1",
+ "isarray": "0.0.1",
+ "string_decoder": "~0.10.x"
+ }
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "dev": true
+ },
+ "through2": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
+ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
+ "dev": true,
+ "requires": {
+ "readable-stream": ">=1.0.33-1 <1.1.0-0",
+ "xtend": ">=4.0.0 <4.1.0-0"
+ }
+ }
+ }
+ },
+ "gulp-remote-src-vscode": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/gulp-remote-src-vscode/-/gulp-remote-src-vscode-0.5.1.tgz",
+ "integrity": "sha512-mw4OGjtC/jlCWJFhbcAlel4YPvccChlpsl3JceNiB/DLJi24/UPxXt53/N26lgI3dknEqd4ErfdHrO8sJ5bATQ==",
+ "dev": true,
+ "requires": {
+ "event-stream": "3.3.4",
+ "node.extend": "^1.1.2",
+ "request": "^2.79.0",
+ "through2": "^2.0.3",
+ "vinyl": "^2.0.1"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
+ "dev": true
+ },
+ "clone-stats": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
+ "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
+ "dev": true
+ },
+ "vinyl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz",
+ "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==",
+ "dev": true,
+ "requires": {
+ "clone": "^2.1.1",
+ "clone-buffer": "^1.0.0",
+ "clone-stats": "^1.0.0",
+ "cloneable-readable": "^1.0.0",
+ "remove-trailing-separator": "^1.0.1",
+ "replace-ext": "^1.0.0"
+ }
+ }
+ }
+ },
+ "gulp-untar": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/gulp-untar/-/gulp-untar-0.0.7.tgz",
+ "integrity": "sha512-0QfbCH2a1k2qkTLWPqTX+QO4qNsHn3kC546YhAP3/n0h+nvtyGITDuDrYBMDZeW4WnFijmkOvBWa5HshTic1tw==",
+ "dev": true,
+ "requires": {
+ "event-stream": "~3.3.4",
+ "streamifier": "~0.1.1",
+ "tar": "^2.2.1",
+ "through2": "~2.0.3",
+ "vinyl": "^1.2.0"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
+ "dev": true
+ },
+ "replace-ext": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz",
+ "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=",
+ "dev": true
+ },
+ "vinyl": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz",
+ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=",
+ "dev": true,
+ "requires": {
+ "clone": "^1.0.0",
+ "clone-stats": "^0.0.1",
+ "replace-ext": "0.0.1"
+ }
+ }
+ }
+ },
+ "gulp-vinyl-zip": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.2.tgz",
+ "integrity": "sha512-wJn09jsb8PyvUeyFF7y7ImEJqJwYy40BqL9GKfJs6UGpaGW9A+N68Q+ajsIpb9AeR6lAdjMbIdDPclIGo1/b7Q==",
+ "dev": true,
+ "requires": {
+ "event-stream": "3.3.4",
+ "queue": "^4.2.1",
+ "through2": "^2.0.3",
+ "vinyl": "^2.0.2",
+ "vinyl-fs": "^3.0.3",
+ "yauzl": "^2.2.1",
+ "yazl": "^2.2.1"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
+ "dev": true
+ },
+ "clone-stats": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
+ "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
+ "dev": true
+ },
+ "vinyl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz",
+ "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==",
+ "dev": true,
+ "requires": {
+ "clone": "^2.1.1",
+ "clone-buffer": "^1.0.0",
+ "clone-stats": "^1.0.0",
+ "cloneable-readable": "^1.0.0",
+ "remove-trailing-separator": "^1.0.1",
+ "replace-ext": "^1.0.0"
+ }
+ }
+ }
+ },
+ "har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+ "dev": true
+ },
+ "har-validator": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+ "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.5.5",
+ "har-schema": "^2.0.0"
+ }
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "has-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
+ "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
+ "dev": true
+ },
+ "he": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
+ "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
+ "dev": true
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "is": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz",
+ "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==",
+ "dev": true
+ },
+ "is-absolute": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
+ "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==",
+ "dev": true,
+ "requires": {
+ "is-relative": "^1.0.0",
+ "is-windows": "^1.0.1"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ },
+ "is-negated-glob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz",
+ "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=",
+ "dev": true
+ },
+ "is-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+ "dev": true
+ },
+ "is-relative": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
+ "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==",
+ "dev": true,
+ "requires": {
+ "is-unc-path": "^1.0.0"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
+ "is-unc-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
+ "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==",
+ "dev": true,
+ "requires": {
+ "unc-path-regex": "^0.1.2"
+ }
+ },
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+ "dev": true
+ },
+ "is-valid-glob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz",
+ "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=",
+ "dev": true
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+ "dev": true
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+ "dev": true
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+ "dev": true
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+ "dev": true
+ },
+ "jsprim": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+ "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.2.3",
+ "verror": "1.10.0"
+ }
+ },
+ "kind-of": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
+ "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=",
+ "dev": true
+ },
+ "lazystream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
+ "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "^2.0.5"
+ }
+ },
+ "lead": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz",
+ "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=",
+ "dev": true,
+ "requires": {
+ "flush-write-stream": "^1.0.2"
+ }
+ },
+ "map-stream": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz",
+ "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=",
+ "dev": true
+ },
+ "mime-db": {
+ "version": "1.37.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
+ "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.21",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz",
+ "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==",
+ "dev": true,
+ "requires": {
+ "mime-db": "~1.37.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "mocha": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
+ "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
+ "dev": true,
+ "requires": {
+ "browser-stdout": "1.3.1",
+ "commander": "2.15.1",
+ "debug": "3.1.0",
+ "diff": "3.5.0",
+ "escape-string-regexp": "1.0.5",
+ "glob": "7.1.2",
+ "growl": "1.10.5",
+ "he": "1.1.1",
+ "minimatch": "3.0.4",
+ "mkdirp": "0.5.1",
+ "supports-color": "5.4.0"
+ },
+ "dependencies": {
+ "browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "dev": true
+ }
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "multimatch": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz",
+ "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=",
+ "dev": true,
+ "requires": {
+ "array-differ": "^1.0.0",
+ "array-union": "^1.0.1",
+ "arrify": "^1.0.0",
+ "minimatch": "^3.0.0"
+ },
+ "dependencies": {
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ }
+ }
+ },
+ "node.extend": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.8.tgz",
+ "integrity": "sha512-L/dvEBwyg3UowwqOUTyDsGBU6kjBQOpOhshio9V3i3BMPv5YUb9+mWNN8MK0IbWqT0AqaTSONZf0aTuMMahWgA==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3",
+ "is": "^3.2.1"
+ }
+ },
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true,
+ "requires": {
+ "remove-trailing-separator": "^1.0.1"
+ }
+ },
+ "now-and-later": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz",
+ "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.2"
+ }
+ },
+ "oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
+ "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
+ "dev": true
+ },
+ "object.assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+ "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "function-bind": "^1.1.1",
+ "has-symbols": "^1.0.0",
+ "object-keys": "^1.0.11"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "ordered-read-streams": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz",
+ "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "^2.0.1"
+ }
+ },
+ "path-dirname": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "pause-stream": {
+ "version": "0.0.11",
+ "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
+ "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=",
+ "dev": true,
+ "requires": {
+ "through": "~2.3"
+ }
+ },
+ "pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
+ "dev": true
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+ "dev": true
+ },
+ "plugin-error": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz",
+ "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=",
+ "dev": true,
+ "requires": {
+ "ansi-cyan": "^0.1.1",
+ "ansi-red": "^0.1.1",
+ "arr-diff": "^1.0.1",
+ "arr-union": "^2.0.1",
+ "extend-shallow": "^1.1.2"
+ }
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+ "dev": true
+ },
+ "psl": {
+ "version": "1.1.31",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz",
+ "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==",
+ "dev": true
+ },
+ "pump": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+ "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "pumpify": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
+ "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
+ "dev": true,
+ "requires": {
+ "duplexify": "^3.6.0",
+ "inherits": "^2.0.3",
+ "pump": "^2.0.0"
+ }
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+ "dev": true
+ },
+ "querystringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz",
+ "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==",
+ "dev": true
+ },
+ "queue": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/queue/-/queue-4.5.1.tgz",
+ "integrity": "sha512-AMD7w5hRXcFSb8s9u38acBZ+309u6GsiibP4/0YacJeaurRshogB7v/ZcVPxP5gD5+zIw6ixRHdutiYUJfwKHw==",
+ "dev": true,
+ "requires": {
+ "inherits": "~2.0.0"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "remove-bom-buffer": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz",
+ "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5",
+ "is-utf8": "^0.2.1"
+ }
+ },
+ "remove-bom-stream": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz",
+ "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=",
+ "dev": true,
+ "requires": {
+ "remove-bom-buffer": "^3.0.0",
+ "safe-buffer": "^5.1.0",
+ "through2": "^2.0.3"
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+ "dev": true
+ },
+ "replace-ext": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz",
+ "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=",
+ "dev": true
+ },
+ "request": {
+ "version": "2.88.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+ "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+ "dev": true,
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.0",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.4.3",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ }
+ },
+ "requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+ "dev": true
+ },
+ "resolve-options": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz",
+ "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=",
+ "dev": true,
+ "requires": {
+ "value-or-function": "^3.0.0"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+ "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ }
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "semver": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+ "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "source-map-support": {
+ "version": "0.5.10",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz",
+ "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "split": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
+ "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=",
+ "dev": true,
+ "requires": {
+ "through": "2"
+ }
+ },
+ "sshpk": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+ "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+ "dev": true,
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "stat-mode": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz",
+ "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=",
+ "dev": true
+ },
+ "stream-combiner": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz",
+ "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=",
+ "dev": true,
+ "requires": {
+ "duplexer": "~0.1.1"
+ }
+ },
+ "stream-shift": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
+ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
+ "dev": true
+ },
+ "streamfilter": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-1.0.7.tgz",
+ "integrity": "sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ==",
+ "dev": true,
+ "requires": {
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "streamifier": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/streamifier/-/streamifier-0.1.1.tgz",
+ "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "supports-color": {
+ "version": "5.4.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
+ "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ },
+ "dependencies": {
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ }
+ }
+ },
+ "tar": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
+ "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
+ "dev": true,
+ "requires": {
+ "block-stream": "*",
+ "fstream": "^1.0.2",
+ "inherits": "2"
+ }
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+ "dev": true
+ },
+ "through2": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+ "dev": true,
+ "requires": {
+ "readable-stream": "~2.3.6",
+ "xtend": "~4.0.1"
+ }
+ },
+ "through2-filter": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz",
+ "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==",
+ "dev": true,
+ "requires": {
+ "through2": "~2.0.0",
+ "xtend": "~4.0.0"
+ }
+ },
+ "to-absolute-glob": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz",
+ "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=",
+ "dev": true,
+ "requires": {
+ "is-absolute": "^1.0.0",
+ "is-negated-glob": "^1.0.0"
+ }
+ },
+ "to-through": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz",
+ "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=",
+ "dev": true,
+ "requires": {
+ "through2": "^2.0.3"
+ }
+ },
+ "tough-cookie": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+ "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
+ "dev": true,
+ "requires": {
+ "psl": "^1.1.24",
+ "punycode": "^1.4.1"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+ "dev": true
+ }
+ }
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "dev": true
+ },
+ "typescript": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz",
+ "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==",
+ "dev": true
+ },
+ "unc-path-regex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
+ "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=",
+ "dev": true
+ },
+ "unique-stream": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz",
+ "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==",
+ "dev": true,
+ "requires": {
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "through2-filter": "^3.0.0"
+ }
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "url-parse": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz",
+ "integrity": "sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==",
+ "dev": true,
+ "requires": {
+ "querystringify": "^2.0.0",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "uuid": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
+ "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
+ "dev": true
+ },
+ "value-or-function": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz",
+ "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=",
+ "dev": true
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "vinyl": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz",
+ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=",
+ "dev": true,
+ "requires": {
+ "clone": "^0.2.0",
+ "clone-stats": "^0.0.1"
+ }
+ },
+ "vinyl-fs": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz",
+ "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==",
+ "dev": true,
+ "requires": {
+ "fs-mkdirp-stream": "^1.0.0",
+ "glob-stream": "^6.1.0",
+ "graceful-fs": "^4.0.0",
+ "is-valid-glob": "^1.0.0",
+ "lazystream": "^1.0.0",
+ "lead": "^1.0.0",
+ "object.assign": "^4.0.4",
+ "pumpify": "^1.3.5",
+ "readable-stream": "^2.3.3",
+ "remove-bom-buffer": "^3.0.0",
+ "remove-bom-stream": "^1.2.0",
+ "resolve-options": "^1.1.0",
+ "through2": "^2.0.0",
+ "to-through": "^2.0.0",
+ "value-or-function": "^3.0.0",
+ "vinyl": "^2.0.0",
+ "vinyl-sourcemap": "^1.1.0"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
+ "dev": true
+ },
+ "clone-stats": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
+ "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
+ "dev": true
+ },
+ "vinyl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz",
+ "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==",
+ "dev": true,
+ "requires": {
+ "clone": "^2.1.1",
+ "clone-buffer": "^1.0.0",
+ "clone-stats": "^1.0.0",
+ "cloneable-readable": "^1.0.0",
+ "remove-trailing-separator": "^1.0.1",
+ "replace-ext": "^1.0.0"
+ }
+ }
+ }
+ },
+ "vinyl-source-stream": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz",
+ "integrity": "sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A=",
+ "dev": true,
+ "requires": {
+ "through2": "^2.0.3",
+ "vinyl": "^0.4.3"
+ }
+ },
+ "vinyl-sourcemap": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz",
+ "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=",
+ "dev": true,
+ "requires": {
+ "append-buffer": "^1.0.2",
+ "convert-source-map": "^1.5.0",
+ "graceful-fs": "^4.1.6",
+ "normalize-path": "^2.1.1",
+ "now-and-later": "^2.0.0",
+ "remove-bom-buffer": "^3.0.0",
+ "vinyl": "^2.0.0"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
+ "dev": true
+ },
+ "clone-stats": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
+ "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
+ "dev": true
+ },
+ "vinyl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz",
+ "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==",
+ "dev": true,
+ "requires": {
+ "clone": "^2.1.1",
+ "clone-buffer": "^1.0.0",
+ "clone-stats": "^1.0.0",
+ "cloneable-readable": "^1.0.0",
+ "remove-trailing-separator": "^1.0.1",
+ "replace-ext": "^1.0.0"
+ }
+ }
+ }
+ },
+ "vscode": {
+ "version": "1.1.28",
+ "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.28.tgz",
+ "integrity": "sha512-vxpRMKVa/DgSihyy8I7puRZKiwQm9NK/e5oDTEFDtughhEHrspi0UaXKe795b1DFgO3XJe6KLiXzC8mJonvvWw==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.2",
+ "gulp-chmod": "^2.0.0",
+ "gulp-filter": "^5.0.1",
+ "gulp-gunzip": "1.0.0",
+ "gulp-remote-src-vscode": "^0.5.1",
+ "gulp-untar": "^0.0.7",
+ "gulp-vinyl-zip": "^2.1.2",
+ "mocha": "^4.0.1",
+ "request": "^2.88.0",
+ "semver": "^5.4.1",
+ "source-map-support": "^0.5.0",
+ "url-parse": "^1.4.3",
+ "vinyl-fs": "^3.0.3",
+ "vinyl-source-stream": "^1.1.0"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
+ "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==",
+ "dev": true
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "diff": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz",
+ "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+ "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "growl": {
+ "version": "1.10.3",
+ "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz",
+ "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "mocha": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz",
+ "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==",
+ "dev": true,
+ "requires": {
+ "browser-stdout": "1.3.0",
+ "commander": "2.11.0",
+ "debug": "3.1.0",
+ "diff": "3.3.1",
+ "escape-string-regexp": "1.0.5",
+ "glob": "7.1.2",
+ "growl": "1.10.3",
+ "he": "1.1.1",
+ "mkdirp": "0.5.1",
+ "supports-color": "4.4.0"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
+ "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^2.0.0"
+ }
+ }
+ }
+ },
+ "vscode-jsonrpc": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz",
+ "integrity": "sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg=="
+ },
+ "vscode-languageclient": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-5.2.1.tgz",
+ "integrity": "sha512-7jrS/9WnV0ruqPamN1nE7qCxn0phkH5LjSgSp9h6qoJGoeAKzwKz/PF6M+iGA/aklx4GLZg1prddhEPQtuXI1Q==",
+ "requires": {
+ "semver": "^5.5.0",
+ "vscode-languageserver-protocol": "3.14.1"
+ }
+ },
+ "vscode-languageserver": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-5.2.1.tgz",
+ "integrity": "sha512-GuayqdKZqAwwaCUjDvMTAVRPJOp/SLON3mJ07eGsx/Iq9HjRymhKWztX41rISqDKhHVVyFM+IywICyZDla6U3A==",
+ "requires": {
+ "vscode-languageserver-protocol": "3.14.1",
+ "vscode-uri": "^1.0.6"
+ }
+ },
+ "vscode-languageserver-protocol": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz",
+ "integrity": "sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g==",
+ "requires": {
+ "vscode-jsonrpc": "^4.0.0",
+ "vscode-languageserver-types": "3.14.0"
+ }
+ },
+ "vscode-languageserver-types": {
+ "version": "3.14.0",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz",
+ "integrity": "sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A=="
+ },
+ "vscode-uri": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.6.tgz",
+ "integrity": "sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww=="
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
+ "dev": true
+ },
+ "yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
+ "dev": true,
+ "requires": {
+ "buffer-crc32": "~0.2.3",
+ "fd-slicer": "~1.1.0"
+ }
+ },
+ "yazl": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz",
+ "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==",
+ "dev": true,
+ "requires": {
+ "buffer-crc32": "~0.2.3"
+ }
+ }
+ }
+}
diff --git a/clangd/clients/clangd-vscode/package.json b/clangd/clients/clangd-vscode/package.json
index 89b61ff9..b8125808 100644
--- a/clangd/clients/clangd-vscode/package.json
+++ b/clangd/clients/clangd-vscode/package.json
@@ -2,11 +2,11 @@
"name": "vscode-clangd",
"displayName": "vscode-clangd",
"description": "Clang Language Server",
- "version": "0.0.9",
+ "version": "0.0.12",
"publisher": "llvm-vs-code-extensions",
"homepage": "https://clang.llvm.org/extra/clangd.html",
"engines": {
- "vscode": "^1.27.0"
+ "vscode": "^1.30.0"
},
"categories": [
"Programming Languages",
@@ -21,8 +21,11 @@
"LLVM"
],
"activationEvents": [
+ "onLanguage:c",
"onLanguage:cpp",
- "onLanguage:c"
+ "onLanguage:objective-c",
+ "onLanguage:objective-cpp",
+ "onCommand:clangd-vscode.activate"
],
"main": "./out/src/extension",
"scripts": {
@@ -32,15 +35,15 @@
"test": "node ./node_modules/vscode/bin/test"
},
"dependencies": {
- "vscode-languageclient": "^5.1.0",
- "vscode-languageserver": "^5.1.0"
+ "vscode-languageclient": "^5.2.0",
+ "vscode-languageserver": "^5.2.0"
},
"devDependencies": {
- "typescript": "^2.0.3",
- "vscode": "^1.1.0",
- "mocha": "^2.3.3",
+ "@types/mocha": "^2.2.32",
"@types/node": "^6.0.40",
- "@types/mocha": "^2.2.32"
+ "mocha": "^5.2.0",
+ "typescript": "^2.0.3",
+ "vscode": "^1.1.0"
},
"repository": {
"type": "svn",
@@ -79,6 +82,10 @@
{
"command": "clangd-vscode.switchheadersource",
"title": "Switch between Source/Header"
+ },
+ {
+ "command": "clangd-vscode.activate",
+ "title": "Manually activate clangd extension"
}
],
"keybindings": [
diff --git a/clangd/clients/clangd-vscode/src/extension.ts b/clangd/clients/clangd-vscode/src/extension.ts
index cad6a3a1..2cb97d97 100644
--- a/clangd/clients/clangd-vscode/src/extension.ts
+++ b/clangd/clients/clangd-vscode/src/extension.ts
@@ -40,6 +40,11 @@ class FileStatus {
this.statusBarItem.show();
}
+ clear() {
+ this.statuses.clear();
+ this.statusBarItem.hide();
+ }
+
dispose() {
this.statusBarItem.dispose();
}
@@ -63,8 +68,18 @@ export function activate(context: vscode.ExtensionContext) {
}
const serverOptions: vscodelc.ServerOptions = clangd;
+ // Note that CUDA ('.cu') files are special. When opening files of all other
+ // extensions, VSCode would load clangd automatically. This is achieved by
+ // having a corresponding 'onLanguage:...' activation event in package.json.
+ // However, VSCode does not have CUDA as a supported language yet, so we
+ // cannot add a corresponding activationEvent for CUDA files and clangd will
+ // *not* load itself automatically on '.cu' files. When any of the files
+ // with other extensions are open, clangd will load itself and will also
+ // work on '.cu' files.
const filePattern: string = '**/*.{' +
- ['cpp', 'c', 'cc', 'cxx', 'c++', 'm', 'mm', 'h', 'hh', 'hpp', 'hxx', 'inc'].join() + '}';
+ ['cpp', 'c', 'cc', 'cu', 'cxx', 'c++', 'm', 'mm',
+ 'h', 'hh', 'hpp', 'hxx', 'inc'].join()
+ + '}';
const clientOptions: vscodelc.LanguageClientOptions = {
// Register the server for C/C++ files
documentSelector: [{ scheme: 'file', pattern: filePattern }],
@@ -87,34 +102,45 @@ export function activate(context: vscode.ExtensionContext) {
revealOutputChannelOn: vscodelc.RevealOutputChannelOn.Never
};
- const clangdClient = new vscodelc.LanguageClient('Clang Language Server', serverOptions, clientOptions);
- console.log('Clang Language Server is now active!');
- context.subscriptions.push(clangdClient.start());
- context.subscriptions.push(vscode.commands.registerCommand(
- 'clangd-vscode.switchheadersource', async () => {
- const uri =
- vscode.Uri.file(vscode.window.activeTextEditor.document.fileName);
- if (!uri) {
- return;
- }
- const docIdentifier =
- vscodelc.TextDocumentIdentifier.create(uri.toString());
- const sourceUri = await clangdClient.sendRequest(
- SwitchSourceHeaderRequest.type, docIdentifier);
- if (!sourceUri) {
- return;
- }
- const doc = await vscode.workspace.openTextDocument(
- vscode.Uri.parse(sourceUri));
- vscode.window.showTextDocument(doc);
- }));
+ const clangdClient = new vscodelc.LanguageClient('Clang Language Server',serverOptions, clientOptions);
+ console.log('Clang Language Server is now active!');
+ context.subscriptions.push(clangdClient.start());
+ context.subscriptions.push(vscode.commands.registerCommand(
+ 'clangd-vscode.switchheadersource', async () => {
+ const uri =
+ vscode.Uri.file(vscode.window.activeTextEditor.document.fileName);
+ if (!uri) {
+ return;
+ }
+ const docIdentifier =
+ vscodelc.TextDocumentIdentifier.create(uri.toString());
+ const sourceUri = await clangdClient.sendRequest(
+ SwitchSourceHeaderRequest.type, docIdentifier);
+ if (!sourceUri) {
+ return;
+ }
+ const doc = await vscode.workspace.openTextDocument(
+ vscode.Uri.parse(sourceUri));
+ vscode.window.showTextDocument(doc);
+ }));
const status = new FileStatus();
context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(() => {
status.updateStatus();
}));
- clangdClient.onReady().then(() => {
- clangdClient.onNotification(
- 'textDocument/clangd.fileStatus',
- (fileStatus) => { status.onFileUpdated(fileStatus); });
- })
+ clangdClient.onDidChangeState(
+ ({ newState }) => {
+ if (newState == vscodelc.State.Running) {
+ // clangd starts or restarts after crash.
+ clangdClient.onNotification(
+ 'textDocument/clangd.fileStatus',
+ (fileStatus) => { status.onFileUpdated(fileStatus); });
+ } else if (newState == vscodelc.State.Stopped) {
+ // Clear all cached statuses when clangd crashes.
+ status.clear();
+ }
+ })
+ // An empty place holder for the activate command, otherwise we'll get an
+ // "command is not registered" error.
+ context.subscriptions.push(vscode.commands.registerCommand(
+ 'clangd-vscode.activate', async () => {}));
}
diff --git a/clangd/fuzzer/CMakeLists.txt b/clangd/fuzzer/CMakeLists.txt
index ca76c977..28191a3f 100644
--- a/clangd/fuzzer/CMakeLists.txt
+++ b/clangd/fuzzer/CMakeLists.txt
@@ -1,14 +1,15 @@
-include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..
+ ${CMAKE_CURRENT_BINARY_DIR}/..)
-set(LLVM_LINK_COMPONENTS support)
-
-if(LLVM_USE_SANITIZE_COVERAGE)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=fuzzer")
-endif()
+set(LLVM_LINK_COMPONENTS
+ FuzzMutate
+ Support
+ )
-add_clang_executable(clangd-fuzzer
- EXCLUDE_FROM_ALL
- ClangdFuzzer.cpp
+# This fuzzer runs on oss-fuzz, so keep it around even if it looks unreferenced.
+add_llvm_fuzzer(clangd-fuzzer
+ clangd-fuzzer.cpp
+ DUMMY_MAIN DummyClangdMain.cpp
)
target_link_libraries(clangd-fuzzer
@@ -20,5 +21,4 @@ target_link_libraries(clangd-fuzzer
clangSema
clangTooling
clangToolingCore
- ${LLVM_LIB_FUZZING_ENGINE}
)
diff --git a/clangd/fuzzer/DummyClangdMain.cpp b/clangd/fuzzer/DummyClangdMain.cpp
new file mode 100644
index 00000000..cd5a6121
--- /dev/null
+++ b/clangd/fuzzer/DummyClangdMain.cpp
@@ -0,0 +1,18 @@
+//===---- DummyClangdMain.cpp - Entry point to sanity check the fuzzer ----===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of main so we can build and test without linking libFuzzer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/FuzzMutate/FuzzerCLI.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
+int main(int argc, char *argv[]) {
+ return llvm::runFuzzerOnInputs(argc, argv, LLVMFuzzerTestOneInput);
+}
diff --git a/clangd/fuzzer/ClangdFuzzer.cpp b/clangd/fuzzer/clangd-fuzzer.cpp
index 7afd0798..5e7de771 100644
--- a/clangd/fuzzer/ClangdFuzzer.cpp
+++ b/clangd/fuzzer/clangd-fuzzer.cpp
@@ -1,9 +1,8 @@
//===-- ClangdFuzzer.cpp - Fuzz clangd ------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
@@ -16,6 +15,7 @@
#include "ClangdLSPServer.h"
#include "ClangdServer.h"
#include "CodeComplete.h"
+#include "FSProvider.h"
#include <cstdio>
#include <sstream>
@@ -29,13 +29,15 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
std::FILE *In = fmemopen(data, size, "r");
auto Transport = newJSONTransport(In, llvm::nulls(),
/*InMirror=*/nullptr, /*Pretty=*/false,
- /*Style=*/JSONStreamStyle::Standard);
+ /*Style=*/JSONStreamStyle::Delimited);
+ RealFileSystemProvider FS;
CodeCompleteOptions CCOpts;
CCOpts.EnableSnippets = false;
ClangdServer::Options Opts;
// Initialize and run ClangdLSPServer.
- ClangdLSPServer LSPServer(*Transport, CCOpts, llvm::None, false, Opts);
+ ClangdLSPServer LSPServer(*Transport, FS, CCOpts, llvm::None, false,
+ llvm::None, Opts);
LSPServer.run();
return 0;
}
diff --git a/clangd/include-mapping/gen_std.py b/clangd/include-mapping/gen_std.py
new file mode 100755
index 00000000..bfa6d0d4
--- /dev/null
+++ b/clangd/include-mapping/gen_std.py
@@ -0,0 +1,252 @@
+#!/usr/bin/env python
+#===- gen_std.py - ------------------------------------------*- python -*--===#
+#
+# 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
+#
+#===------------------------------------------------------------------------===#
+
+"""gen_std.py is a tool to generate a lookup table (from qualified names to
+include headers) for C++ Standard Library symbols by parsing archieved HTML
+files from cppreference.
+
+Caveats and FIXMEs:
+ - only symbols directly in "std" namespace are added, we should also add std's
+ subnamespace symbols (e.g. chrono).
+ - symbols with multiple variants or defined in multiple headers aren't added,
+ e.g. std::move, std::swap
+
+Usage:
+ 1. Install BeautifulSoup dependency, see instruction:
+ https://www.crummy.com/software/BeautifulSoup/bs4/doc/#installing-beautiful-soup
+ 2. Download cppreference offline HTML files (e.g. html_book_20181028.zip) at
+ https://en.cppreference.com/w/Cppreference:Archives
+ 3. Unzip the zip file from step 2 to directory </cppreference>, you should
+ get a "reference" directory in </cppreference>
+ 4. Run the command:
+ gen_std.py -cppreference </cppreference/reference> > StdSymbolMap.inc
+"""
+
+from bs4 import BeautifulSoup, NavigableString
+
+import argparse
+import collections
+import datetime
+import multiprocessing
+import os
+import re
+import signal
+import sys
+
+STDGEN_CODE_PREFIX = """\
+//===-- gen_std.py generated file -------------------------------*- C++ -*-===//
+//
+// Used to build a lookup table (qualified names => include headers) for C++
+// Standard Library symbols.
+//
+// Automatically generated file, DO NOT EDIT!
+//
+// Generated from cppreference offline HTML book (modified on %s).
+//===----------------------------------------------------------------------===//
+"""
+
+def HasClass(tag, *classes):
+ for c in tag.get('class', []):
+ if c in classes:
+ return True
+ return False
+
+def ParseSymbolPage(symbol_page_html, symbol_name):
+ """Parse symbol page and retrieve the include header defined in this page.
+ The symbol page provides header for the symbol, specifically in
+ "Defined in header <header>" section. An example:
+
+ <tr class="t-dsc-header">
+ <td colspan="2"> <div>Defined in header <code>&lt;ratio&gt;</code> </div>
+ </td></tr>
+
+ Returns a list of headers.
+ """
+ headers = set()
+ all_headers = set()
+
+ soup = BeautifulSoup(symbol_page_html, "html.parser")
+ # Rows in table are like:
+ # Defined in header <foo> .t-dsc-header
+ # Defined in header <bar> .t-dsc-header
+ # decl1 .t-dcl
+ # Defined in header <baz> .t-dsc-header
+ # decl2 .t-dcl
+ for table in soup.select('table.t-dcl-begin, table.t-dsc-begin'):
+ current_headers = []
+ was_decl = False
+ for row in table.select('tr'):
+ if HasClass(row, 't-dcl', 't-dsc'):
+ was_decl = True
+ # Declaration is in the first cell.
+ text = row.find('td').text
+ # Decl may not be for the symbol name we're looking for.
+ if not re.search("\\b%s\\b" % symbol_name, text):
+ continue
+ headers.update(current_headers)
+ elif HasClass(row, 't-dsc-header'):
+ # If we saw a decl since the last header, this is a new block of headers
+ # for a new block of decls.
+ if was_decl:
+ current_headers = []
+ was_decl = False
+ # There are also .t-dsc-header for "defined in namespace".
+ if not "Defined in header " in row.text:
+ continue
+ # The interesting header content (e.g. <cstdlib>) is wrapped in <code>.
+ for header_code in row.find_all("code"):
+ current_headers.append(header_code.text)
+ all_headers.add(header_code.text)
+ # If the symbol was never named, consider all named headers.
+ return headers or all_headers
+
+
+def ParseIndexPage(index_page_html):
+ """Parse index page.
+ The index page lists all std symbols and hrefs to their detailed pages
+ (which contain the defined header). An example:
+
+ <a href="abs.html" title="abs"><tt>abs()</tt></a> (int) <br>
+ <a href="acos.html" title="acos"><tt>acos()</tt></a> <br>
+
+ Returns a list of tuple (symbol_name, relative_path_to_symbol_page, variant).
+ """
+ symbols = []
+ soup = BeautifulSoup(index_page_html, "html.parser")
+ for symbol_href in soup.select("a[title]"):
+ # Ignore annotated symbols like "acos<>() (std::complex)".
+ # These tend to be overloads, and we the primary is more useful.
+ # This accidentally accepts begin/end despite the (iterator) caption: the
+ # (since C++11) note is first. They are good symbols, so the bug is unfixed.
+ caption = symbol_href.next_sibling
+ variant = isinstance(caption, NavigableString) and "(" in caption
+ symbol_tt = symbol_href.find("tt")
+ if symbol_tt:
+ symbols.append((symbol_tt.text.rstrip("<>()"), # strip any trailing <>()
+ symbol_href["href"], variant))
+ return symbols
+
+class Symbol:
+
+ def __init__(self, name, namespace, headers):
+ # unqualifed symbol name, e.g. "move"
+ self.name = name
+ # namespace of the symbol (with trailing "::"), e.g. "std::"
+ self.namespace = namespace
+ # a list of corresponding headers
+ self.headers = headers
+
+
+def ReadSymbolPage(path, name):
+ with open(path) as f:
+ return ParseSymbolPage(f.read(), name)
+
+
+def GetSymbols(pool, root_dir, index_page_name, namespace):
+ """Get all symbols listed in the index page. All symbols should be in the
+ given namespace.
+
+ Returns a list of Symbols.
+ """
+
+ # Workflow steps:
+ # 1. Parse index page which lists all symbols to get symbol
+ # name (unqualified name) and its href link to the symbol page which
+ # contains the defined header.
+ # 2. Parse the symbol page to get the defined header.
+ index_page_path = os.path.join(root_dir, index_page_name)
+ with open(index_page_path, "r") as f:
+ # Read each symbol page in parallel.
+ results = [] # (symbol_name, promise of [header...])
+ for symbol_name, symbol_page_path, variant in ParseIndexPage(f.read()):
+ # Variant symbols (e.g. the std::locale version of isalpha) add ambiguity.
+ # FIXME: use these as a fallback rather than ignoring entirely.
+ if variant:
+ continue
+ path = os.path.join(root_dir, symbol_page_path)
+ results.append((symbol_name,
+ pool.apply_async(ReadSymbolPage, (path, symbol_name))))
+
+ # Build map from symbol name to a set of headers.
+ symbol_headers = collections.defaultdict(set)
+ for symbol_name, lazy_headers in results:
+ symbol_headers[symbol_name].update(lazy_headers.get())
+
+ symbols = []
+ for name, headers in sorted(symbol_headers.items(), key=lambda t : t[0]):
+ symbols.append(Symbol(name, namespace, list(headers)))
+ return symbols
+
+
+def ParseArg():
+ parser = argparse.ArgumentParser(description='Generate StdGen file')
+ parser.add_argument('-cppreference', metavar='PATH',
+ default='',
+ help='path to the cppreference offline HTML directory',
+ required=True
+ )
+ return parser.parse_args()
+
+
+def main():
+ args = ParseArg()
+ cpp_root = os.path.join(args.cppreference, "en", "cpp")
+ symbol_index_root = os.path.join(cpp_root, "symbol_index")
+ if not os.path.exists(symbol_index_root):
+ exit("Path %s doesn't exist!" % symbol_index_root)
+
+ parse_pages = [
+ (cpp_root, "symbol_index.html", "std::"),
+ # std sub-namespace symbols have separated pages.
+ # We don't index std literal operators (e.g.
+ # std::literals::chrono_literals::operator""d), these symbols can't be
+ # accessed by std::<symbol_name>.
+ # FIXME: index std::placeholders symbols, placeholders.html page is
+ # different (which contains one entry for _1, _2, ..., _N), we need special
+ # handling.
+ (symbol_index_root, "chrono.html", "std::chrono::"),
+ (symbol_index_root, "filesystem.html", "std::filesystem::"),
+ (symbol_index_root, "pmr.html", "std::pmr::"),
+ (symbol_index_root, "regex_constants.html", "std::regex_constants::"),
+ (symbol_index_root, "this_thread.html", "std::this_thread::"),
+ ]
+
+ symbols = []
+ # Run many workers to process individual symbol pages under the symbol index.
+ # Don't allow workers to capture Ctrl-C.
+ pool = multiprocessing.Pool(
+ initializer=lambda: signal.signal(signal.SIGINT, signal.SIG_IGN))
+ try:
+ for root_dir, page_name, namespace in parse_pages:
+ symbols.extend(GetSymbols(pool, root_dir, page_name, namespace))
+ finally:
+ pool.terminate()
+ pool.join()
+
+ # We don't have version information from the unzipped offline HTML files.
+ # so we use the modified time of the symbol_index.html as the version.
+ index_page_path = os.path.join(cpp_root, "symbol_index.html")
+ cppreference_modified_date = datetime.datetime.fromtimestamp(
+ os.stat(index_page_path).st_mtime).strftime('%Y-%m-%d')
+ print STDGEN_CODE_PREFIX % cppreference_modified_date
+ for symbol in symbols:
+ if len(symbol.headers) == 1:
+ # SYMBOL(unqualified_name, namespace, header)
+ print "SYMBOL(%s, %s, %s)" % (symbol.name, symbol.namespace,
+ symbol.headers[0])
+ elif len(symbol.headers) == 0:
+ sys.stderr.write("No header found for symbol %s\n" % symbol.name)
+ else:
+ # FIXME: support symbols with multiple headers (e.g. std::move).
+ sys.stderr.write("Ambiguous header for symbol %s: %s\n" % (
+ symbol.name, ', '.join(symbol.headers)))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/clangd/include-mapping/test.py b/clangd/include-mapping/test.py
new file mode 100755
index 00000000..10725769
--- /dev/null
+++ b/clangd/include-mapping/test.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+#===- test.py - ---------------------------------------------*- python -*--===#
+#
+# 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
+#
+#===------------------------------------------------------------------------===#
+
+from gen_std import ParseSymbolPage, ParseIndexPage
+
+import unittest
+
+class TestStdGen(unittest.TestCase):
+
+ def testParseIndexPage(self):
+ html = """
+ <a href="abs.html" title="abs"><tt>abs()</tt></a> (int) <br>
+ <a href="complex/abs.html" title="abs"><tt>abs&lt;&gt;()</tt></a> (std::complex) <br>
+ <a href="acos.html" title="acos"><tt>acos()</tt></a> <br>
+ <a href="acosh.html" title="acosh"><tt>acosh()</tt></a> <span class="t-mark-rev">(since C++11)</span> <br>
+ <a href="as_bytes.html" title="as bytes"><tt>as_bytes&lt;&gt;()</tt></a> <span class="t-mark-rev t-since-cxx20">(since C++20)</span> <br>
+ """
+
+ actual = ParseIndexPage(html)
+ expected = [
+ ("abs", "abs.html", True),
+ ("abs", "complex/abs.html", True),
+ ("acos", "acos.html", False),
+ ("acosh", "acosh.html", False),
+ ("as_bytes", "as_bytes.html", False),
+ ]
+ self.assertEqual(len(actual), len(expected))
+ for i in range(0, len(actual)):
+ self.assertEqual(expected[i][0], actual[i][0])
+ self.assertTrue(actual[i][1].endswith(expected[i][1]))
+ self.assertEqual(expected[i][2], actual[i][2])
+
+
+ def testParseSymbolPage_SingleHeader(self):
+ # Defined in header <cmath>
+ html = """
+ <table class="t-dcl-begin"><tbody>
+ <tr class="t-dsc-header">
+ <td> <div>Defined in header <code><a href="cmath.html" title="cmath">&lt;cmath&gt;</a></code>
+ </div></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr class="t-dcl">
+ <td>void foo()</td>
+ <td>this is matched</td>
+ </tr>
+</tbody></table>
+"""
+ self.assertEqual(ParseSymbolPage(html, 'foo'), set(['<cmath>']))
+
+
+ def testParseSymbolPage_MulHeaders(self):
+ # Defined in header <cstddef>
+ # Defined in header <cstdio>
+ # Defined in header <cstdlib>
+ html = """
+<table class="t-dcl-begin"><tbody>
+ <tr class="t-dsc-header">
+ <td> <div>Defined in header <code><a href="cstddef.html" title="cstddef">&lt;cstddef&gt;</a></code>
+ </div></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr class="t-dcl">
+ <td>void bar()</td>
+ <td>this mentions foo, but isn't matched</td>
+ </tr>
+ <tr class="t-dsc-header">
+ <td> <div>Defined in header <code><a href="cstdio.html" title="cstdio">&lt;cstdio&gt;</a></code>
+ </div></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr class="t-dsc-header">
+ <td> <div>Defined in header <code><a href=".cstdlib.html" title="ccstdlib">&lt;cstdlib&gt;</a></code>
+ </div></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr class="t-dcl">
+ <td>void foo()</td>
+ <td>this is matched</td>
+ </tr>
+</tbody></table>
+"""
+ self.assertEqual(ParseSymbolPage(html, "foo"),
+ set(['<cstdio>', '<cstdlib>']))
+
+
+ def testParseSymbolPage_MulHeadersInSameDiv(self):
+ # Multile <code> blocks in a Div.
+ # Defined in header <algorithm>
+ # Defined in header <utility>
+ html = """
+<table class="t-dcl-begin"><tbody>
+<tr class="t-dsc-header">
+<td><div>
+ Defined in header <code><a href="../header/algorithm.html" title="cpp/header/algorithm">&lt;algorithm&gt;</a></code><br>
+ Defined in header <code><a href="../header/utility.html" title="cpp/header/utility">&lt;utility&gt;</a></code>
+</div></td>
+<td></td>
+</tr>
+<tr class="t-dcl">
+ <td>void foo()</td>
+ <td>this is matched</td>
+</tr>
+</tbody></table>
+"""
+ self.assertEqual(ParseSymbolPage(html, "foo"),
+ set(['<algorithm>', '<utility>']))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/clangd/index/Background.cpp b/clangd/index/Background.cpp
index b9b945c5..0746a358 100644
--- a/clangd/index/Background.cpp
+++ b/clangd/index/Background.cpp
@@ -1,9 +1,8 @@
//===-- Background.cpp - Build an index in a background thread ------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -12,6 +11,7 @@
#include "Compiler.h"
#include "Logger.h"
#include "SourceCode.h"
+#include "Symbol.h"
#include "Threading.h"
#include "Trace.h"
#include "URI.h"
@@ -26,7 +26,9 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/SHA1.h"
+#include "llvm/Support/Threading.h"
+#include <atomic>
#include <chrono>
#include <memory>
#include <numeric>
@@ -38,6 +40,9 @@
namespace clang {
namespace clangd {
namespace {
+
+static std::atomic<bool> PreventStarvation = {false};
+
// Resolves URI to file paths with cache.
class URIToFileCache {
public:
@@ -121,19 +126,19 @@ llvm::SmallString<128> getAbsolutePath(const tooling::CompileCommand &Cmd) {
} else {
AbsolutePath = Cmd.Directory;
llvm::sys::path::append(AbsolutePath, Cmd.Filename);
+ llvm::sys::path::remove_dots(AbsolutePath, true);
}
return AbsolutePath;
}
} // namespace
BackgroundIndex::BackgroundIndex(
- Context BackgroundContext, llvm::StringRef ResourceDir,
- const FileSystemProvider &FSProvider, const GlobalCompilationDatabase &CDB,
+ Context BackgroundContext, const FileSystemProvider &FSProvider,
+ const GlobalCompilationDatabase &CDB,
BackgroundIndexStorage::Factory IndexStorageFactory,
size_t BuildIndexPeriodMs, size_t ThreadPoolSize)
- : SwapIndex(llvm::make_unique<MemIndex>()), ResourceDir(ResourceDir),
- FSProvider(FSProvider), CDB(CDB),
- BackgroundContext(std::move(BackgroundContext)),
+ : SwapIndex(llvm::make_unique<MemIndex>()), FSProvider(FSProvider),
+ CDB(CDB), BackgroundContext(std::move(BackgroundContext)),
BuildIndexPeriodMs(BuildIndexPeriodMs),
SymbolsUpdatedSinceLastIndex(false),
IndexStorageFactory(std::move(IndexStorageFactory)),
@@ -172,7 +177,7 @@ void BackgroundIndex::run() {
WithContext Background(BackgroundContext.clone());
while (true) {
llvm::Optional<Task> Task;
- ThreadPriority Priority;
+ llvm::ThreadPriority Priority;
{
std::unique_lock<std::mutex> Lock(QueueMu);
QueueCV.wait(Lock, [&] { return ShouldStop || !Queue.empty(); });
@@ -186,11 +191,11 @@ void BackgroundIndex::run() {
Queue.pop_front();
}
- if (Priority != ThreadPriority::Normal)
- setCurrentThreadPriority(Priority);
+ if (Priority != llvm::ThreadPriority::Default && !PreventStarvation.load())
+ llvm::set_thread_priority(Priority);
(*Task)();
- if (Priority != ThreadPriority::Normal)
- setCurrentThreadPriority(ThreadPriority::Normal);
+ if (Priority != llvm::ThreadPriority::Default)
+ llvm::set_thread_priority(llvm::ThreadPriority::Default);
{
std::unique_lock<std::mutex> Lock(QueueMu);
@@ -223,14 +228,13 @@ void BackgroundIndex::enqueue(const std::vector<std::string> &ChangedFiles) {
for (auto &Elem : NeedsReIndexing)
enqueue(std::move(Elem.first), Elem.second);
},
- ThreadPriority::Normal);
+ llvm::ThreadPriority::Default);
}
void BackgroundIndex::enqueue(tooling::CompileCommand Cmd,
BackgroundIndexStorage *Storage) {
enqueueTask(Bind(
[this, Storage](tooling::CompileCommand Cmd) {
- Cmd.CommandLine.push_back("-resource-dir=" + ResourceDir);
// We can't use llvm::StringRef here since we are going to
// move from Cmd during the call below.
const std::string FileName = Cmd.Filename;
@@ -239,10 +243,10 @@ void BackgroundIndex::enqueue(tooling::CompileCommand Cmd,
std::move(Error));
},
std::move(Cmd)),
- ThreadPriority::Low);
+ llvm::ThreadPriority::Background);
}
-void BackgroundIndex::enqueueTask(Task T, ThreadPriority Priority) {
+void BackgroundIndex::enqueueTask(Task T, llvm::ThreadPriority Priority) {
{
std::lock_guard<std::mutex> Lock(QueueMu);
auto I = Queue.end();
@@ -250,10 +254,11 @@ void BackgroundIndex::enqueueTask(Task T, ThreadPriority Priority) {
// Then we store low priority tasks. Normal priority tasks are pretty rare,
// they should not grow beyond single-digit numbers, so it is OK to do
// linear search and insert after that.
- if (Priority == ThreadPriority::Normal) {
- I = llvm::find_if(Queue, [](const std::pair<Task, ThreadPriority> &Elem) {
- return Elem.second == ThreadPriority::Low;
- });
+ if (Priority == llvm::ThreadPriority::Default) {
+ I = llvm::find_if(
+ Queue, [](const std::pair<Task, llvm::ThreadPriority> &Elem) {
+ return Elem.second == llvm::ThreadPriority::Background;
+ });
}
Queue.insert(I, {std::move(T), Priority});
}
@@ -375,7 +380,9 @@ void BackgroundIndex::buildIndex() {
// extra index build.
reset(
IndexedSymbols.buildIndex(IndexType::Heavy, DuplicateHandling::Merge));
- log("BackgroundIndex: rebuilt symbol index.");
+ log("BackgroundIndex: rebuilt symbol index with estimated memory {0} "
+ "bytes.",
+ estimateMemoryUsage());
}
}
@@ -398,7 +405,7 @@ llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd,
DigestsSnapshot = IndexedFileDigests;
}
- log("Indexing {0} (digest:={1})", Cmd.Filename, llvm::toHex(Hash));
+ vlog("Indexing {0} (digest:={1})", Cmd.Filename, llvm::toHex(Hash));
ParseInputs Inputs;
Inputs.FS = std::move(FS);
Inputs.FS->setCurrentWorkingDirectory(Cmd.Directory);
@@ -408,9 +415,8 @@ llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd,
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"Couldn't build compiler invocation");
IgnoreDiagnostics IgnoreDiags;
- auto Clang = prepareCompilerInstance(
- std::move(CI), /*Preamble=*/nullptr, std::move(*Buf),
- std::make_shared<PCHContainerOperations>(), Inputs.FS, IgnoreDiags);
+ auto Clang = prepareCompilerInstance(std::move(CI), /*Preamble=*/nullptr,
+ std::move(*Buf), Inputs.FS, IgnoreDiags);
if (!Clang)
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"Couldn't build compiler instance");
@@ -604,10 +610,16 @@ BackgroundIndex::loadShards(std::vector<std::string> ChangedFiles) {
}
}
vlog("Loaded all shards");
- reset(IndexedSymbols.buildIndex(IndexType::Light, DuplicateHandling::Merge));
-
+ reset(IndexedSymbols.buildIndex(IndexType::Heavy, DuplicateHandling::Merge));
+ vlog("BackgroundIndex: built symbol index with estimated memory {0} "
+ "bytes.",
+ estimateMemoryUsage());
return NeedsReIndexing;
}
+void BackgroundIndex::preventThreadStarvationInTests() {
+ PreventStarvation.store(true);
+}
+
} // namespace clangd
} // namespace clang
diff --git a/clangd/index/Background.h b/clangd/index/Background.h
index 1a1fee68..2132e579 100644
--- a/clangd/index/Background.h
+++ b/clangd/index/Background.h
@@ -1,9 +1,8 @@
//===--- Background.h - Build an index in a background thread ----*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -55,7 +54,7 @@ public:
llvm::unique_function<BackgroundIndexStorage *(llvm::StringRef)>;
// Creates an Index Storage that saves shards into disk. Index storage uses
- // CDBDirectory + ".clangd-index/" as the folder to save shards.
+ // CDBDirectory + ".clangd/index/" as the folder to save shards.
static Factory createDiskBackedStorageFactory();
};
@@ -68,13 +67,12 @@ public:
/// If BuildIndexPeriodMs is greater than 0, the symbol index will only be
/// rebuilt periodically (one per \p BuildIndexPeriodMs); otherwise, index is
/// rebuilt for each indexed file.
- // FIXME: resource-dir injection should be hoisted somewhere common.
- BackgroundIndex(Context BackgroundContext, llvm::StringRef ResourceDir,
- const FileSystemProvider &,
- const GlobalCompilationDatabase &CDB,
- BackgroundIndexStorage::Factory IndexStorageFactory,
- size_t BuildIndexPeriodMs = 0,
- size_t ThreadPoolSize = llvm::hardware_concurrency());
+ BackgroundIndex(
+ Context BackgroundContext, const FileSystemProvider &,
+ const GlobalCompilationDatabase &CDB,
+ BackgroundIndexStorage::Factory IndexStorageFactory,
+ size_t BuildIndexPeriodMs = 0,
+ size_t ThreadPoolSize = llvm::heavyweight_hardware_concurrency());
~BackgroundIndex(); // Blocks while the current task finishes.
// Enqueue translation units for indexing.
@@ -90,6 +88,10 @@ public:
LLVM_NODISCARD bool
blockUntilIdleForTest(llvm::Optional<double> TimeoutSeconds = 10);
+ // Disables thread priority lowering in background index to make sure it can
+ // progress on loaded systems. Only affects tasks that run after the call.
+ static void preventThreadStarvationInTests();
+
private:
/// Given index results from a TU, only update symbols coming from files with
/// different digests than \p DigestsSnapshot. Also stores new index
@@ -99,7 +101,6 @@ private:
BackgroundIndexStorage *IndexStorage);
// configuration
- std::string ResourceDir;
const FileSystemProvider &FSProvider;
const GlobalCompilationDatabase &CDB;
Context BackgroundContext;
@@ -137,14 +138,14 @@ private:
// queue management
using Task = std::function<void()>;
void run(); // Main loop executed by Thread. Runs tasks from Queue.
- void enqueueTask(Task T, ThreadPriority Prioirty);
+ void enqueueTask(Task T, llvm::ThreadPriority Prioirty);
void enqueueLocked(tooling::CompileCommand Cmd,
BackgroundIndexStorage *IndexStorage);
std::mutex QueueMu;
unsigned NumActiveTasks = 0; // Only idle when queue is empty *and* no tasks.
std::condition_variable QueueCV;
bool ShouldStop = false;
- std::deque<std::pair<Task, ThreadPriority>> Queue;
+ std::deque<std::pair<Task, llvm::ThreadPriority>> Queue;
std::vector<std::thread> ThreadPool; // FIXME: Abstract this away.
GlobalCompilationDatabase::CommandChanged::Subscription CommandsChanged;
};
diff --git a/clangd/index/BackgroundIndexStorage.cpp b/clangd/index/BackgroundIndexStorage.cpp
index a83bec6f..42db1dc5 100644
--- a/clangd/index/BackgroundIndexStorage.cpp
+++ b/clangd/index/BackgroundIndexStorage.cpp
@@ -1,9 +1,8 @@
//== BackgroundIndexStorage.cpp - Provide caching support to BackgroundIndex ==/
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -64,19 +63,19 @@ writeAtomically(llvm::StringRef OutPath,
}
// Uses disk as a storage for index shards. Creates a directory called
-// ".clangd-index/" under the path provided during construction.
+// ".clangd/index/" under the path provided during construction.
class DiskBackedIndexStorage : public BackgroundIndexStorage {
std::string DiskShardRoot;
public:
- // Sets DiskShardRoot to (Directory + ".clangd-index/") which is the base
+ // Sets DiskShardRoot to (Directory + ".clangd/index/") which is the base
// directory for all shard files.
DiskBackedIndexStorage(llvm::StringRef Directory) {
llvm::SmallString<128> CDBDirectory(Directory);
- llvm::sys::path::append(CDBDirectory, ".clangd-index/");
+ llvm::sys::path::append(CDBDirectory, ".clangd", "index");
DiskShardRoot = CDBDirectory.str();
std::error_code OK;
- std::error_code EC = llvm::sys::fs::create_directory(DiskShardRoot);
+ std::error_code EC = llvm::sys::fs::create_directories(DiskShardRoot);
if (EC != OK) {
elog("Failed to create directory {0} for index storage: {1}",
DiskShardRoot, EC.message());
@@ -138,9 +137,6 @@ public:
return IndexStorage.get();
}
- // Creates or fetches to storage from cache for the specified CDB.
- BackgroundIndexStorage *createStorage(llvm::StringRef CDBDirectory);
-
private:
std::unique_ptr<BackgroundIndexStorage> create(llvm::StringRef CDBDirectory) {
if (CDBDirectory.empty())
diff --git a/clangd/index/CanonicalIncludes.cpp b/clangd/index/CanonicalIncludes.cpp
index 7351b861..25bbffb1 100644
--- a/clangd/index/CanonicalIncludes.cpp
+++ b/clangd/index/CanonicalIncludes.cpp
@@ -1,9 +1,8 @@
//===-- CanonicalIncludes.h - remap #inclue headers--------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -38,31 +37,12 @@ void CanonicalIncludes::addSymbolMapping(llvm::StringRef QualifiedName,
}
llvm::StringRef
-CanonicalIncludes::mapHeader(llvm::ArrayRef<std::string> Headers,
+CanonicalIncludes::mapHeader(llvm::StringRef Header,
llvm::StringRef QualifiedName) const {
- assert(!Headers.empty());
+ assert(!Header.empty());
auto SE = SymbolMapping.find(QualifiedName);
if (SE != SymbolMapping.end())
return SE->second;
- // Find the first header such that the extension is not '.inc', and isn't a
- // recognized non-header file
- auto I = llvm::find_if(Headers, [](llvm::StringRef Include) {
- // Skip .inc file whose including header file should
- // be #included instead.
- return !Include.endswith(".inc");
- });
- if (I == Headers.end())
- return Headers[0]; // Fallback to the declaring header.
- llvm::StringRef Header = *I;
- // If Header is not expected be included (e.g. .cc file), we fall back to
- // the declaring header.
- llvm::StringRef Ext = llvm::sys::path::extension(Header).trim('.');
- // Include-able headers must have precompile type. Treat files with
- // non-recognized extenstions (TY_INVALID) as headers.
- auto ExtType = driver::types::lookupTypeForExtension(Ext);
- if ((ExtType != driver::types::TY_INVALID) &&
- !driver::types::onlyPrecompileType(ExtType))
- return Headers[0];
auto MapIt = FullPathMapping.find(Header);
if (MapIt != FullPathMapping.end())
@@ -108,57 +88,30 @@ collectIWYUHeaderMaps(CanonicalIncludes *Includes) {
void addSystemHeadersMapping(CanonicalIncludes *Includes) {
static const std::vector<std::pair<const char *, const char *>> SymbolMap = {
- {"std::addressof", "<memory>"},
// Map symbols in <iosfwd> to their preferred includes.
{"std::basic_filebuf", "<fstream>"},
- {"std::basic_fstream", "<fstream>"},
- {"std::basic_ifstream", "<fstream>"},
- {"std::basic_ofstream", "<fstream>"},
{"std::filebuf", "<fstream>"},
- {"std::fstream", "<fstream>"},
- {"std::ifstream", "<fstream>"},
- {"std::ofstream", "<fstream>"},
{"std::wfilebuf", "<fstream>"},
- {"std::wfstream", "<fstream>"},
- {"std::wifstream", "<fstream>"},
- {"std::wofstream", "<fstream>"},
- {"std::basic_ios", "<ios>"},
- {"std::ios", "<ios>"},
- {"std::wios", "<ios>"},
- {"std::basic_iostream", "<iostream>"},
- {"std::iostream", "<iostream>"},
- {"std::wiostream", "<iostream>"},
{"std::basic_istream", "<istream>"},
{"std::istream", "<istream>"},
{"std::wistream", "<istream>"},
- {"std::istreambuf_iterator", "<iterator>"},
- {"std::ostreambuf_iterator", "<iterator>"},
{"std::basic_ostream", "<ostream>"},
{"std::ostream", "<ostream>"},
{"std::wostream", "<ostream>"},
- {"std::basic_istringstream", "<sstream>"},
- {"std::basic_ostringstream", "<sstream>"},
- {"std::basic_stringbuf", "<sstream>"},
- {"std::basic_stringstream", "<sstream>"},
- {"std::istringstream", "<sstream>"},
- {"std::ostringstream", "<sstream>"},
- {"std::string", "<string>"},
- {"std::stringbuf", "<sstream>"},
- {"std::stringstream", "<sstream>"},
- {"std::wistringstream", "<sstream>"},
- {"std::wostringstream", "<sstream>"},
- {"std::wstringbuf", "<sstream>"},
- {"std::wstringstream", "<sstream>"},
- {"std::basic_streambuf", "<streambuf>"},
- {"std::streambuf", "<streambuf>"},
- {"std::wstreambuf", "<streambuf>"},
{"std::uint_least16_t", "<cstdint>"}, // <type_traits> redeclares these
{"std::uint_least32_t", "<cstdint>"},
- {"std::declval", "<utility>"},
+#define SYMBOL(Name, NameSpace, Header) { #NameSpace#Name, #Header },
+ #include "StdSymbolMap.inc"
+#undef SYMBOL
};
for (const auto &Pair : SymbolMap)
Includes->addSymbolMapping(Pair.first, Pair.second);
+ // FIXME: remove the std header mapping once we support ambiguous symbols, now
+ // it serves as a fallback to disambiguate:
+ // - symbols with mulitiple headers (e.g. std::move)
+ // - symbols with a primary template in one header and a specialization in
+ // another (std::abs)
static const std::vector<std::pair<const char *, const char *>>
SystemHeaderMap = {
{"include/__stddef_max_align_t.h", "<cstddef>"},
diff --git a/clangd/index/CanonicalIncludes.h b/clangd/index/CanonicalIncludes.h
index 3751b000..f85b76bf 100644
--- a/clangd/index/CanonicalIncludes.h
+++ b/clangd/index/CanonicalIncludes.h
@@ -1,9 +1,8 @@
//===-- CanonicalIncludes.h - remap #include header -------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -51,9 +50,9 @@ public:
llvm::StringRef CanonicalPath);
/// Returns the canonical include for symbol with \p QualifiedName.
- /// \p Headers is the include stack: Headers.front() is the file declaring the
- /// symbol, and Headers.back() is the main file.
- llvm::StringRef mapHeader(llvm::ArrayRef<std::string> Headers,
+ /// \p Header is the file the declaration was reachable from.
+ /// Header itself will be returned if there is no relevant mapping.
+ llvm::StringRef mapHeader(llvm::StringRef Header,
llvm::StringRef QualifiedName) const;
private:
diff --git a/clangd/index/FileIndex.cpp b/clangd/index/FileIndex.cpp
index d3e3596d..7eca85e2 100644
--- a/clangd/index/FileIndex.cpp
+++ b/clangd/index/FileIndex.cpp
@@ -1,9 +1,8 @@
//===--- FileIndex.cpp - Indexes for files. ------------------------ C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -11,9 +10,11 @@
#include "ClangdUnit.h"
#include "Logger.h"
#include "SymbolCollector.h"
+#include "index/CanonicalIncludes.h"
#include "index/Index.h"
#include "index/MemIndex.h"
#include "index/Merge.h"
+#include "index/SymbolOrigin.h"
#include "index/dex/Dex.h"
#include "clang/Index/IndexingAction.h"
#include "clang/Lex/MacroInfo.h"
@@ -29,14 +30,11 @@ namespace clangd {
static std::pair<SymbolSlab, RefSlab>
indexSymbols(ASTContext &AST, std::shared_ptr<Preprocessor> PP,
- llvm::ArrayRef<Decl *> DeclsToIndex, bool IsIndexMainAST) {
+ llvm::ArrayRef<Decl *> DeclsToIndex,
+ const CanonicalIncludes &Includes, bool IsIndexMainAST) {
SymbolCollector::Options CollectorOpts;
- // FIXME(ioeric): we might also want to collect include headers. We would need
- // to make sure all includes are canonicalized (with CanonicalIncludes), which
- // is not trivial given the current way of collecting symbols: we only have
- // AST at this point, but we also need preprocessor callbacks (e.g.
- // CommentHandler for IWYU pragma) to canonicalize includes.
- CollectorOpts.CollectIncludePath = false;
+ CollectorOpts.CollectIncludePath = true;
+ CollectorOpts.Includes = &Includes;
CollectorOpts.CountReferences = false;
CollectorOpts.Origin = SymbolOrigin::Dynamic;
@@ -48,9 +46,13 @@ indexSymbols(ASTContext &AST, std::shared_ptr<Preprocessor> PP,
if (IsIndexMainAST) {
// We only collect refs when indexing main AST.
CollectorOpts.RefFilter = RefKind::All;
- }else {
+ // Comments for main file can always be obtained from sema, do not store
+ // them in the index.
+ CollectorOpts.StoreAllDocumentation = false;
+ } else {
IndexOpts.IndexMacrosInPreprocessor = true;
CollectorOpts.CollectMacro = true;
+ CollectorOpts.StoreAllDocumentation = true;
}
SymbolCollector Collector(std::move(CollectorOpts));
@@ -73,16 +75,16 @@ indexSymbols(ASTContext &AST, std::shared_ptr<Preprocessor> PP,
std::pair<SymbolSlab, RefSlab> indexMainDecls(ParsedAST &AST) {
return indexSymbols(AST.getASTContext(), AST.getPreprocessorPtr(),
- AST.getLocalTopLevelDecls(),
+ AST.getLocalTopLevelDecls(), AST.getCanonicalIncludes(),
/*IsIndexMainAST=*/true);
}
-SymbolSlab indexHeaderSymbols(ASTContext &AST,
- std::shared_ptr<Preprocessor> PP) {
+SymbolSlab indexHeaderSymbols(ASTContext &AST, std::shared_ptr<Preprocessor> PP,
+ const CanonicalIncludes &Includes) {
std::vector<Decl *> DeclsToIndex(
AST.getTranslationUnitDecl()->decls().begin(),
AST.getTranslationUnitDecl()->decls().end());
- return indexSymbols(AST, std::move(PP), DeclsToIndex,
+ return indexSymbols(AST, std::move(PP), DeclsToIndex, Includes,
/*IsIndexMainAST=*/false)
.first;
}
@@ -196,8 +198,9 @@ FileIndex::FileIndex(bool UseDex)
MainFileIndex(llvm::make_unique<MemIndex>()) {}
void FileIndex::updatePreamble(PathRef Path, ASTContext &AST,
- std::shared_ptr<Preprocessor> PP) {
- auto Symbols = indexHeaderSymbols(AST, std::move(PP));
+ std::shared_ptr<Preprocessor> PP,
+ const CanonicalIncludes &Includes) {
+ auto Symbols = indexHeaderSymbols(AST, std::move(PP), Includes);
PreambleSymbols.update(Path,
llvm::make_unique<SymbolSlab>(std::move(Symbols)),
llvm::make_unique<RefSlab>());
diff --git a/clangd/index/FileIndex.h b/clangd/index/FileIndex.h
index 92e3b2b6..d9bee888 100644
--- a/clangd/index/FileIndex.h
+++ b/clangd/index/FileIndex.h
@@ -1,9 +1,8 @@
//===--- FileIndex.h - Index for files. ---------------------------- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -20,6 +19,8 @@
#include "Index.h"
#include "MemIndex.h"
#include "Merge.h"
+#include "index/CanonicalIncludes.h"
+#include "index/Symbol.h"
#include "clang/Lex/Preprocessor.h"
#include <memory>
@@ -85,7 +86,8 @@ public:
/// Update preamble symbols of file \p Path with all declarations in \p AST
/// and macros in \p PP.
void updatePreamble(PathRef Path, ASTContext &AST,
- std::shared_ptr<Preprocessor> PP);
+ std::shared_ptr<Preprocessor> PP,
+ const CanonicalIncludes &Includes);
/// Update symbols and references from main file \p Path with
/// `indexMainDecls`.
@@ -125,8 +127,8 @@ std::pair<SymbolSlab, RefSlab> indexMainDecls(ParsedAST &AST);
/// Idex declarations from \p AST and macros from \p PP that are declared in
/// included headers.
-SymbolSlab indexHeaderSymbols(ASTContext &AST,
- std::shared_ptr<Preprocessor> PP);
+SymbolSlab indexHeaderSymbols(ASTContext &AST, std::shared_ptr<Preprocessor> PP,
+ const CanonicalIncludes &Includes);
} // namespace clangd
} // namespace clang
diff --git a/clangd/index/Index.cpp b/clangd/index/Index.cpp
index 4036d671..a5bfc672 100644
--- a/clangd/index/Index.cpp
+++ b/clangd/index/Index.cpp
@@ -1,9 +1,8 @@
//===--- Index.cpp -----------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -13,152 +12,11 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
+#include <limits>
namespace clang {
namespace clangd {
-constexpr uint32_t SymbolLocation::Position::MaxLine;
-constexpr uint32_t SymbolLocation::Position::MaxColumn;
-void SymbolLocation::Position::setLine(uint32_t L) {
- if (L > MaxLine) {
- Line = MaxLine;
- return;
- }
- Line = L;
-}
-void SymbolLocation::Position::setColumn(uint32_t Col) {
- if (Col > MaxColumn) {
- Column = MaxColumn;
- return;
- }
- Column = Col;
-}
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolLocation &L) {
- if (!L)
- return OS << "(none)";
- return OS << L.FileURI << "[" << L.Start.line() << ":" << L.Start.column()
- << "-" << L.End.line() << ":" << L.End.column() << ")";
-}
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SymbolOrigin O) {
- if (O == SymbolOrigin::Unknown)
- return OS << "unknown";
- constexpr static char Sigils[] = "ADSM4567";
- for (unsigned I = 0; I < sizeof(Sigils); ++I)
- if (static_cast<uint8_t>(O) & 1u << I)
- OS << Sigils[I];
- return OS;
-}
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Symbol::SymbolFlag F) {
- if (F == Symbol::None)
- return OS << "None";
- std::string s;
- if (F & Symbol::Deprecated)
- s += "deprecated|";
- if (F & Symbol::IndexedForCodeCompletion)
- s += "completion|";
- return OS << llvm::StringRef(s).rtrim('|');
-}
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S) {
- return OS << S.Scope << S.Name;
-}
-
-float quality(const Symbol &S) {
- // This avoids a sharp gradient for tail symbols, and also neatly avoids the
- // question of whether 0 references means a bad symbol or missing data.
- if (S.References < 3)
- return 1;
- return std::log(S.References);
-}
-
-SymbolSlab::const_iterator SymbolSlab::find(const SymbolID &ID) const {
- auto It = std::lower_bound(
- Symbols.begin(), Symbols.end(), ID,
- [](const Symbol &S, const SymbolID &I) { return S.ID < I; });
- if (It != Symbols.end() && It->ID == ID)
- return It;
- return Symbols.end();
-}
-
-// Copy the underlying data of the symbol into the owned arena.
-static void own(Symbol &S, llvm::UniqueStringSaver &Strings) {
- visitStrings(S, [&](llvm::StringRef &V) { V = Strings.save(V); });
-}
-
-void SymbolSlab::Builder::insert(const Symbol &S) {
- auto R = SymbolIndex.try_emplace(S.ID, Symbols.size());
- if (R.second) {
- Symbols.push_back(S);
- own(Symbols.back(), UniqueStrings);
- } else {
- auto &Copy = Symbols[R.first->second] = S;
- own(Copy, UniqueStrings);
- }
-}
-
-SymbolSlab SymbolSlab::Builder::build() && {
- Symbols = {Symbols.begin(), Symbols.end()}; // Force shrink-to-fit.
- // Sort symbols so the slab can binary search over them.
- llvm::sort(Symbols,
- [](const Symbol &L, const Symbol &R) { return L.ID < R.ID; });
- // We may have unused strings from overwritten symbols. Build a new arena.
- llvm::BumpPtrAllocator NewArena;
- llvm::UniqueStringSaver Strings(NewArena);
- for (auto &S : Symbols)
- own(S, Strings);
- return SymbolSlab(std::move(NewArena), std::move(Symbols));
-}
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, RefKind K) {
- if (K == RefKind::Unknown)
- return OS << "Unknown";
- static const std::vector<const char *> Messages = {"Decl", "Def", "Ref"};
- bool VisitedOnce = false;
- for (unsigned I = 0; I < Messages.size(); ++I) {
- if (static_cast<uint8_t>(K) & 1u << I) {
- if (VisitedOnce)
- OS << ", ";
- OS << Messages[I];
- VisitedOnce = true;
- }
- }
- return OS;
-}
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Ref &R) {
- return OS << R.Location << ":" << R.Kind;
-}
-
-void RefSlab::Builder::insert(const SymbolID &ID, const Ref &S) {
- auto &M = Refs[ID];
- M.push_back(S);
- M.back().Location.FileURI =
- UniqueStrings.save(M.back().Location.FileURI).data();
-}
-
-RefSlab RefSlab::Builder::build() && {
- // We can reuse the arena, as it only has unique strings and we need them all.
- // Reallocate refs on the arena to reduce waste and indirections when reading.
- std::vector<std::pair<SymbolID, llvm::ArrayRef<Ref>>> Result;
- Result.reserve(Refs.size());
- size_t NumRefs = 0;
- for (auto &Sym : Refs) {
- auto &SymRefs = Sym.second;
- llvm::sort(SymRefs);
- // FIXME: do we really need to dedup?
- SymRefs.erase(std::unique(SymRefs.begin(), SymRefs.end()), SymRefs.end());
-
- NumRefs += SymRefs.size();
- auto *Array = Arena.Allocate<Ref>(SymRefs.size());
- std::uninitialized_copy(SymRefs.begin(), SymRefs.end(), Array);
- Result.emplace_back(Sym.first, llvm::ArrayRef<Ref>(Array, SymRefs.size()));
- }
- return RefSlab(std::move(Result), std::move(Arena), NumRefs);
-}
-
void SwapIndex::reset(std::unique_ptr<SymbolIndex> Index) {
// Keep the old index alive, so we don't destroy it under lock (may be slow).
std::shared_ptr<SymbolIndex> Pin;
@@ -180,7 +38,8 @@ bool fromJSON(const llvm::json::Value &Parameters, FuzzyFindRequest &Request) {
O && O.map("Query", Request.Query) && O.map("Scopes", Request.Scopes) &&
O.map("AnyScope", Request.AnyScope) && O.map("Limit", Limit) &&
O.map("RestrictForCodeCompletion", Request.RestrictForCodeCompletion) &&
- O.map("ProximityPaths", Request.ProximityPaths);
+ O.map("ProximityPaths", Request.ProximityPaths) &&
+ O.map("PreferredTypes", Request.PreferredTypes);
if (OK && Limit <= std::numeric_limits<uint32_t>::max())
Request.Limit = Limit;
return OK;
@@ -194,6 +53,7 @@ llvm::json::Value toJSON(const FuzzyFindRequest &Request) {
{"Limit", Request.Limit},
{"RestrictForCodeCompletion", Request.RestrictForCodeCompletion},
{"ProximityPaths", llvm::json::Array{Request.ProximityPaths}},
+ {"PreferredTypes", llvm::json::Array{Request.PreferredTypes}},
};
}
diff --git a/clangd/index/Index.h b/clangd/index/Index.h
index cc4cf2a2..0a271a7c 100644
--- a/clangd/index/Index.h
+++ b/clangd/index/Index.h
@@ -1,438 +1,27 @@
//===--- Index.h -------------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CLANGD_INDEX_INDEX_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_INDEX_H
-#include "ExpectedTypes.h"
+#include "Ref.h"
+#include "Symbol.h"
#include "SymbolID.h"
-#include "clang/Index/IndexSymbol.h"
-#include "clang/Lex/Lexer.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/JSON.h"
-#include "llvm/Support/StringSaver.h"
-#include <array>
-#include <limits>
#include <mutex>
#include <string>
-#include <tuple>
-
-namespace clang {
-namespace clangd {
-
-struct SymbolLocation {
- // Specify a position (Line, Column) of symbol. Using Line/Column allows us to
- // build LSP responses without reading the file content.
- //
- // Position is encoded into 32 bits to save space.
- // If Line/Column overflow, the value will be their maximum value.
- struct Position {
- Position() : Line(0), Column(0) {}
- void setLine(uint32_t Line);
- uint32_t line() const { return Line; }
- void setColumn(uint32_t Column);
- uint32_t column() const { return Column; }
-
- bool hasOverflow() const {
- return Line >= MaxLine || Column >= MaxColumn;
- }
-
- static constexpr uint32_t MaxLine = (1 << 20) - 1;
- static constexpr uint32_t MaxColumn = (1 << 12) - 1;
-
- private:
- uint32_t Line : 20; // 0-based
- // Using UTF-16 code units.
- uint32_t Column : 12; // 0-based
- };
-
- /// The symbol range, using half-open range [Start, End).
- Position Start;
- Position End;
- explicit operator bool() const { return !StringRef(FileURI).empty(); }
-
- // The URI of the source file where a symbol occurs.
- // The string must be null-terminated.
- //
- // We avoid using llvm::StringRef here to save memory.
- // WARNING: unless you know what you are doing, it is recommended to use it
- // via llvm::StringRef.
- const char *FileURI = "";
-};
-inline bool operator==(const SymbolLocation::Position &L,
- const SymbolLocation::Position &R) {
- return std::make_tuple(L.line(), L.column()) ==
- std::make_tuple(R.line(), R.column());
-}
-inline bool operator<(const SymbolLocation::Position &L,
- const SymbolLocation::Position &R) {
- return std::make_tuple(L.line(), L.column()) <
- std::make_tuple(R.line(), R.column());
-}
-inline bool operator==(const SymbolLocation &L, const SymbolLocation &R) {
- assert(L.FileURI && R.FileURI);
- return !std::strcmp(L.FileURI, R.FileURI) &&
- std::tie(L.Start, L.End) == std::tie(R.Start, R.End);
-}
-inline bool operator<(const SymbolLocation &L, const SymbolLocation &R) {
- assert(L.FileURI && R.FileURI);
- int Cmp = std::strcmp(L.FileURI, R.FileURI);
- if (Cmp != 0)
- return Cmp < 0;
- return std::tie(L.Start, L.End) < std::tie(R.Start, R.End);
-}
-llvm::raw_ostream &operator<<(llvm::raw_ostream &, const SymbolLocation &);
-
-} // namespace clangd
-} // namespace clang
-namespace llvm {
-// Support SymbolIDs as DenseMap keys.
-template <> struct DenseMapInfo<clang::clangd::SymbolID> {
- static inline clang::clangd::SymbolID getEmptyKey() {
- static clang::clangd::SymbolID EmptyKey("EMPTYKEY");
- return EmptyKey;
- }
- static inline clang::clangd::SymbolID getTombstoneKey() {
- static clang::clangd::SymbolID TombstoneKey("TOMBSTONEKEY");
- return TombstoneKey;
- }
- static unsigned getHashValue(const clang::clangd::SymbolID &Sym) {
- return hash_value(Sym);
- }
- static bool isEqual(const clang::clangd::SymbolID &LHS,
- const clang::clangd::SymbolID &RHS) {
- return LHS == RHS;
- }
-};
-} // namespace llvm
namespace clang {
namespace clangd {
-// Describes the source of information about a symbol.
-// Mainly useful for debugging, e.g. understanding code completion reuslts.
-// This is a bitfield as information can be combined from several sources.
-enum class SymbolOrigin : uint8_t {
- Unknown = 0,
- AST = 1 << 0, // Directly from the AST (indexes should not set this).
- Dynamic = 1 << 1, // From the dynamic index of opened files.
- Static = 1 << 2, // From the static, externally-built index.
- Merge = 1 << 3, // A non-trivial index merge was performed.
- // Remaining bits reserved for index implementations.
-};
-inline SymbolOrigin operator|(SymbolOrigin A, SymbolOrigin B) {
- return static_cast<SymbolOrigin>(static_cast<uint8_t>(A) |
- static_cast<uint8_t>(B));
-}
-inline SymbolOrigin &operator|=(SymbolOrigin &A, SymbolOrigin B) {
- return A = A | B;
-}
-inline SymbolOrigin operator&(SymbolOrigin A, SymbolOrigin B) {
- return static_cast<SymbolOrigin>(static_cast<uint8_t>(A) &
- static_cast<uint8_t>(B));
-}
-raw_ostream &operator<<(raw_ostream &, SymbolOrigin);
-
-// The class presents a C++ symbol, e.g. class, function.
-//
-// WARNING: Symbols do not own much of their underlying data - typically strings
-// are owned by a SymbolSlab. They should be treated as non-owning references.
-// Copies are shallow.
-// When adding new unowned data fields to Symbol, remember to update:
-// - SymbolSlab::Builder in Index.cpp, to copy them to the slab's storage.
-// - mergeSymbol in Merge.cpp, to properly combine two Symbols.
-//
-// A fully documented symbol can be split as:
-// size_type std::map<k, t>::count(const K& key) const
-// | Return | Scope |Name| Signature |
-// We split up these components to allow display flexibility later.
-struct Symbol {
- // The ID of the symbol.
- SymbolID ID;
- // The symbol information, like symbol kind.
- index::SymbolInfo SymInfo;
- // The unqualified name of the symbol, e.g. "bar" (for ns::bar).
- llvm::StringRef Name;
- // The containing namespace. e.g. "" (global), "ns::" (top-level namespace).
- llvm::StringRef Scope;
- // The location of the symbol's definition, if one was found.
- // This just covers the symbol name (e.g. without class/function body).
- SymbolLocation Definition;
- // The location of the preferred declaration of the symbol.
- // This just covers the symbol name.
- // This may be the same as Definition.
- //
- // A C++ symbol may have multiple declarations, and we pick one to prefer.
- // * For classes, the canonical declaration should be the definition.
- // * For non-inline functions, the canonical declaration typically appears
- // in the ".h" file corresponding to the definition.
- SymbolLocation CanonicalDeclaration;
- // The number of translation units that reference this symbol from their main
- // file. This number is only meaningful if aggregated in an index.
- unsigned References = 0;
- /// Where this symbol came from. Usually an index provides a constant value.
- SymbolOrigin Origin = SymbolOrigin::Unknown;
- /// A brief description of the symbol that can be appended in the completion
- /// candidate list. For example, "(X x, Y y) const" is a function signature.
- /// Only set when the symbol is indexed for completion.
- llvm::StringRef Signature;
- /// What to insert when completing this symbol, after the symbol name.
- /// This is in LSP snippet syntax (e.g. "({$0})" for a no-args function).
- /// (When snippets are disabled, the symbol name alone is used).
- /// Only set when the symbol is indexed for completion.
- llvm::StringRef CompletionSnippetSuffix;
- /// Documentation including comment for the symbol declaration.
- llvm::StringRef Documentation;
- /// Type when this symbol is used in an expression. (Short display form).
- /// e.g. return type of a function, or type of a variable.
- /// Only set when the symbol is indexed for completion.
- llvm::StringRef ReturnType;
-
- /// Raw representation of the OpaqueType of the symbol, used for scoring
- /// purposes.
- /// Only set when the symbol is indexed for completion.
- llvm::StringRef Type;
-
- struct IncludeHeaderWithReferences {
- IncludeHeaderWithReferences() = default;
-
- IncludeHeaderWithReferences(llvm::StringRef IncludeHeader,
- unsigned References)
- : IncludeHeader(IncludeHeader), References(References) {}
-
- /// This can be either a URI of the header to be #include'd
- /// for this symbol, or a literal header quoted with <> or "" that is
- /// suitable to be included directly. When it is a URI, the exact #include
- /// path needs to be calculated according to the URI scheme.
- ///
- /// Note that the include header is a canonical include for the symbol and
- /// can be different from FileURI in the CanonicalDeclaration.
- llvm::StringRef IncludeHeader = "";
- /// The number of translation units that reference this symbol and include
- /// this header. This number is only meaningful if aggregated in an index.
- unsigned References = 0;
- };
- /// One Symbol can potentially be incuded via different headers.
- /// - If we haven't seen a definition, this covers all declarations.
- /// - If we have seen a definition, this covers declarations visible from
- /// any definition.
- /// Only set when the symbol is indexed for completion.
- llvm::SmallVector<IncludeHeaderWithReferences, 1> IncludeHeaders;
-
- enum SymbolFlag : uint8_t {
- None = 0,
- /// Whether or not this symbol is meant to be used for the code completion.
- /// See also isIndexedForCodeCompletion().
- /// Note that we don't store completion information (signature, snippet,
- /// type, inclues) if the symbol is not indexed for code completion.
- IndexedForCodeCompletion = 1 << 0,
- /// Indicates if the symbol is deprecated.
- Deprecated = 1 << 1,
- // Symbol is an implementation detail.
- ImplementationDetail = 1 << 2,
- // Symbol is visible to other files (not e.g. a static helper function).
- VisibleOutsideFile = 1 << 3,
- };
-
- SymbolFlag Flags = SymbolFlag::None;
- /// FIXME: also add deprecation message and fixit?
-};
-inline Symbol::SymbolFlag operator|(Symbol::SymbolFlag A, Symbol::SymbolFlag B) {
- return static_cast<Symbol::SymbolFlag>(static_cast<uint8_t>(A) |
- static_cast<uint8_t>(B));
-}
-inline Symbol::SymbolFlag &operator|=(Symbol::SymbolFlag &A, Symbol::SymbolFlag B) {
- return A = A | B;
-}
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S);
-raw_ostream &operator<<(raw_ostream &, Symbol::SymbolFlag);
-
-// Invokes Callback with each StringRef& contained in the Symbol.
-// Useful for deduplicating backing strings.
-template <typename Callback> void visitStrings(Symbol &S, const Callback &CB) {
- CB(S.Name);
- CB(S.Scope);
- CB(S.Signature);
- CB(S.CompletionSnippetSuffix);
- CB(S.Documentation);
- CB(S.ReturnType);
- CB(S.Type);
- auto RawCharPointerCB = [&CB](const char *&P) {
- llvm::StringRef S(P);
- CB(S);
- assert(!S.data()[S.size()] && "Visited StringRef must be null-terminated");
- P = S.data();
- };
- RawCharPointerCB(S.CanonicalDeclaration.FileURI);
- RawCharPointerCB(S.Definition.FileURI);
-
- for (auto &Include : S.IncludeHeaders)
- CB(Include.IncludeHeader);
-}
-
-// Computes query-independent quality score for a Symbol.
-// This currently falls in the range [1, ln(#indexed documents)].
-// FIXME: this should probably be split into symbol -> signals
-// and signals -> score, so it can be reused for Sema completions.
-float quality(const Symbol &S);
-
-// An immutable symbol container that stores a set of symbols.
-// The container will maintain the lifetime of the symbols.
-class SymbolSlab {
-public:
- using const_iterator = std::vector<Symbol>::const_iterator;
- using iterator = const_iterator;
- using value_type = Symbol;
-
- SymbolSlab() = default;
-
- const_iterator begin() const { return Symbols.begin(); }
- const_iterator end() const { return Symbols.end(); }
- const_iterator find(const SymbolID &SymID) const;
-
- size_t size() const { return Symbols.size(); }
- bool empty() const { return Symbols.empty(); }
- // Estimates the total memory usage.
- size_t bytes() const {
- return sizeof(*this) + Arena.getTotalMemory() +
- Symbols.capacity() * sizeof(Symbol);
- }
-
- // SymbolSlab::Builder is a mutable container that can 'freeze' to SymbolSlab.
- // The frozen SymbolSlab will use less memory.
- class Builder {
- public:
- Builder() : UniqueStrings(Arena) {}
-
- // Adds a symbol, overwriting any existing one with the same ID.
- // This is a deep copy: underlying strings will be owned by the slab.
- void insert(const Symbol &S);
-
- // Returns the symbol with an ID, if it exists. Valid until next insert().
- const Symbol *find(const SymbolID &ID) {
- auto I = SymbolIndex.find(ID);
- return I == SymbolIndex.end() ? nullptr : &Symbols[I->second];
- }
-
- // Consumes the builder to finalize the slab.
- SymbolSlab build() &&;
-
- private:
- llvm::BumpPtrAllocator Arena;
- // Intern table for strings. Contents are on the arena.
- llvm::UniqueStringSaver UniqueStrings;
- std::vector<Symbol> Symbols;
- // Values are indices into Symbols vector.
- llvm::DenseMap<SymbolID, size_t> SymbolIndex;
- };
-
-private:
- SymbolSlab(llvm::BumpPtrAllocator Arena, std::vector<Symbol> Symbols)
- : Arena(std::move(Arena)), Symbols(std::move(Symbols)) {}
-
- llvm::BumpPtrAllocator Arena; // Owns Symbol data that the Symbols do not.
- std::vector<Symbol> Symbols; // Sorted by SymbolID to allow lookup.
-};
-
-// Describes the kind of a cross-reference.
-//
-// This is a bitfield which can be combined from different kinds.
-enum class RefKind : uint8_t {
- Unknown = 0,
- Declaration = static_cast<uint8_t>(index::SymbolRole::Declaration),
- Definition = static_cast<uint8_t>(index::SymbolRole::Definition),
- Reference = static_cast<uint8_t>(index::SymbolRole::Reference),
- All = Declaration | Definition | Reference,
-};
-inline RefKind operator|(RefKind L, RefKind R) {
- return static_cast<RefKind>(static_cast<uint8_t>(L) |
- static_cast<uint8_t>(R));
-}
-inline RefKind &operator|=(RefKind &L, RefKind R) { return L = L | R; }
-inline RefKind operator&(RefKind A, RefKind B) {
- return static_cast<RefKind>(static_cast<uint8_t>(A) &
- static_cast<uint8_t>(B));
-}
-llvm::raw_ostream &operator<<(llvm::raw_ostream &, RefKind);
-
-// Represents a symbol occurrence in the source file.
-// Despite the name, it could be a declaration/definition/reference.
-//
-// WARNING: Location does not own the underlying data - Copies are shallow.
-struct Ref {
- // The source location where the symbol is named.
- SymbolLocation Location;
- RefKind Kind = RefKind::Unknown;
-};
-inline bool operator<(const Ref &L, const Ref &R) {
- return std::tie(L.Location, L.Kind) < std::tie(R.Location, R.Kind);
-}
-inline bool operator==(const Ref &L, const Ref &R) {
- return std::tie(L.Location, L.Kind) == std::tie(R.Location, R.Kind);
-}
-llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Ref &);
-
-// An efficient structure of storing large set of symbol references in memory.
-// Filenames are deduplicated.
-class RefSlab {
-public:
- using value_type = std::pair<SymbolID, llvm::ArrayRef<Ref>>;
- using const_iterator = std::vector<value_type>::const_iterator;
- using iterator = const_iterator;
-
- RefSlab() = default;
- RefSlab(RefSlab &&Slab) = default;
- RefSlab &operator=(RefSlab &&RHS) = default;
-
- const_iterator begin() const { return Refs.begin(); }
- const_iterator end() const { return Refs.end(); }
- /// Gets the number of symbols.
- size_t size() const { return Refs.size(); }
- size_t numRefs() const { return NumRefs; }
- bool empty() const { return Refs.empty(); }
-
- size_t bytes() const {
- return sizeof(*this) + Arena.getTotalMemory() +
- sizeof(value_type) * Refs.size();
- }
-
- // RefSlab::Builder is a mutable container that can 'freeze' to RefSlab.
- class Builder {
- public:
- Builder() : UniqueStrings(Arena) {}
- // Adds a ref to the slab. Deep copy: Strings will be owned by the slab.
- void insert(const SymbolID &ID, const Ref &S);
- // Consumes the builder to finalize the slab.
- RefSlab build() &&;
-
- private:
- llvm::BumpPtrAllocator Arena;
- llvm::UniqueStringSaver UniqueStrings; // Contents on the arena.
- llvm::DenseMap<SymbolID, std::vector<Ref>> Refs;
- };
-
-private:
- RefSlab(std::vector<value_type> Refs, llvm::BumpPtrAllocator Arena,
- size_t NumRefs)
- : Arena(std::move(Arena)), Refs(std::move(Refs)), NumRefs(NumRefs) {}
-
- llvm::BumpPtrAllocator Arena;
- std::vector<value_type> Refs;
- // Number of all references.
- size_t NumRefs = 0;
-};
-
struct FuzzyFindRequest {
/// \brief A query string for the fuzzy find. This is matched against symbols'
/// un-qualified identifiers and should not contain qualifiers like "::".
@@ -455,14 +44,15 @@ struct FuzzyFindRequest {
/// Contextually relevant files (e.g. the file we're code-completing in).
/// Paths should be absolute.
std::vector<std::string> ProximityPaths;
-
- // FIXME(ibiryukov): add expected type to the request.
+ /// Preferred types of symbols. These are raw representation of `OpaqueType`.
+ std::vector<std::string> PreferredTypes;
bool operator==(const FuzzyFindRequest &Req) const {
return std::tie(Query, Scopes, Limit, RestrictForCodeCompletion,
- ProximityPaths) ==
+ ProximityPaths, PreferredTypes) ==
std::tie(Req.Query, Req.Scopes, Req.Limit,
- Req.RestrictForCodeCompletion, Req.ProximityPaths);
+ Req.RestrictForCodeCompletion, Req.ProximityPaths,
+ Req.PreferredTypes);
}
bool operator!=(const FuzzyFindRequest &Req) const { return !(*this == Req); }
};
@@ -513,9 +103,6 @@ public:
llvm::function_ref<void(const Ref &)> Callback) const = 0;
/// Returns estimated size of index (in bytes).
- // FIXME(kbobyrev): Currently, this only returns the size of index itself
- // excluding the size of actual symbol slab index refers to. We should include
- // both.
virtual size_t estimateMemoryUsage() const = 0;
};
diff --git a/clangd/index/IndexAction.cpp b/clangd/index/IndexAction.cpp
index a6df64b7..120f6b0b 100644
--- a/clangd/index/IndexAction.cpp
+++ b/clangd/index/IndexAction.cpp
@@ -1,6 +1,14 @@
+//===--- IndexAction.cpp -----------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
#include "IndexAction.h"
+#include "index/SymbolOrigin.h"
#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Index/IndexDataConsumer.h"
#include "clang/Index/IndexingAction.h"
#include "clang/Tooling/Tooling.h"
@@ -127,6 +135,11 @@ public:
bool BeginInvocation(CompilerInstance &CI) override {
// We want all comments, not just the doxygen ones.
CI.getLangOpts().CommentOpts.ParseAllComments = true;
+ // Index the whole file even if there are warnings and -Werror is set.
+ // Avoids some analyses too. Set in two places as we're late to the party.
+ CI.getDiagnosticOpts().IgnoreWarnings = true;
+ CI.getDiagnostics().setIgnoreAllWarnings(true);
+
return WrapperFrontendAction::BeginInvocation(CI);
}
@@ -174,7 +187,9 @@ std::unique_ptr<FrontendAction> createStaticIndexingAction(
index::IndexingOptions::SystemSymbolFilterKind::All;
Opts.CollectIncludePath = true;
Opts.CountReferences = true;
- Opts.Origin = SymbolOrigin::Static;
+ if (Opts.Origin == SymbolOrigin::Unknown)
+ Opts.Origin = SymbolOrigin::Static;
+ Opts.StoreAllDocumentation = false;
if (RefsCallback != nullptr) {
Opts.RefFilter = RefKind::All;
Opts.RefsInHeaders = true;
diff --git a/clangd/index/IndexAction.h b/clangd/index/IndexAction.h
index f2c5298f..f2b45deb 100644
--- a/clangd/index/IndexAction.h
+++ b/clangd/index/IndexAction.h
@@ -1,9 +1,8 @@
//===--- IndexAction.h - Run the indexer as a frontend action ----*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -23,7 +22,7 @@ namespace clangd {
// - include paths are always collected, and canonicalized appropriately
// - references are always counted
// - all references are collected (if RefsCallback is non-null)
-// - the symbol origin is always Static
+// - the symbol origin is set to Static if not specified by caller
std::unique_ptr<FrontendAction> createStaticIndexingAction(
SymbolCollector::Options Opts,
std::function<void(SymbolSlab)> SymbolsCallback,
diff --git a/clangd/index/MemIndex.cpp b/clangd/index/MemIndex.cpp
index e4dc56c5..582091f0 100644
--- a/clangd/index/MemIndex.cpp
+++ b/clangd/index/MemIndex.cpp
@@ -1,9 +1,8 @@
//===--- MemIndex.cpp - Dynamic in-memory symbol index. ----------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===-------------------------------------------------------------------===//
@@ -12,6 +11,7 @@
#include "Logger.h"
#include "Quality.h"
#include "Trace.h"
+#include "clang/Index/IndexSymbol.h"
namespace clang {
namespace clangd {
diff --git a/clangd/index/MemIndex.h b/clangd/index/MemIndex.h
index 24f2ba19..47227fd7 100644
--- a/clangd/index/MemIndex.h
+++ b/clangd/index/MemIndex.h
@@ -1,9 +1,8 @@
//===--- MemIndex.h - Dynamic in-memory symbol index. -------------- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/index/Merge.cpp b/clangd/index/Merge.cpp
index 52f54e39..a5945a7d 100644
--- a/clangd/index/Merge.cpp
+++ b/clangd/index/Merge.cpp
@@ -1,18 +1,23 @@
//===--- Merge.cpp -----------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "Merge.h"
#include "Logger.h"
#include "Trace.h"
+#include "index/Symbol.h"
+#include "index/SymbolLocation.h"
+#include "index/SymbolOrigin.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <iterator>
namespace clang {
namespace clangd {
@@ -103,7 +108,6 @@ void MergedIndex::refs(const RefsRequest &Req,
Callback(O);
--Remaining;
});
- assert(Remaining >= 0);
if (Remaining == 0)
return;
// We return less than Req.Limit if static index returns more refs for dirty
@@ -116,6 +120,23 @@ void MergedIndex::refs(const RefsRequest &Req,
});
}
+// Returns true if \p L is (strictly) preferred to \p R (e.g. by file paths). If
+// neither is preferred, this returns false.
+bool prefer(const SymbolLocation &L, const SymbolLocation &R) {
+ if (!L)
+ return false;
+ if (!R)
+ return true;
+ auto HasCodeGenSuffix = [](const SymbolLocation &Loc) {
+ constexpr static const char *CodegenSuffixes[] = {".proto"};
+ return std::any_of(std::begin(CodegenSuffixes), std::end(CodegenSuffixes),
+ [&](llvm::StringRef Suffix) {
+ return llvm::StringRef(Loc.FileURI).endswith(Suffix);
+ });
+ };
+ return HasCodeGenSuffix(L) && !HasCodeGenSuffix(R);
+}
+
Symbol mergeSymbol(const Symbol &L, const Symbol &R) {
assert(L.ID == R.ID);
// We prefer information from TUs that saw the definition.
@@ -130,12 +151,11 @@ Symbol mergeSymbol(const Symbol &L, const Symbol &R) {
Symbol S = PreferR ? R : L; // The target symbol we're merging into.
const Symbol &O = PreferR ? L : R; // The "other" less-preferred symbol.
- // For each optional field, fill it from O if missing in S.
- // (It might be missing in O too, but that's a no-op).
- if (!S.Definition)
- S.Definition = O.Definition;
- if (!S.CanonicalDeclaration)
+ // Only use locations in \p O if it's (strictly) preferred.
+ if (prefer(O.CanonicalDeclaration, S.CanonicalDeclaration))
S.CanonicalDeclaration = O.CanonicalDeclaration;
+ if (prefer(O.Definition, S.Definition))
+ S.Definition = O.Definition;
S.References += O.References;
if (S.Signature == "")
S.Signature = O.Signature;
diff --git a/clangd/index/Merge.h b/clangd/index/Merge.h
index 7569c7a4..5954b6bc 100644
--- a/clangd/index/Merge.h
+++ b/clangd/index/Merge.h
@@ -1,9 +1,8 @@
//===--- Merge.h -------------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/index/Ref.cpp b/clangd/index/Ref.cpp
new file mode 100644
index 00000000..2b21f3cb
--- /dev/null
+++ b/clangd/index/Ref.cpp
@@ -0,0 +1,59 @@
+//===--- Ref.cpp -------------------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Ref.h"
+
+namespace clang {
+namespace clangd {
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, RefKind K) {
+ if (K == RefKind::Unknown)
+ return OS << "Unknown";
+ static const std::vector<const char *> Messages = {"Decl", "Def", "Ref"};
+ bool VisitedOnce = false;
+ for (unsigned I = 0; I < Messages.size(); ++I) {
+ if (static_cast<uint8_t>(K) & 1u << I) {
+ if (VisitedOnce)
+ OS << ", ";
+ OS << Messages[I];
+ VisitedOnce = true;
+ }
+ }
+ return OS;
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Ref &R) {
+ return OS << R.Location << ":" << R.Kind;
+}
+
+void RefSlab::Builder::insert(const SymbolID &ID, const Ref &S) {
+ auto &M = Refs[ID];
+ if (M.count(S))
+ return;
+ Ref R = S;
+ R.Location.FileURI =
+ UniqueStrings.save(R.Location.FileURI).data();
+ M.insert(std::move(R));
+}
+
+RefSlab RefSlab::Builder::build() && {
+ // We can reuse the arena, as it only has unique strings and we need them all.
+ // Reallocate refs on the arena to reduce waste and indirections when reading.
+ std::vector<std::pair<SymbolID, llvm::ArrayRef<Ref>>> Result;
+ Result.reserve(Refs.size());
+ size_t NumRefs = 0;
+ for (auto &Sym : Refs) {
+ std::vector<Ref> SymRefs(Sym.second.begin(), Sym.second.end());
+ NumRefs += SymRefs.size();
+ Result.emplace_back(Sym.first, llvm::ArrayRef<Ref>(SymRefs).copy(Arena));
+ }
+ return RefSlab(std::move(Result), std::move(Arena), NumRefs);
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/clangd/index/Ref.h b/clangd/index/Ref.h
new file mode 100644
index 00000000..4d6ae169
--- /dev/null
+++ b/clangd/index/Ref.h
@@ -0,0 +1,121 @@
+//===--- Ref.h ---------------------------------------------------*- 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_CLANGD_INDEX_REF_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REF_H
+
+#include "SymbolID.h"
+#include "SymbolLocation.h"
+#include "clang/Index/IndexSymbol.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+#include <set>
+#include <utility>
+
+namespace clang {
+namespace clangd {
+
+/// Describes the kind of a cross-reference.
+///
+/// This is a bitfield which can be combined from different kinds.
+enum class RefKind : uint8_t {
+ Unknown = 0,
+ Declaration = static_cast<uint8_t>(index::SymbolRole::Declaration),
+ Definition = static_cast<uint8_t>(index::SymbolRole::Definition),
+ Reference = static_cast<uint8_t>(index::SymbolRole::Reference),
+ All = Declaration | Definition | Reference,
+};
+
+inline RefKind operator|(RefKind L, RefKind R) {
+ return static_cast<RefKind>(static_cast<uint8_t>(L) |
+ static_cast<uint8_t>(R));
+}
+inline RefKind &operator|=(RefKind &L, RefKind R) { return L = L | R; }
+inline RefKind operator&(RefKind A, RefKind B) {
+ return static_cast<RefKind>(static_cast<uint8_t>(A) &
+ static_cast<uint8_t>(B));
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, RefKind);
+
+/// Represents a symbol occurrence in the source file.
+/// Despite the name, it could be a declaration/definition/reference.
+///
+/// WARNING: Location does not own the underlying data - Copies are shallow.
+struct Ref {
+ /// The source location where the symbol is named.
+ SymbolLocation Location;
+ RefKind Kind = RefKind::Unknown;
+};
+
+inline bool operator<(const Ref &L, const Ref &R) {
+ return std::tie(L.Location, L.Kind) < std::tie(R.Location, R.Kind);
+}
+inline bool operator==(const Ref &L, const Ref &R) {
+ return std::tie(L.Location, L.Kind) == std::tie(R.Location, R.Kind);
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Ref &);
+
+/// An efficient structure of storing large set of symbol references in memory.
+/// Filenames are deduplicated.
+class RefSlab {
+public:
+ // Refs are stored in order.
+ using value_type = std::pair<SymbolID, llvm::ArrayRef<Ref>>;
+ using const_iterator = std::vector<value_type>::const_iterator;
+ using iterator = const_iterator;
+
+ RefSlab() = default;
+ RefSlab(RefSlab &&Slab) = default;
+ RefSlab &operator=(RefSlab &&RHS) = default;
+
+ const_iterator begin() const { return Refs.begin(); }
+ const_iterator end() const { return Refs.end(); }
+ /// Gets the number of symbols.
+ size_t size() const { return Refs.size(); }
+ size_t numRefs() const { return NumRefs; }
+ bool empty() const { return Refs.empty(); }
+
+ size_t bytes() const {
+ return sizeof(*this) + Arena.getTotalMemory() +
+ sizeof(value_type) * Refs.capacity();
+ }
+
+ /// RefSlab::Builder is a mutable container that can 'freeze' to RefSlab.
+ class Builder {
+ public:
+ Builder() : UniqueStrings(Arena) {}
+ /// Adds a ref to the slab. Deep copy: Strings will be owned by the slab.
+ void insert(const SymbolID &ID, const Ref &S);
+ /// Consumes the builder to finalize the slab.
+ RefSlab build() &&;
+
+ private:
+ llvm::BumpPtrAllocator Arena;
+ llvm::UniqueStringSaver UniqueStrings; // Contents on the arena.
+ llvm::DenseMap<SymbolID, std::set<Ref>> Refs;
+ };
+
+private:
+ RefSlab(std::vector<value_type> Refs, llvm::BumpPtrAllocator Arena,
+ size_t NumRefs)
+ : Arena(std::move(Arena)), Refs(std::move(Refs)), NumRefs(NumRefs) {}
+
+ llvm::BumpPtrAllocator Arena;
+ std::vector<value_type> Refs;
+ /// Number of all references.
+ size_t NumRefs = 0;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REF_H
diff --git a/clangd/index/Serialization.cpp b/clangd/index/Serialization.cpp
index a4f99b1c..62eb3fcd 100644
--- a/clangd/index/Serialization.cpp
+++ b/clangd/index/Serialization.cpp
@@ -1,16 +1,16 @@
//===-- Serialization.cpp - Binary serialization of index data ------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "Serialization.h"
-#include "Index.h"
#include "Logger.h"
#include "RIFF.h"
+#include "SymbolLocation.h"
+#include "SymbolOrigin.h"
#include "Trace.h"
#include "dex/Dex.h"
#include "llvm/Support/Compression.h"
@@ -106,9 +106,9 @@ public:
};
void write32(uint32_t I, llvm::raw_ostream &OS) {
- char buf[4];
- llvm::support::endian::write32le(buf, I);
- OS.write(buf, sizeof(buf));
+ char Buf[4];
+ llvm::support::endian::write32le(Buf, I);
+ OS.write(Buf, sizeof(Buf));
}
void writeVar(uint32_t I, llvm::raw_ostream &OS) {
@@ -282,6 +282,7 @@ void writeSymbol(const Symbol &Sym, const StringTableOut &Strings,
OS.write(static_cast<uint8_t>(Sym.SymInfo.Lang));
writeVar(Strings.index(Sym.Name), OS);
writeVar(Strings.index(Sym.Scope), OS);
+ writeVar(Strings.index(Sym.TemplateSpecializationArgs), OS);
writeLocation(Sym.Definition, Strings, OS);
writeLocation(Sym.CanonicalDeclaration, Strings, OS);
writeVar(Sym.References, OS);
@@ -309,11 +310,12 @@ Symbol readSymbol(Reader &Data, llvm::ArrayRef<llvm::StringRef> Strings) {
Sym.SymInfo.Lang = static_cast<index::SymbolLanguage>(Data.consume8());
Sym.Name = Data.consumeString(Strings);
Sym.Scope = Data.consumeString(Strings);
+ Sym.TemplateSpecializationArgs = Data.consumeString(Strings);
Sym.Definition = readLocation(Data, Strings);
Sym.CanonicalDeclaration = readLocation(Data, Strings);
Sym.References = Data.consumeVar();
- Sym.Flags = static_cast<Symbol::SymbolFlag>(Data.consumeVar());
- Sym.Origin = static_cast<SymbolOrigin>(Data.consumeVar());
+ Sym.Flags = static_cast<Symbol::SymbolFlag>(Data.consume8());
+ Sym.Origin = static_cast<SymbolOrigin>(Data.consume8());
Sym.Signature = Data.consumeString(Strings);
Sym.CompletionSnippetSuffix = Data.consumeString(Strings);
Sym.Documentation = Data.consumeString(Strings);
@@ -368,7 +370,7 @@ readRefs(Reader &Data, llvm::ArrayRef<llvm::StringRef> Strings) {
// The current versioning scheme is simple - non-current versions are rejected.
// If you make a breaking change, bump this version number to invalidate stored
// data. Later we may want to support some backward compatibility.
-constexpr static uint32_t Version = 8;
+constexpr static uint32_t Version = 9;
llvm::Expected<IndexFileIn> readRIFF(llvm::StringRef Data) {
auto RIFF = riff::readFile(Data);
diff --git a/clangd/index/Serialization.h b/clangd/index/Serialization.h
index c403b957..3788693e 100644
--- a/clangd/index/Serialization.h
+++ b/clangd/index/Serialization.h
@@ -1,9 +1,8 @@
//===--- Serialization.h - Binary serialization of index data ----*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -24,8 +23,10 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_RIFF_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_RIFF_H
+
#include "Headers.h"
#include "Index.h"
+#include "index/Symbol.h"
#include "llvm/Support/Error.h"
namespace clang {
diff --git a/clangd/index/Symbol.cpp b/clangd/index/Symbol.cpp
new file mode 100644
index 00000000..137f90df
--- /dev/null
+++ b/clangd/index/Symbol.cpp
@@ -0,0 +1,71 @@
+//===--- Symbol.cpp ----------------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Symbol.h"
+
+namespace clang {
+namespace clangd {
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Symbol::SymbolFlag F) {
+ if (F == Symbol::None)
+ return OS << "None";
+ std::string S;
+ if (F & Symbol::Deprecated)
+ S += "deprecated|";
+ if (F & Symbol::IndexedForCodeCompletion)
+ S += "completion|";
+ return OS << llvm::StringRef(S).rtrim('|');
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S) {
+ return OS << S.Scope << S.Name;
+}
+
+float quality(const Symbol &S) {
+ // This avoids a sharp gradient for tail symbols, and also neatly avoids the
+ // question of whether 0 references means a bad symbol or missing data.
+ if (S.References < 3)
+ return 1;
+ return std::log(S.References);
+}
+
+SymbolSlab::const_iterator SymbolSlab::find(const SymbolID &ID) const {
+ auto It =
+ llvm::bsearch(Symbols, [&](const Symbol &S) { return !(S.ID < ID); });
+ if (It != Symbols.end() && It->ID == ID)
+ return It;
+ return Symbols.end();
+}
+
+// Copy the underlying data of the symbol into the owned arena.
+static void own(Symbol &S, llvm::UniqueStringSaver &Strings) {
+ visitStrings(S, [&](llvm::StringRef &V) { V = Strings.save(V); });
+}
+
+void SymbolSlab::Builder::insert(const Symbol &S) {
+ own(Symbols[S.ID] = S, UniqueStrings);
+}
+
+SymbolSlab SymbolSlab::Builder::build() && {
+ // Sort symbols into vector so the slab can binary search over them.
+ std::vector<Symbol> SortedSymbols;
+ SortedSymbols.reserve(Symbols.size());
+ for (auto &Entry : Symbols)
+ SortedSymbols.push_back(std::move(Entry.second));
+ llvm::sort(SortedSymbols,
+ [](const Symbol &L, const Symbol &R) { return L.ID < R.ID; });
+ // We may have unused strings from overwritten symbols. Build a new arena.
+ llvm::BumpPtrAllocator NewArena;
+ llvm::UniqueStringSaver Strings(NewArena);
+ for (auto &S : SortedSymbols)
+ own(S, Strings);
+ return SymbolSlab(std::move(NewArena), std::move(SortedSymbols));
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/clangd/index/Symbol.h b/clangd/index/Symbol.h
new file mode 100644
index 00000000..65ca8269
--- /dev/null
+++ b/clangd/index/Symbol.h
@@ -0,0 +1,238 @@
+//===--- Symbol.h ------------------------------------------------*- 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_CLANGD_INDEX_SYMBOL_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_H
+
+#include "SymbolID.h"
+#include "SymbolLocation.h"
+#include "SymbolOrigin.h"
+#include "clang/Index/IndexSymbol.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/StringSaver.h"
+
+namespace clang {
+namespace clangd {
+
+/// The class presents a C++ symbol, e.g. class, function.
+///
+/// WARNING: Symbols do not own much of their underlying data - typically
+/// strings are owned by a SymbolSlab. They should be treated as non-owning
+/// references. Copies are shallow.
+///
+/// When adding new unowned data fields to Symbol, remember to update:
+/// - SymbolSlab::Builder in Index.cpp, to copy them to the slab's storage.
+/// - mergeSymbol in Merge.cpp, to properly combine two Symbols.
+///
+/// A fully documented symbol can be split as:
+/// size_type std::map<k, t>::count(const K& key) const
+/// | Return | Scope |Name| Signature |
+/// We split up these components to allow display flexibility later.
+struct Symbol {
+ /// The ID of the symbol.
+ SymbolID ID;
+ /// The symbol information, like symbol kind.
+ index::SymbolInfo SymInfo = index::SymbolInfo();
+ /// The unqualified name of the symbol, e.g. "bar" (for ns::bar).
+ llvm::StringRef Name;
+ /// The containing namespace. e.g. "" (global), "ns::" (top-level namespace).
+ llvm::StringRef Scope;
+ /// The location of the symbol's definition, if one was found.
+ /// This just covers the symbol name (e.g. without class/function body).
+ SymbolLocation Definition;
+ /// The location of the preferred declaration of the symbol.
+ /// This just covers the symbol name.
+ /// This may be the same as Definition.
+ ///
+ /// A C++ symbol may have multiple declarations, and we pick one to prefer.
+ /// * For classes, the canonical declaration should be the definition.
+ /// * For non-inline functions, the canonical declaration typically appears
+ /// in the ".h" file corresponding to the definition.
+ SymbolLocation CanonicalDeclaration;
+ /// The number of translation units that reference this symbol from their main
+ /// file. This number is only meaningful if aggregated in an index.
+ unsigned References = 0;
+ /// Where this symbol came from. Usually an index provides a constant value.
+ SymbolOrigin Origin = SymbolOrigin::Unknown;
+ /// A brief description of the symbol that can be appended in the completion
+ /// candidate list. For example, "(X x, Y y) const" is a function signature.
+ /// Only set when the symbol is indexed for completion.
+ llvm::StringRef Signature;
+ /// Argument list in human-readable format, will be displayed to help
+ /// disambiguate between different specializations of a template. Empty for
+ /// non-specializations. Example: "<int, bool, 3>"
+ llvm::StringRef TemplateSpecializationArgs;
+ /// What to insert when completing this symbol, after the symbol name.
+ /// This is in LSP snippet syntax (e.g. "({$0})" for a no-args function).
+ /// (When snippets are disabled, the symbol name alone is used).
+ /// Only set when the symbol is indexed for completion.
+ llvm::StringRef CompletionSnippetSuffix;
+ /// Documentation including comment for the symbol declaration.
+ llvm::StringRef Documentation;
+ /// Type when this symbol is used in an expression. (Short display form).
+ /// e.g. return type of a function, or type of a variable.
+ /// Only set when the symbol is indexed for completion.
+ llvm::StringRef ReturnType;
+
+ /// Raw representation of the OpaqueType of the symbol, used for scoring
+ /// purposes.
+ /// Only set when the symbol is indexed for completion.
+ llvm::StringRef Type;
+
+ struct IncludeHeaderWithReferences {
+ IncludeHeaderWithReferences() = default;
+
+ IncludeHeaderWithReferences(llvm::StringRef IncludeHeader,
+ unsigned References)
+ : IncludeHeader(IncludeHeader), References(References) {}
+
+ /// This can be either a URI of the header to be #include'd
+ /// for this symbol, or a literal header quoted with <> or "" that is
+ /// suitable to be included directly. When it is a URI, the exact #include
+ /// path needs to be calculated according to the URI scheme.
+ ///
+ /// Note that the include header is a canonical include for the symbol and
+ /// can be different from FileURI in the CanonicalDeclaration.
+ llvm::StringRef IncludeHeader = "";
+ /// The number of translation units that reference this symbol and include
+ /// this header. This number is only meaningful if aggregated in an index.
+ unsigned References = 0;
+ };
+ /// One Symbol can potentially be incuded via different headers.
+ /// - If we haven't seen a definition, this covers all declarations.
+ /// - If we have seen a definition, this covers declarations visible from
+ /// any definition.
+ /// Only set when the symbol is indexed for completion.
+ llvm::SmallVector<IncludeHeaderWithReferences, 1> IncludeHeaders;
+
+ enum SymbolFlag : uint8_t {
+ None = 0,
+ /// Whether or not this symbol is meant to be used for the code completion.
+ /// See also isIndexedForCodeCompletion().
+ /// Note that we don't store completion information (signature, snippet,
+ /// type, inclues) if the symbol is not indexed for code completion.
+ IndexedForCodeCompletion = 1 << 0,
+ /// Indicates if the symbol is deprecated.
+ Deprecated = 1 << 1,
+ /// Symbol is an implementation detail.
+ ImplementationDetail = 1 << 2,
+ /// Symbol is visible to other files (not e.g. a static helper function).
+ VisibleOutsideFile = 1 << 3,
+ };
+
+ SymbolFlag Flags = SymbolFlag::None;
+ /// FIXME: also add deprecation message and fixit?
+};
+
+inline Symbol::SymbolFlag operator|(Symbol::SymbolFlag A,
+ Symbol::SymbolFlag B) {
+ return static_cast<Symbol::SymbolFlag>(static_cast<uint8_t>(A) |
+ static_cast<uint8_t>(B));
+}
+inline Symbol::SymbolFlag &operator|=(Symbol::SymbolFlag &A,
+ Symbol::SymbolFlag B) {
+ return A = A | B;
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Symbol::SymbolFlag);
+
+/// Invokes Callback with each StringRef& contained in the Symbol.
+/// Useful for deduplicating backing strings.
+template <typename Callback> void visitStrings(Symbol &S, const Callback &CB) {
+ CB(S.Name);
+ CB(S.Scope);
+ CB(S.TemplateSpecializationArgs);
+ CB(S.Signature);
+ CB(S.CompletionSnippetSuffix);
+ CB(S.Documentation);
+ CB(S.ReturnType);
+ CB(S.Type);
+ auto RawCharPointerCB = [&CB](const char *&P) {
+ llvm::StringRef S(P);
+ CB(S);
+ assert(!S.data()[S.size()] && "Visited StringRef must be null-terminated");
+ P = S.data();
+ };
+ RawCharPointerCB(S.CanonicalDeclaration.FileURI);
+ RawCharPointerCB(S.Definition.FileURI);
+
+ for (auto &Include : S.IncludeHeaders)
+ CB(Include.IncludeHeader);
+}
+
+/// Computes query-independent quality score for a Symbol.
+/// This currently falls in the range [1, ln(#indexed documents)].
+/// FIXME: this should probably be split into symbol -> signals
+/// and signals -> score, so it can be reused for Sema completions.
+float quality(const Symbol &S);
+
+/// An immutable symbol container that stores a set of symbols.
+/// The container will maintain the lifetime of the symbols.
+class SymbolSlab {
+public:
+ using const_iterator = std::vector<Symbol>::const_iterator;
+ using iterator = const_iterator;
+ using value_type = Symbol;
+
+ SymbolSlab() = default;
+
+ const_iterator begin() const { return Symbols.begin(); }
+ const_iterator end() const { return Symbols.end(); }
+ const_iterator find(const SymbolID &SymID) const;
+
+ size_t size() const { return Symbols.size(); }
+ bool empty() const { return Symbols.empty(); }
+ // Estimates the total memory usage.
+ size_t bytes() const {
+ return sizeof(*this) + Arena.getTotalMemory() +
+ Symbols.capacity() * sizeof(Symbol);
+ }
+
+ /// SymbolSlab::Builder is a mutable container that can 'freeze' to
+ /// SymbolSlab. The frozen SymbolSlab will use less memory.
+ class Builder {
+ public:
+ Builder() : UniqueStrings(Arena) {}
+
+ /// Adds a symbol, overwriting any existing one with the same ID.
+ /// This is a deep copy: underlying strings will be owned by the slab.
+ void insert(const Symbol &S);
+
+ /// Removes the symbol with an ID, if it exists.
+ void erase(const SymbolID &ID) { Symbols.erase(ID); }
+
+ /// Returns the symbol with an ID, if it exists. Valid until insert/remove.
+ const Symbol *find(const SymbolID &ID) {
+ auto I = Symbols.find(ID);
+ return I == Symbols.end() ? nullptr : &I->second;
+ }
+
+ /// Consumes the builder to finalize the slab.
+ SymbolSlab build() &&;
+
+ private:
+ llvm::BumpPtrAllocator Arena;
+ /// Intern table for strings. Contents are on the arena.
+ llvm::UniqueStringSaver UniqueStrings;
+ /// Values are indices into Symbols vector.
+ llvm::DenseMap<SymbolID, Symbol> Symbols;
+ };
+
+private:
+ SymbolSlab(llvm::BumpPtrAllocator Arena, std::vector<Symbol> Symbols)
+ : Arena(std::move(Arena)), Symbols(std::move(Symbols)) {}
+
+ llvm::BumpPtrAllocator Arena; // Owns Symbol data that the Symbols do not.
+ std::vector<Symbol> Symbols; // Sorted by SymbolID to allow lookup.
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_H
diff --git a/clangd/index/SymbolCollector.cpp b/clangd/index/SymbolCollector.cpp
index d3ce7712..af1938da 100644
--- a/clangd/index/SymbolCollector.cpp
+++ b/clangd/index/SymbolCollector.cpp
@@ -1,9 +1,8 @@
//===--- SymbolCollector.cpp -------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -12,8 +11,10 @@
#include "CanonicalIncludes.h"
#include "CodeComplete.h"
#include "CodeCompletionStrings.h"
+#include "ExpectedTypes.h"
#include "Logger.h"
#include "SourceCode.h"
+#include "SymbolLocation.h"
#include "URI.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
@@ -23,7 +24,9 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Index/IndexSymbol.h"
+#include "clang/Index/IndexingAction.h"
#include "clang/Index/USRGeneration.h"
+#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -126,36 +129,6 @@ bool shouldCollectIncludePath(index::SymbolKind Kind) {
}
}
-/// Gets a canonical include (URI of the header or <header> or "header") for
-/// header of \p Loc.
-/// Returns None if fails to get include header for \p Loc.
-llvm::Optional<std::string>
-getIncludeHeader(llvm::StringRef QName, const SourceManager &SM,
- SourceLocation Loc, const SymbolCollector::Options &Opts) {
- std::vector<std::string> Headers;
- // Collect the #include stack.
- while (true) {
- if (!Loc.isValid())
- break;
- auto FilePath = SM.getFilename(Loc);
- if (FilePath.empty())
- break;
- Headers.push_back(FilePath);
- if (SM.isInMainFile(Loc))
- break;
- Loc = SM.getIncludeLoc(SM.getFileID(Loc));
- }
- if (Headers.empty())
- return None;
- llvm::StringRef Header = Headers[0];
- if (Opts.Includes) {
- Header = Opts.Includes->mapHeader(Headers, QName);
- if (Header.startswith("<") || Header.startswith("\""))
- return Header.str();
- }
- return toURI(SM, Header, Opts);
-}
-
// Return the symbol range of the token at \p TokLoc.
std::pair<SymbolLocation::Position, SymbolLocation::Position>
getTokenRange(SourceLocation TokLoc, const SourceManager &SM,
@@ -210,7 +183,7 @@ getTokenLocation(SourceLocation TokLoc, const SourceManager &SM,
// the first seen declaration as canonical declaration is not a good enough
// heuristic.
bool isPreferredDeclaration(const NamedDecl &ND, index::SymbolRoleSet Roles) {
- const auto& SM = ND.getASTContext().getSourceManager();
+ const auto &SM = ND.getASTContext().getSourceManager();
return (Roles & static_cast<unsigned>(index::SymbolRole::Definition)) &&
isa<TagDecl>(&ND) &&
!SM.isWrittenInMainFile(SM.getExpansionLoc(ND.getLocation()));
@@ -220,13 +193,6 @@ RefKind toRefKind(index::SymbolRoleSet Roles) {
return static_cast<RefKind>(static_cast<unsigned>(RefKind::All) & Roles);
}
-template <class T> bool explicitTemplateSpecialization(const NamedDecl &ND) {
- if (const auto *TD = dyn_cast<T>(&ND))
- if (TD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
- return true;
- return false;
-}
-
} // namespace
SymbolCollector::SymbolCollector(Options Opts) : Opts(std::move(Opts)) {}
@@ -242,8 +208,6 @@ bool SymbolCollector::shouldCollectSymbol(const NamedDecl &ND,
const ASTContext &ASTCtx,
const Options &Opts,
bool IsMainFileOnly) {
- if (ND.isImplicit())
- return false;
// Skip anonymous declarations, e.g (anonymous enum/class/struct).
if (ND.getDeclName().isEmpty())
return false;
@@ -278,10 +242,6 @@ bool SymbolCollector::shouldCollectSymbol(const NamedDecl &ND,
if (!isa<RecordDecl>(DeclCtx))
return false;
}
- if (explicitTemplateSpecialization<FunctionDecl>(ND) ||
- explicitTemplateSpecialization<CXXRecordDecl>(ND) ||
- explicitTemplateSpecialization<VarDecl>(ND))
- return false;
// Avoid indexing internal symbols in protobuf generated headers.
if (isPrivateProtoDecl(ND))
@@ -297,6 +257,11 @@ bool SymbolCollector::handleDeclOccurence(
assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set.");
assert(CompletionAllocator && CompletionTUInfo);
assert(ASTNode.OrigD);
+ // Indexing API puts cannonical decl into D, which might not have a valid
+ // source location for implicit/built-in decls. Fallback to original decl in
+ // such cases.
+ if (D->getLocation().isInvalid())
+ D = ASTNode.OrigD;
// If OrigD is an declaration associated with a friend declaration and it's
// not a definition, skip it. Note that OrigD is the occurrence that the
// collector is currently visiting.
@@ -304,6 +269,10 @@ bool SymbolCollector::handleDeclOccurence(
Decl::FriendObjectKind::FOK_None) &&
!(Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
return true;
+ // Skip non-semantic references, we should start processing these when we
+ // decide to implement renaming with index support.
+ if ((Roles & static_cast<unsigned>(index::SymbolRole::NameReference)))
+ return true;
// A declaration created for a friend declaration should not be used as the
// canonical declaration in the index. Use OrigD instead, unless we've already
// picked a replacement for D
@@ -332,9 +301,11 @@ bool SymbolCollector::handleDeclOccurence(
// ND is the canonical (i.e. first) declaration. If it's in the main file,
// then no public declaration was visible, so assume it's main-file only.
- bool IsMainFileOnly = SM.isWrittenInMainFile(SM.getExpansionLoc(
- ND->getBeginLoc()));
- if (!shouldCollectSymbol(*ND, *ASTCtx, Opts, IsMainFileOnly))
+ bool IsMainFileOnly =
+ SM.isWrittenInMainFile(SM.getExpansionLoc(ND->getBeginLoc()));
+ // In C, printf is a redecl of an implicit builtin! So check OrigD instead.
+ if (ASTNode.OrigD->isImplicit() ||
+ !shouldCollectSymbol(*ND, *ASTCtx, Opts, IsMainFileOnly))
return true;
// Do not store references to main-file symbols.
if (CollectRef && !IsMainFileOnly && !isa<NamespaceDecl>(ND) &&
@@ -348,19 +319,25 @@ bool SymbolCollector::handleDeclOccurence(
if (!ID)
return true;
- const NamedDecl &OriginalDecl = *cast<NamedDecl>(ASTNode.OrigD);
+ // FIXME: ObjCPropertyDecl are not properly indexed here:
+ // - ObjCPropertyDecl may have an OrigD of ObjCPropertyImplDecl, which is
+ // not a NamedDecl.
+ auto *OriginalDecl = dyn_cast<NamedDecl>(ASTNode.OrigD);
+ if (!OriginalDecl)
+ return true;
+
const Symbol *BasicSymbol = Symbols.find(*ID);
if (!BasicSymbol) // Regardless of role, ND is the canonical declaration.
BasicSymbol = addDeclaration(*ND, std::move(*ID), IsMainFileOnly);
- else if (isPreferredDeclaration(OriginalDecl, Roles))
+ else if (isPreferredDeclaration(*OriginalDecl, Roles))
// If OriginalDecl is preferred, replace the existing canonical
// declaration (e.g. a class forward declaration). There should be at most
// one duplicate as we expect to see only one preferred declaration per
// TU, because in practice they are definitions.
- BasicSymbol = addDeclaration(OriginalDecl, std::move(*ID), IsMainFileOnly);
+ BasicSymbol = addDeclaration(*OriginalDecl, std::move(*ID), IsMainFileOnly);
if (Roles & static_cast<unsigned>(index::SymbolRole::Definition))
- addDefinition(OriginalDecl, *BasicSymbol);
+ addDefinition(*OriginalDecl, *BasicSymbol);
return true;
}
@@ -374,11 +351,18 @@ bool SymbolCollector::handleMacroOccurence(const IdentifierInfo *Name,
const auto &SM = PP->getSourceManager();
auto DefLoc = MI->getDefinitionLoc();
- if (SM.isInMainFile(SM.getExpansionLoc(DefLoc)))
+
+ // Builtin macros don't have useful locations and aren't needed in completion.
+ if (MI->isBuiltinMacro())
return true;
- // Header guards are not interesting in index. Builtin macros don't have
- // useful locations and are not needed for code completions.
- if (MI->isUsedForHeaderGuard() || MI->isBuiltinMacro())
+
+ // Skip main-file symbols if we are not collecting them.
+ bool IsMainFileSymbol = SM.isInMainFile(SM.getExpansionLoc(DefLoc));
+ if (IsMainFileSymbol && !Opts.CollectMainFileSymbols)
+ return false;
+
+ // Also avoid storing predefined macros like __DBL_MIN__.
+ if (SM.isWrittenInBuiltinFile(DefLoc))
return true;
// Mark the macro as referenced if this is a reference coming from the main
@@ -405,7 +389,10 @@ bool SymbolCollector::handleMacroOccurence(const IdentifierInfo *Name,
Symbol S;
S.ID = std::move(*ID);
S.Name = Name->getName();
- S.Flags |= Symbol::IndexedForCodeCompletion;
+ if (!IsMainFileSymbol) {
+ S.Flags |= Symbol::IndexedForCodeCompletion;
+ S.Flags |= Symbol::VisibleOutsideFile;
+ }
S.SymInfo = index::getSymbolInfoForMacro(*MI);
std::string FileURI;
// FIXME: use the result to filter out symbols.
@@ -420,22 +407,25 @@ bool SymbolCollector::handleMacroOccurence(const IdentifierInfo *Name,
std::string Signature;
std::string SnippetSuffix;
getSignature(*CCS, &Signature, &SnippetSuffix);
-
- std::string Include;
- if (Opts.CollectIncludePath && shouldCollectIncludePath(S.SymInfo.Kind)) {
- if (auto Header = getIncludeHeader(Name->getName(), SM,
- SM.getExpansionLoc(DefLoc), Opts))
- Include = std::move(*Header);
- }
S.Signature = Signature;
S.CompletionSnippetSuffix = SnippetSuffix;
- if (!Include.empty())
- S.IncludeHeaders.emplace_back(Include, 1);
+ IndexedMacros.insert(Name);
+ setIncludeLocation(S, DefLoc);
Symbols.insert(S);
return true;
}
+void SymbolCollector::setIncludeLocation(const Symbol &S,
+ SourceLocation Loc) {
+ if (Opts.CollectIncludePath)
+ if (shouldCollectIncludePath(S.SymInfo.Kind))
+ // Use the expansion location to get the #include header since this is
+ // where the symbol is exposed.
+ IncludeFiles[S.ID] =
+ PP->getSourceManager().getDecomposedExpansionLoc(Loc).first;
+}
+
void SymbolCollector::finish() {
// At the end of the TU, add 1 to the refcount of all referenced symbols.
auto IncRef = [this](const SymbolID &ID) {
@@ -452,6 +442,14 @@ void SymbolCollector::finish() {
}
if (Opts.CollectMacro) {
assert(PP);
+ // First, drop header guards. We can't identify these until EOF.
+ for (const IdentifierInfo *II : IndexedMacros) {
+ if (const auto *MI = PP->getMacroDefinition(II).getMacroInfo())
+ if (auto ID = getSymbolID(*II, MI, PP->getSourceManager()))
+ if (MI->isUsedForHeaderGuard())
+ Symbols.erase(*ID);
+ }
+ // Now increment refcounts.
for (const IdentifierInfo *II : ReferencedMacros) {
if (const auto *MI = PP->getMacroDefinition(II).getMacroInfo())
if (auto ID = getSymbolID(*II, MI, PP->getSourceManager()))
@@ -459,6 +457,21 @@ void SymbolCollector::finish() {
}
}
+ // Fill in IncludeHeaders.
+ // We delay this until end of TU so header guards are all resolved.
+ // Symbols in slabs aren' mutable, so insert() has to walk all the strings :-(
+ llvm::SmallString<256> QName;
+ for (const auto &Entry : IncludeFiles)
+ if (const Symbol *S = Symbols.find(Entry.first)) {
+ QName = S->Scope;
+ QName.append(S->Name);
+ if (auto Header = getIncludeHeader(QName, Entry.second)) {
+ Symbol NewSym = *S;
+ NewSym.IncludeHeaders.push_back({*Header, 1});
+ Symbols.insert(NewSym);
+ }
+ }
+
const auto &SM = ASTCtx->getSourceManager();
llvm::DenseMap<FileID, std::string> URICache;
auto GetURI = [&](FileID FID) -> llvm::Optional<std::string> {
@@ -476,7 +489,7 @@ void SymbolCollector::finish() {
}
return Found->second;
};
-
+ // Populate Refs slab from DeclRefs.
if (auto MainFileURI = GetURI(SM.getMainFileID())) {
for (const auto &It : DeclRefs) {
if (auto ID = getSymbolID(It.first)) {
@@ -503,10 +516,11 @@ void SymbolCollector::finish() {
ReferencedMacros.clear();
DeclRefs.clear();
FilesToIndexCache.clear();
+ HeaderIsSelfContainedCache.clear();
+ IncludeFiles.clear();
}
-const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND,
- SymbolID ID,
+const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND, SymbolID ID,
bool IsMainFileOnly) {
auto &Ctx = ND.getASTContext();
auto &SM = Ctx.getSourceManager();
@@ -514,9 +528,11 @@ const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND,
Symbol S;
S.ID = std::move(ID);
std::string QName = printQualifiedName(ND);
- std::tie(S.Scope, S.Name) = splitQualifiedName(QName);
// FIXME: this returns foo:bar: for objective-C methods, we prefer only foo:
// for consistency with CodeCompletionString and a clean name/signature split.
+ std::tie(S.Scope, S.Name) = splitQualifiedName(QName);
+ std::string TemplateSpecializationArgs = printTemplateSpecializationArgs(ND);
+ S.TemplateSpecializationArgs = TemplateSpecializationArgs;
// We collect main-file symbols, but do not use them for code completion.
if (!IsMainFileOnly && isIndexedForCodeCompletion(ND, Ctx))
@@ -528,6 +544,7 @@ const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND,
S.SymInfo = index::getSymbolInfo(&ND);
std::string FileURI;
auto Loc = findNameLoc(&ND);
+ assert(Loc.isValid() && "Invalid source location for NamedDecl");
// FIXME: use the result to filter out symbols.
shouldIndexFile(SM, SM.getFileID(Loc), Opts, &FilesToIndexCache);
if (auto DeclLoc =
@@ -550,18 +567,13 @@ const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND,
std::string Documentation =
formatDocumentation(*CCS, getDocComment(Ctx, SymbolCompletion,
/*CommentsFromHeaders=*/true));
- // For symbols not indexed for completion (class members), we also store their
- // docs in the index, because Sema doesn't load the docs from the preamble, we
- // rely on the index to get the docs.
- // FIXME: this can be optimized by only storing the docs in dynamic index --
- // dynamic index should index these symbols when Sema completes a member
- // completion.
- S.Documentation = Documentation;
if (!(S.Flags & Symbol::IndexedForCodeCompletion)) {
+ if (Opts.StoreAllDocumentation)
+ S.Documentation = Documentation;
Symbols.insert(S);
return Symbols.find(S.ID);
}
-
+ S.Documentation = Documentation;
std::string Signature;
std::string SnippetSuffix;
getSignature(*CCS, &Signature, &SnippetSuffix);
@@ -570,17 +582,6 @@ const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND,
std::string ReturnType = getReturnType(*CCS);
S.ReturnType = ReturnType;
- std::string Include;
- if (Opts.CollectIncludePath && shouldCollectIncludePath(S.SymInfo.Kind)) {
- // Use the expansion location to get the #include header since this is
- // where the symbol is exposed.
- if (auto Header = getIncludeHeader(
- QName, SM, SM.getExpansionLoc(ND.getLocation()), Opts))
- Include = std::move(*Header);
- }
- if (!Include.empty())
- S.IncludeHeaders.emplace_back(Include, 1);
-
llvm::Optional<OpaqueType> TypeStorage;
if (S.Flags & Symbol::IndexedForCodeCompletion) {
TypeStorage = OpaqueType::fromCompletionResult(*ASTCtx, SymbolCompletion);
@@ -589,6 +590,7 @@ const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND,
}
Symbols.insert(S);
+ setIncludeLocation(S, ND.getLocation());
return Symbols.find(S.ID);
}
@@ -611,5 +613,90 @@ void SymbolCollector::addDefinition(const NamedDecl &ND,
Symbols.insert(S);
}
+/// Gets a canonical include (URI of the header or <header> or "header") for
+/// header of \p FID (which should usually be the *expansion* file).
+/// Returns None if includes should not be inserted for this file.
+llvm::Optional<std::string>
+SymbolCollector::getIncludeHeader(llvm::StringRef QName, FileID FID) {
+ const SourceManager &SM = ASTCtx->getSourceManager();
+ const FileEntry *FE = SM.getFileEntryForID(FID);
+ if (!FE || FE->getName().empty())
+ return llvm::None;
+ llvm::StringRef Filename = FE->getName();
+ // If a file is mapped by canonical headers, use that mapping, regardless
+ // of whether it's an otherwise-good header (header guards etc).
+ if (Opts.Includes) {
+ llvm::StringRef Canonical = Opts.Includes->mapHeader(Filename, QName);
+ // If we had a mapping, always use it.
+ if (Canonical.startswith("<") || Canonical.startswith("\""))
+ return Canonical.str();
+ if (Canonical != Filename)
+ return toURI(SM, Canonical, Opts);
+ }
+ if (!isSelfContainedHeader(FID)) {
+ // A .inc or .def file is often included into a real header to define
+ // symbols (e.g. LLVM tablegen files).
+ if (Filename.endswith(".inc") || Filename.endswith(".def"))
+ return getIncludeHeader(QName, SM.getFileID(SM.getIncludeLoc(FID)));
+ // Conservatively refuse to insert #includes to files without guards.
+ return llvm::None;
+ }
+ // Standard case: just insert the file itself.
+ return toURI(SM, Filename, Opts);
+}
+
+bool SymbolCollector::isSelfContainedHeader(FileID FID) {
+ // The real computation (which will be memoized).
+ auto Compute = [&] {
+ const SourceManager &SM = ASTCtx->getSourceManager();
+ const FileEntry *FE = SM.getFileEntryForID(FID);
+ if (!FE)
+ return false;
+ if (!PP->getHeaderSearchInfo().isFileMultipleIncludeGuarded(FE))
+ return false;
+ // This pattern indicates that a header can't be used without
+ // particular preprocessor state, usually set up by another header.
+ if (isDontIncludeMeHeader(SM.getBufferData(FID)))
+ return false;
+ return true;
+ };
+
+ auto R = HeaderIsSelfContainedCache.try_emplace(FID, false);
+ if (R.second)
+ R.first->second = Compute();
+ return R.first->second;
+}
+
+// Is Line an #if or #ifdef directive?
+static bool isIf(llvm::StringRef Line) {
+ Line = Line.ltrim();
+ if (!Line.consume_front("#"))
+ return false;
+ Line = Line.ltrim();
+ return Line.startswith("if");
+}
+// Is Line an #error directive mentioning includes?
+static bool isErrorAboutInclude(llvm::StringRef Line) {
+ Line = Line.ltrim();
+ if (!Line.consume_front("#"))
+ return false;
+ Line = Line.ltrim();
+ if (! Line.startswith("error"))
+ return false;
+ return Line.contains_lower("includ"); // Matches "include" or "including".
+}
+
+bool SymbolCollector::isDontIncludeMeHeader(llvm::StringRef Content) {
+ llvm::StringRef Line;
+ // Only sniff up to 100 lines or 10KB.
+ Content = Content.take_front(100*100);
+ for (unsigned I = 0; I < 100 && !Content.empty(); ++I) {
+ std::tie(Line, Content) = Content.split('\n');
+ if (isIf(Line) && isErrorAboutInclude(Content.split('\n').first))
+ return true;
+ }
+ return false;
+}
+
} // namespace clangd
} // namespace clang
diff --git a/clangd/index/SymbolCollector.h b/clangd/index/SymbolCollector.h
index 157735d0..f746002b 100644
--- a/clangd/index/SymbolCollector.h
+++ b/clangd/index/SymbolCollector.h
@@ -1,9 +1,8 @@
//===--- SymbolCollector.h ---------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CLANGD_INDEX_SYMBOL_COLLECTOR_H
@@ -11,6 +10,7 @@
#include "CanonicalIncludes.h"
#include "Index.h"
+#include "SymbolOrigin.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/SourceLocation.h"
@@ -19,6 +19,7 @@
#include "clang/Index/IndexSymbol.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Regex.h"
#include <functional>
namespace clang {
@@ -76,6 +77,10 @@ public:
/// Collect symbols local to main-files, such as static functions
/// and symbols inside an anonymous namespace.
bool CollectMainFileSymbols = true;
+ /// If set to true, SymbolCollector will collect doc for all symbols.
+ /// Note that documents of symbols being indexed for completion will always
+ /// be collected regardless of this option.
+ bool StoreAllDocumentation = false;
/// If this is set, only collect symbols/references from a file if
/// `FileFilter(SM, FID)` is true. If not set, all files are indexed.
std::function<bool(const SourceManager &, FileID)> FileFilter = nullptr;
@@ -109,11 +114,23 @@ public:
void finish() override;
private:
- const Symbol *addDeclaration(const NamedDecl &, SymbolID, bool IsMainFileSymbol);
+ const Symbol *addDeclaration(const NamedDecl &, SymbolID,
+ bool IsMainFileSymbol);
void addDefinition(const NamedDecl &, const Symbol &DeclSymbol);
+ llvm::Optional<std::string> getIncludeHeader(llvm::StringRef QName, FileID);
+ bool isSelfContainedHeader(FileID);
+ // Heuristically headers that only want to be included via an umbrella.
+ static bool isDontIncludeMeHeader(llvm::StringRef);
+
// All Symbols collected from the AST.
SymbolSlab::Builder Symbols;
+ // File IDs for Symbol.IncludeHeaders.
+ // The final spelling is calculated in finish().
+ llvm::DenseMap<SymbolID, FileID> IncludeFiles;
+ void setIncludeLocation(const Symbol &S, SourceLocation);
+ // Indexed macros, to be erased if they turned out to be include guards.
+ llvm::DenseSet<const IdentifierInfo *> IndexedMacros;
// All refs collected from the AST.
// Only symbols declared in preamble (from #include) and referenced from the
// main file will be included.
@@ -136,8 +153,10 @@ private:
llvm::DenseMap<const Decl *, const Decl *> CanonicalDecls;
// Cache whether to index a file or not.
llvm::DenseMap<FileID, bool> FilesToIndexCache;
+ llvm::DenseMap<FileID, bool> HeaderIsSelfContainedCache;
};
} // namespace clangd
} // namespace clang
+
#endif
diff --git a/clangd/index/SymbolID.cpp b/clangd/index/SymbolID.cpp
index 1fd42744..b97103d3 100644
--- a/clangd/index/SymbolID.cpp
+++ b/clangd/index/SymbolID.cpp
@@ -1,9 +1,8 @@
//===--- SymbolID.cpp --------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -50,7 +49,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolID &ID) {
llvm::hash_code hash_value(const SymbolID &ID) {
// We already have a good hash, just return the first bytes.
- assert(sizeof(size_t) <= SymbolID::RawSize && "size_t longer than SHA1!");
+ static_assert(sizeof(size_t) <= SymbolID::RawSize,
+ "size_t longer than SHA1!");
size_t Result;
memcpy(&Result, ID.raw().data(), sizeof(size_t));
return llvm::hash_code(Result);
diff --git a/clangd/index/SymbolID.h b/clangd/index/SymbolID.h
index aa8208c1..d715f4d0 100644
--- a/clangd/index/SymbolID.h
+++ b/clangd/index/SymbolID.h
@@ -1,15 +1,15 @@
//===--- SymbolID.h ----------------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_CLANGD_INDEX_SYMBOLID_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOLID_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
@@ -62,4 +62,25 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolID &ID);
} // namespace clangd
} // namespace clang
+namespace llvm {
+// Support SymbolIDs as DenseMap keys.
+template <> struct DenseMapInfo<clang::clangd::SymbolID> {
+ static inline clang::clangd::SymbolID getEmptyKey() {
+ static clang::clangd::SymbolID EmptyKey("EMPTYKEY");
+ return EmptyKey;
+ }
+ static inline clang::clangd::SymbolID getTombstoneKey() {
+ static clang::clangd::SymbolID TombstoneKey("TOMBSTONEKEY");
+ return TombstoneKey;
+ }
+ static unsigned getHashValue(const clang::clangd::SymbolID &Sym) {
+ return hash_value(Sym);
+ }
+ static bool isEqual(const clang::clangd::SymbolID &LHS,
+ const clang::clangd::SymbolID &RHS) {
+ return LHS == RHS;
+ }
+};
+} // namespace llvm
+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOLID_H
diff --git a/clangd/index/SymbolLocation.cpp b/clangd/index/SymbolLocation.cpp
new file mode 100644
index 00000000..aac55703
--- /dev/null
+++ b/clangd/index/SymbolLocation.cpp
@@ -0,0 +1,40 @@
+//===--- SymbolLocation.cpp --------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolLocation.h"
+
+namespace clang {
+namespace clangd {
+
+constexpr uint32_t SymbolLocation::Position::MaxLine;
+constexpr uint32_t SymbolLocation::Position::MaxColumn;
+
+void SymbolLocation::Position::setLine(uint32_t L) {
+ if (L > MaxLine) {
+ Line = MaxLine;
+ return;
+ }
+ Line = L;
+}
+void SymbolLocation::Position::setColumn(uint32_t Col) {
+ if (Col > MaxColumn) {
+ Column = MaxColumn;
+ return;
+ }
+ Column = Col;
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolLocation &L) {
+ if (!L)
+ return OS << "(none)";
+ return OS << L.FileURI << "[" << L.Start.line() << ":" << L.Start.column()
+ << "-" << L.End.line() << ":" << L.End.column() << ")";
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/clangd/index/SymbolLocation.h b/clangd/index/SymbolLocation.h
new file mode 100644
index 00000000..9b503546
--- /dev/null
+++ b/clangd/index/SymbolLocation.h
@@ -0,0 +1,94 @@
+//===--- SymbolLocation.h ----------------------------------------*- 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_CLANGD_INDEX_SYMBOL_LOCATION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_LOCATION_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+
+namespace clang {
+namespace clangd {
+
+struct SymbolLocation {
+ // Specify a position (Line, Column) of symbol. Using Line/Column allows us to
+ // build LSP responses without reading the file content.
+ //
+ // clangd uses the following definitions, which differ slightly from LSP:
+ // - Line is the number of newline characters (\n) before the point.
+ // - Column is (by default) the number of UTF-16 code between the last \n
+ // (or start of file) and the point.
+ // If the `offsetEncoding` protocol extension is used to negotiate UTF-8,
+ // then it is instead the number of *bytes* since the last \n.
+ //
+ // Position is encoded into 32 bits to save space.
+ // If Line/Column overflow, the value will be their maximum value.
+ struct Position {
+ Position() : Line(0), Column(0) {}
+ void setLine(uint32_t Line);
+ uint32_t line() const { return Line; }
+ void setColumn(uint32_t Column);
+ uint32_t column() const { return Column; }
+
+ bool hasOverflow() const {
+ return Line >= MaxLine || Column >= MaxColumn;
+ }
+
+ static constexpr uint32_t MaxLine = (1 << 20) - 1;
+ static constexpr uint32_t MaxColumn = (1 << 12) - 1;
+
+ private:
+ uint32_t Line : 20; // 0-based
+ uint32_t Column : 12; // 0-based
+ };
+
+ /// The symbol range, using half-open range [Start, End).
+ Position Start;
+ Position End;
+
+ explicit operator bool() const { return !llvm::StringRef(FileURI).empty(); }
+
+ // The URI of the source file where a symbol occurs.
+ // The string must be null-terminated.
+ //
+ // We avoid using llvm::StringRef here to save memory.
+ // WARNING: unless you know what you are doing, it is recommended to use it
+ // via llvm::StringRef.
+ const char *FileURI = "";
+};
+
+inline bool operator==(const SymbolLocation::Position &L,
+ const SymbolLocation::Position &R) {
+ return std::make_tuple(L.line(), L.column()) ==
+ std::make_tuple(R.line(), R.column());
+}
+inline bool operator<(const SymbolLocation::Position &L,
+ const SymbolLocation::Position &R) {
+ return std::make_tuple(L.line(), L.column()) <
+ std::make_tuple(R.line(), R.column());
+}
+inline bool operator==(const SymbolLocation &L, const SymbolLocation &R) {
+ assert(L.FileURI && R.FileURI);
+ return !std::strcmp(L.FileURI, R.FileURI) &&
+ std::tie(L.Start, L.End) == std::tie(R.Start, R.End);
+}
+inline bool operator<(const SymbolLocation &L, const SymbolLocation &R) {
+ assert(L.FileURI && R.FileURI);
+ int Cmp = std::strcmp(L.FileURI, R.FileURI);
+ if (Cmp != 0)
+ return Cmp < 0;
+ return std::tie(L.Start, L.End) < std::tie(R.Start, R.End);
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const SymbolLocation &);
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_LOCATION_H
diff --git a/clangd/index/SymbolOrigin.cpp b/clangd/index/SymbolOrigin.cpp
new file mode 100644
index 00000000..e98308a2
--- /dev/null
+++ b/clangd/index/SymbolOrigin.cpp
@@ -0,0 +1,25 @@
+//===--- SymbolOrigin.cpp ----------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolOrigin.h"
+
+namespace clang {
+namespace clangd {
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SymbolOrigin O) {
+ if (O == SymbolOrigin::Unknown)
+ return OS << "unknown";
+ constexpr static char Sigils[] = "ADSMI567";
+ for (unsigned I = 0; I < sizeof(Sigils); ++I)
+ if (static_cast<uint8_t>(O) & 1u << I)
+ OS << Sigils[I];
+ return OS;
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/clangd/index/SymbolOrigin.h b/clangd/index/SymbolOrigin.h
new file mode 100644
index 00000000..953f871d
--- /dev/null
+++ b/clangd/index/SymbolOrigin.h
@@ -0,0 +1,48 @@
+//===--- SymbolOrigin.h ------------------------------------------*- 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_CLANGD_INDEX_SYMBOL_ORIGIN_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_ORIGIN_H
+
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+
+namespace clang {
+namespace clangd {
+
+// Describes the source of information about a symbol.
+// Mainly useful for debugging, e.g. understanding code completion reuslts.
+// This is a bitfield as information can be combined from several sources.
+enum class SymbolOrigin : uint8_t {
+ Unknown = 0,
+ AST = 1 << 0, // Directly from the AST (indexes should not set this).
+ Dynamic = 1 << 1, // From the dynamic index of opened files.
+ Static = 1 << 2, // From the static, externally-built index.
+ Merge = 1 << 3, // A non-trivial index merge was performed.
+ Identifier = 1 << 4, // Raw identifiers in file.
+ // Remaining bits reserved for index implementations.
+};
+
+inline SymbolOrigin operator|(SymbolOrigin A, SymbolOrigin B) {
+ return static_cast<SymbolOrigin>(static_cast<uint8_t>(A) |
+ static_cast<uint8_t>(B));
+}
+inline SymbolOrigin &operator|=(SymbolOrigin &A, SymbolOrigin B) {
+ return A = A | B;
+}
+inline SymbolOrigin operator&(SymbolOrigin A, SymbolOrigin B) {
+ return static_cast<SymbolOrigin>(static_cast<uint8_t>(A) &
+ static_cast<uint8_t>(B));
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, SymbolOrigin);
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_ORIGIN_H
diff --git a/clangd/index/YAMLSerialization.cpp b/clangd/index/YAMLSerialization.cpp
index 7eb5b4cf..6bf0cb78 100644
--- a/clangd/index/YAMLSerialization.cpp
+++ b/clangd/index/YAMLSerialization.cpp
@@ -1,9 +1,8 @@
-//===--- SymbolYAML.cpp ------------------------------------------*- C++-*-===//
+//===-- YAMLSerialization.cpp ------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -15,6 +14,8 @@
#include "Index.h"
#include "Serialization.h"
+#include "SymbolLocation.h"
+#include "SymbolOrigin.h"
#include "Trace.h"
#include "dex/Dex.h"
#include "llvm/ADT/Optional.h"
@@ -192,6 +193,8 @@ template <> struct MappingTraits<Symbol> {
IO.mapOptional("Origin", NSymbolOrigin->Origin);
IO.mapOptional("Flags", NSymbolFlag->Flag);
IO.mapOptional("Signature", Sym.Signature);
+ IO.mapOptional("TemplateSpecializationArgs",
+ Sym.TemplateSpecializationArgs);
IO.mapOptional("CompletionSnippetSuffix", Sym.CompletionSnippetSuffix);
IO.mapOptional("Documentation", Sym.Documentation);
IO.mapOptional("ReturnType", Sym.ReturnType);
diff --git a/clangd/index/dex/Dex.cpp b/clangd/index/dex/Dex.cpp
index c38706c6..d767bb51 100644
--- a/clangd/index/dex/Dex.cpp
+++ b/clangd/index/dex/Dex.cpp
@@ -1,9 +1,8 @@
//===--- Dex.cpp - Dex Symbol Index Implementation --------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -43,7 +42,6 @@ const Token RestrictedForCodeCompletion =
// Returns the tokens which are given symbols's characteristics. For example,
// trigrams and scopes.
// FIXME(kbobyrev): Support more token types:
-// * Types
// * Namespace proximity
std::vector<Token> generateSearchTokens(const Symbol &Sym) {
std::vector<Token> Result = generateIdentifierTrigrams(Sym.Name);
@@ -55,49 +53,11 @@ std::vector<Token> generateSearchTokens(const Symbol &Sym) {
Result.emplace_back(Token::Kind::ProximityURI, ProximityURI);
if (Sym.Flags & Symbol::IndexedForCodeCompletion)
Result.emplace_back(RestrictedForCodeCompletion);
+ if (!Sym.Type.empty())
+ Result.emplace_back(Token::Kind::Type, Sym.Type);
return Result;
}
-// Constructs BOOST iterators for Path Proximities.
-std::unique_ptr<Iterator> createFileProximityIterator(
- llvm::ArrayRef<std::string> ProximityPaths,
- const llvm::DenseMap<Token, PostingList> &InvertedIndex,
- const Corpus &Corpus) {
- std::vector<std::unique_ptr<Iterator>> BoostingIterators;
- // Deduplicate parent URIs extracted from the ProximityPaths.
- llvm::StringSet<> ParentURIs;
- llvm::StringMap<SourceParams> Sources;
- for (const auto &Path : ProximityPaths) {
- Sources[Path] = SourceParams();
- auto PathURI = URI::create(Path);
- const auto PathProximityURIs = generateProximityURIs(PathURI.toString());
- for (const auto &ProximityURI : PathProximityURIs)
- ParentURIs.insert(ProximityURI);
- }
- // Use SymbolRelevanceSignals for symbol relevance evaluation: use defaults
- // for all parameters except for Proximity Path distance signal.
- SymbolRelevanceSignals PathProximitySignals;
- // DistanceCalculator will find the shortest distance from ProximityPaths to
- // any URI extracted from the ProximityPaths.
- URIDistance DistanceCalculator(Sources);
- PathProximitySignals.FileProximityMatch = &DistanceCalculator;
- // Try to build BOOST iterator for each Proximity Path provided by
- // ProximityPaths. Boosting factor should depend on the distance to the
- // Proximity Path: the closer processed path is, the higher boosting factor.
- for (const auto &ParentURI : ParentURIs.keys()) {
- Token Tok(Token::Kind::ProximityURI, ParentURI);
- const auto It = InvertedIndex.find(Tok);
- if (It != InvertedIndex.end()) {
- // FIXME(kbobyrev): Append LIMIT on top of every BOOST iterator.
- PathProximitySignals.SymbolURI = ParentURI;
- BoostingIterators.push_back(Corpus.boost(
- It->second.iterator(&It->first), PathProximitySignals.evaluate()));
- }
- }
- BoostingIterators.push_back(Corpus.all());
- return Corpus.unionOf(std::move(BoostingIterators));
-}
-
} // namespace
void Dex::buildIndex() {
@@ -142,6 +102,57 @@ std::unique_ptr<Iterator> Dex::iterator(const Token &Tok) const {
: It->second.iterator(&It->first);
}
+// Constructs BOOST iterators for Path Proximities.
+std::unique_ptr<Iterator> Dex::createFileProximityIterator(
+ llvm::ArrayRef<std::string> ProximityPaths) const {
+ std::vector<std::unique_ptr<Iterator>> BoostingIterators;
+ // Deduplicate parent URIs extracted from the ProximityPaths.
+ llvm::StringSet<> ParentURIs;
+ llvm::StringMap<SourceParams> Sources;
+ for (const auto &Path : ProximityPaths) {
+ Sources[Path] = SourceParams();
+ auto PathURI = URI::create(Path);
+ const auto PathProximityURIs = generateProximityURIs(PathURI.toString());
+ for (const auto &ProximityURI : PathProximityURIs)
+ ParentURIs.insert(ProximityURI);
+ }
+ // Use SymbolRelevanceSignals for symbol relevance evaluation: use defaults
+ // for all parameters except for Proximity Path distance signal.
+ SymbolRelevanceSignals PathProximitySignals;
+ // DistanceCalculator will find the shortest distance from ProximityPaths to
+ // any URI extracted from the ProximityPaths.
+ URIDistance DistanceCalculator(Sources);
+ PathProximitySignals.FileProximityMatch = &DistanceCalculator;
+ // Try to build BOOST iterator for each Proximity Path provided by
+ // ProximityPaths. Boosting factor should depend on the distance to the
+ // Proximity Path: the closer processed path is, the higher boosting factor.
+ for (const auto &ParentURI : ParentURIs.keys()) {
+ // FIXME(kbobyrev): Append LIMIT on top of every BOOST iterator.
+ auto It = iterator(Token(Token::Kind::ProximityURI, ParentURI));
+ if (It->kind() != Iterator::Kind::False) {
+ PathProximitySignals.SymbolURI = ParentURI;
+ BoostingIterators.push_back(
+ Corpus.boost(std::move(It), PathProximitySignals.evaluate()));
+ }
+ }
+ BoostingIterators.push_back(Corpus.all());
+ return Corpus.unionOf(std::move(BoostingIterators));
+}
+
+// Constructs BOOST iterators for preferred types.
+std::unique_ptr<Iterator>
+Dex::createTypeBoostingIterator(llvm::ArrayRef<std::string> Types) const {
+ std::vector<std::unique_ptr<Iterator>> BoostingIterators;
+ SymbolRelevanceSignals PreferredTypeSignals;
+ PreferredTypeSignals.TypeMatchesPreferred = true;
+ auto Boost = PreferredTypeSignals.evaluate();
+ for (const auto &T : Types)
+ BoostingIterators.push_back(
+ Corpus.boost(iterator(Token(Token::Kind::Type, T)), Boost));
+ BoostingIterators.push_back(Corpus.all());
+ return Corpus.unionOf(std::move(BoostingIterators));
+}
+
/// Constructs iterators over tokens extracted from the query and exhausts it
/// while applying Callback to each symbol in the order of decreasing quality
/// of the matched symbols.
@@ -175,8 +186,9 @@ bool Dex::fuzzyFind(const FuzzyFindRequest &Req,
Criteria.push_back(Corpus.unionOf(move(ScopeIterators)));
// Add proximity paths boosting (all symbols, some boosted).
- Criteria.push_back(
- createFileProximityIterator(Req.ProximityPaths, InvertedIndex, Corpus));
+ Criteria.push_back(createFileProximityIterator(Req.ProximityPaths));
+ // Add boosting for preferred types.
+ Criteria.push_back(createTypeBoostingIterator(Req.PreferredTypes));
if (Req.RestrictForCodeCompletion)
Criteria.push_back(iterator(RestrictedForCodeCompletion));
diff --git a/clangd/index/dex/Dex.h b/clangd/index/dex/Dex.h
index c790e417..fb80ca03 100644
--- a/clangd/index/dex/Dex.h
+++ b/clangd/index/dex/Dex.h
@@ -1,9 +1,8 @@
//===--- Dex.h - Dex Symbol Index Implementation ----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
@@ -78,6 +77,10 @@ public:
private:
void buildIndex();
std::unique_ptr<Iterator> iterator(const Token &Tok) const;
+ std::unique_ptr<Iterator>
+ createFileProximityIterator(llvm::ArrayRef<std::string> ProximityPaths) const;
+ std::unique_ptr<Iterator>
+ createTypeBoostingIterator(llvm::ArrayRef<std::string> Types) const;
/// Stores symbols sorted in the descending order of symbol quality..
std::vector<const Symbol *> Symbols;
diff --git a/clangd/index/dex/Iterator.cpp b/clangd/index/dex/Iterator.cpp
index 0b132b94..cb294a33 100644
--- a/clangd/index/dex/Iterator.cpp
+++ b/clangd/index/dex/Iterator.cpp
@@ -1,9 +1,8 @@
//===--- Iterator.cpp - Query Symbol Retrieval ------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/index/dex/Iterator.h b/clangd/index/dex/Iterator.h
index 149fd43a..34b42c32 100644
--- a/clangd/index/dex/Iterator.h
+++ b/clangd/index/dex/Iterator.h
@@ -1,9 +1,8 @@
//===--- Iterator.h - Query Symbol Retrieval --------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
diff --git a/clangd/index/dex/PostingList.cpp b/clangd/index/dex/PostingList.cpp
index eb2e4757..67ed070a 100644
--- a/clangd/index/dex/PostingList.cpp
+++ b/clangd/index/dex/PostingList.cpp
@@ -1,15 +1,15 @@
//===--- PostingList.cpp - Symbol identifiers storage interface -----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "PostingList.h"
#include "Iterator.h"
#include "Token.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
@@ -50,7 +50,8 @@ public:
return;
advanceToChunk(ID);
// Try to find ID within current chunk.
- CurrentID = std::lower_bound(CurrentID, std::end(DecompressedChunk), ID);
+ CurrentID = llvm::bsearch(CurrentID, DecompressedChunk.end(),
+ [&](const DocID D) { return D >= ID; });
normalizeCursor();
}
@@ -101,10 +102,9 @@ private:
void advanceToChunk(DocID ID) {
if ((CurrentChunk != Chunks.end() - 1) &&
((CurrentChunk + 1)->Head <= ID)) {
- // Find the next chunk with Head >= ID.
- CurrentChunk = std::lower_bound(
- CurrentChunk + 1, Chunks.end(), ID,
- [](const Chunk &C, const DocID ID) { return C.Head <= ID; });
+ CurrentChunk =
+ llvm::bsearch(CurrentChunk + 1, Chunks.end(),
+ [&](const Chunk &C) { return C.Head >= ID; });
--CurrentChunk;
DecompressedChunk = CurrentChunk->decompress();
CurrentID = DecompressedChunk.begin();
diff --git a/clangd/index/dex/PostingList.h b/clangd/index/dex/PostingList.h
index 81ba64c1..418e4c72 100644
--- a/clangd/index/dex/PostingList.h
+++ b/clangd/index/dex/PostingList.h
@@ -1,9 +1,8 @@
//===--- PostingList.h - Symbol identifiers storage interface --*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
diff --git a/clangd/index/dex/Token.h b/clangd/index/dex/Token.h
index f80d9254..37859bcf 100644
--- a/clangd/index/dex/Token.h
+++ b/clangd/index/dex/Token.h
@@ -1,9 +1,8 @@
//===--- Token.h - Symbol Search primitive ----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
@@ -63,11 +62,11 @@ struct Token {
/// Example: "file:///path/to/clang-tools-extra/clangd/index/SymbolIndex.h"
/// and some amount of its parents.
ProximityURI,
+ /// Type of symbol (see `Symbol::Type`).
+ Type,
/// Internal Token type for invalid/special tokens, e.g. empty tokens for
/// llvm::DenseMap.
Sentinel,
- /// FIXME(kbobyrev): Add other Token Kinds
- /// * Type with qualified type name or its USR
};
Token(Kind TokenKind, llvm::StringRef Data)
@@ -92,6 +91,9 @@ struct Token {
case Kind::ProximityURI:
OS << "U=";
break;
+ case Kind::Type:
+ OS << "Ty=";
+ break;
case Kind::Sentinel:
OS << "?=";
break;
diff --git a/clangd/index/dex/Trigram.cpp b/clangd/index/dex/Trigram.cpp
index 2ba0ad18..24ae72bf 100644
--- a/clangd/index/dex/Trigram.cpp
+++ b/clangd/index/dex/Trigram.cpp
@@ -1,9 +1,8 @@
//===--- Trigram.cpp - Trigram generation for Fuzzy Matching ----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/index/dex/Trigram.h b/clangd/index/dex/Trigram.h
index adce9f42..bf1e5e80 100644
--- a/clangd/index/dex/Trigram.h
+++ b/clangd/index/dex/Trigram.h
@@ -1,9 +1,8 @@
//===--- Trigram.h - Trigram generation for Fuzzy Matching ------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
diff --git a/clangd/index/dex/dexp/Dexp.cpp b/clangd/index/dex/dexp/Dexp.cpp
index 5a0b6d97..820dc66b 100644
--- a/clangd/index/dex/dexp/Dexp.cpp
+++ b/clangd/index/dex/dexp/Dexp.cpp
@@ -1,9 +1,8 @@
//===--- Dexp.cpp - Dex EXPloration tool ------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clangd/indexer/CMakeLists.txt b/clangd/indexer/CMakeLists.txt
index 5ba5b677..92aae064 100644
--- a/clangd/indexer/CMakeLists.txt
+++ b/clangd/indexer/CMakeLists.txt
@@ -11,10 +11,10 @@ add_clang_executable(clangd-indexer
target_link_libraries(clangd-indexer
PRIVATE
clangAST
- clangIndex
- clangDaemon
clangBasic
+ clangDaemon
clangFrontend
+ clangIndex
clangLex
clangTooling
)
diff --git a/clangd/indexer/IndexerMain.cpp b/clangd/indexer/IndexerMain.cpp
index 18e6304f..d0128251 100644
--- a/clangd/indexer/IndexerMain.cpp
+++ b/clangd/indexer/IndexerMain.cpp
@@ -1,9 +1,8 @@
//===--- IndexerMain.cpp -----------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -11,11 +10,13 @@
//
//===----------------------------------------------------------------------===//
-#include "index/Index.h"
#include "index/IndexAction.h"
#include "index/Merge.h"
+#include "index/Ref.h"
#include "index/Serialization.h"
+#include "index/Symbol.h"
#include "index/SymbolCollector.h"
+#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Execution.h"
#include "clang/Tooling/Tooling.h"
@@ -55,7 +56,7 @@ public:
[&](RefSlab S) {
std::lock_guard<std::mutex> Lock(SymbolsMu);
for (const auto &Sym : S) {
- // No need to merge as currently all Refs are from main file.
+ // Deduplication happens during insertion.
for (const auto &Ref : Sym.second)
Refs.insert(Sym.first, Ref);
}
@@ -110,7 +111,8 @@ int main(int argc, const char **argv) {
// Collect symbols found in each translation unit, merging as we go.
clang::clangd::IndexFileIn Data;
auto Err = Executor->get()->execute(
- llvm::make_unique<clang::clangd::IndexActionFactory>(Data));
+ llvm::make_unique<clang::clangd::IndexActionFactory>(Data),
+ clang::tooling::getStripPluginsAdjuster());
if (Err) {
llvm::errs() << llvm::toString(std::move(Err)) << "\n";
}
diff --git a/clangd/refactor/Tweak.cpp b/clangd/refactor/Tweak.cpp
new file mode 100644
index 00000000..34634e64
--- /dev/null
+++ b/clangd/refactor/Tweak.cpp
@@ -0,0 +1,82 @@
+//===--- Tweak.cpp -----------------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "Tweak.h"
+#include "Logger.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Registry.h"
+#include <functional>
+#include <memory>
+
+LLVM_INSTANTIATE_REGISTRY(llvm::Registry<clang::clangd::Tweak>)
+
+namespace clang {
+namespace clangd {
+
+/// A handy typedef to save some typing.
+typedef llvm::Registry<Tweak> TweakRegistry;
+
+namespace {
+/// Asserts invariants on TweakRegistry. No-op with assertion disabled.
+void validateRegistry() {
+#ifndef NDEBUG
+ llvm::StringSet<> Seen;
+ for (const auto &E : TweakRegistry::entries()) {
+ // REGISTER_TWEAK ensures E.getName() is equal to the tweak class name.
+ // We check that id() matches it.
+ assert(E.instantiate()->id() == E.getName() &&
+ "id should be equal to class name");
+ assert(Seen.try_emplace(E.getName()).second && "duplicate check id");
+ }
+#endif
+}
+} // namespace
+
+Tweak::Selection::Selection(ParsedAST &AST, unsigned RangeBegin,
+ unsigned RangeEnd)
+ : AST(AST), ASTSelection(AST.getASTContext(), RangeBegin, RangeEnd) {
+ auto &SM = AST.getASTContext().getSourceManager();
+ Code = SM.getBufferData(SM.getMainFileID());
+ Cursor = SM.getComposedLoc(SM.getMainFileID(), RangeBegin);
+}
+
+std::vector<std::unique_ptr<Tweak>> prepareTweaks(const Tweak::Selection &S) {
+ validateRegistry();
+
+ std::vector<std::unique_ptr<Tweak>> Available;
+ for (const auto &E : TweakRegistry::entries()) {
+ std::unique_ptr<Tweak> T = E.instantiate();
+ if (!T->prepare(S))
+ continue;
+ Available.push_back(std::move(T));
+ }
+ // Ensure deterministic order of the results.
+ llvm::sort(Available,
+ [](const std::unique_ptr<Tweak> &L,
+ const std::unique_ptr<Tweak> &R) { return L->id() < R->id(); });
+ return Available;
+}
+
+llvm::Expected<std::unique_ptr<Tweak>> prepareTweak(StringRef ID,
+ const Tweak::Selection &S) {
+ auto It = llvm::find_if(
+ TweakRegistry::entries(),
+ [ID](const TweakRegistry::entry &E) { return E.getName() == ID; });
+ if (It == TweakRegistry::end())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "id of the tweak is invalid");
+ std::unique_ptr<Tweak> T = It->instantiate();
+ if (!T->prepare(S))
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "failed to prepare() a check");
+ return std::move(T);
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/clangd/refactor/Tweak.h b/clangd/refactor/Tweak.h
new file mode 100644
index 00000000..35c3ce8a
--- /dev/null
+++ b/clangd/refactor/Tweak.h
@@ -0,0 +1,94 @@
+//===--- Tweak.h -------------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+// Tweaks are small refactoring-like actions that run over the AST and produce
+// the set of edits as a result. They are local, i.e. they should take the
+// current editor context, e.g. the cursor position and selection into account.
+// The actions are executed in two stages:
+// - Stage 1 should check whether the action is available in a current
+// context. It should be cheap and fast to compute as it is executed for all
+// available actions on every client request, which happen quite frequently.
+// - Stage 2 is performed after stage 1 and can be more expensive to compute.
+// It is performed when the user actually chooses the action.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_ACTIONS_TWEAK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_ACTIONS_TWEAK_H
+
+#include "ClangdUnit.h"
+#include "Protocol.h"
+#include "Selection.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+namespace clang {
+namespace clangd {
+
+/// An interface base for small context-sensitive refactoring actions.
+/// To implement a new tweak use the following pattern in a .cpp file:
+/// class MyTweak : public Tweak {
+/// public:
+/// const char* id() const override final; // defined by REGISTER_TWEAK.
+/// // implement other methods here.
+/// };
+/// REGISTER_TWEAK(MyTweak);
+class Tweak {
+public:
+ /// Input to prepare and apply tweaks.
+ struct Selection {
+ Selection(ParsedAST &AST, unsigned RangeBegin, unsigned RangeEnd);
+ /// The text of the active document.
+ llvm::StringRef Code;
+ /// Parsed AST of the active file.
+ ParsedAST &AST;
+ /// A location of the cursor in the editor.
+ SourceLocation Cursor;
+ // The AST nodes that were selected.
+ SelectionTree ASTSelection;
+ // FIXME: provide a way to get sources and ASTs for other files.
+ };
+ virtual ~Tweak() = default;
+ /// A unique id of the action, it is always equal to the name of the class
+ /// defining the Tweak. Definition is provided automatically by
+ /// REGISTER_TWEAK.
+ virtual const char *id() const = 0;
+ /// Run the first stage of the action. Returns true indicating that the
+ /// action is available and should be shown to the user. Returns false if the
+ /// action is not available.
+ /// This function should be fast, if the action requires non-trivial work it
+ /// should be moved into 'apply'.
+ /// Returns true iff the action is available and apply() can be called on it.
+ virtual bool prepare(const Selection &Sel) = 0;
+ /// Run the second stage of the action that would produce the actual changes.
+ /// EXPECTS: prepare() was called and returned true.
+ virtual Expected<tooling::Replacements> apply(const Selection &Sel) = 0;
+ /// A one-line title of the action that should be shown to the users in the
+ /// UI.
+ /// EXPECTS: prepare() was called and returned true.
+ virtual std::string title() const = 0;
+};
+
+// All tweaks must be registered in the .cpp file next to their definition.
+#define REGISTER_TWEAK(Subclass) \
+ ::llvm::Registry<::clang::clangd::Tweak>::Add<Subclass> \
+ TweakRegistrationFor##Subclass(#Subclass, /*Description=*/""); \
+ const char *Subclass::id() const { return #Subclass; }
+
+/// Calls prepare() on all tweaks, returning those that can run on the
+/// selection.
+std::vector<std::unique_ptr<Tweak>> prepareTweaks(const Tweak::Selection &S);
+
+// Calls prepare() on the tweak with a given ID.
+// If prepare() returns false, returns an error.
+// If prepare() returns true, returns the corresponding tweak.
+llvm::Expected<std::unique_ptr<Tweak>> prepareTweak(StringRef TweakID,
+ const Tweak::Selection &S);
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/clangd/refactor/tweaks/CMakeLists.txt b/clangd/refactor/tweaks/CMakeLists.txt
new file mode 100644
index 00000000..35528d87
--- /dev/null
+++ b/clangd/refactor/tweaks/CMakeLists.txt
@@ -0,0 +1,21 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../..)
+
+set(LLVM_LINK_COMPONENTS
+ support
+ )
+
+# A target containing all code tweaks (i.e. mini-refactorings) provided by
+# clangd.
+# Built as an object library to make sure the linker does not remove global
+# constructors that register individual tweaks in a global registry.
+# To enable these tweaks in executables or shared libraries, add
+# $<TARGET_OBJECTS:obj.clangDaemonTweaks> to a list of sources, see
+# clangd/tool/CMakeLists.txt for an example.
+add_clang_library(clangDaemonTweaks OBJECT
+ SwapIfBranches.cpp
+
+ LINK_LIBS
+ clangAST
+ clangDaemon
+ clangToolingCore
+ )
diff --git a/clangd/refactor/tweaks/SwapIfBranches.cpp b/clangd/refactor/tweaks/SwapIfBranches.cpp
new file mode 100644
index 00000000..9b0b72d9
--- /dev/null
+++ b/clangd/refactor/tweaks/SwapIfBranches.cpp
@@ -0,0 +1,99 @@
+//===--- SwapIfBranches.cpp --------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "ClangdUnit.h"
+#include "Logger.h"
+#include "SourceCode.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+/// Swaps the 'then' and 'else' branch of the if statement.
+/// Before:
+/// if (foo) { return 10; } else { continue; }
+/// ^^^^^^^ ^^^^
+/// After:
+/// if (foo) { continue; } else { return 10; }
+class SwapIfBranches : public Tweak {
+public:
+ const char *id() const override final;
+
+ bool prepare(const Selection &Inputs) override;
+ Expected<tooling::Replacements> apply(const Selection &Inputs) override;
+ std::string title() const override;
+
+private:
+ const IfStmt *If = nullptr;
+};
+
+REGISTER_TWEAK(SwapIfBranches)
+
+bool SwapIfBranches::prepare(const Selection &Inputs) {
+ for (const SelectionTree::Node *N = Inputs.ASTSelection.commonAncestor();
+ N && !If; N = N->Parent) {
+ // Stop once we hit a block, e.g. a lambda in the if condition.
+ if (dyn_cast_or_null<CompoundStmt>(N->ASTNode.get<Stmt>()))
+ return false;
+ If = dyn_cast_or_null<IfStmt>(N->ASTNode.get<Stmt>());
+ }
+ // avoid dealing with single-statement brances, they require careful handling
+ // to avoid changing semantics of the code (i.e. dangling else).
+ return If && dyn_cast_or_null<CompoundStmt>(If->getThen()) &&
+ dyn_cast_or_null<CompoundStmt>(If->getElse());
+}
+
+Expected<tooling::Replacements> SwapIfBranches::apply(const Selection &Inputs) {
+ auto &Ctx = Inputs.AST.getASTContext();
+ auto &SrcMgr = Ctx.getSourceManager();
+
+ auto ThenRng = toHalfOpenFileRange(SrcMgr, Ctx.getLangOpts(),
+ If->getThen()->getSourceRange());
+ if (!ThenRng)
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Could not obtain range of the 'then' branch. Macros?");
+ auto ElseRng = toHalfOpenFileRange(SrcMgr, Ctx.getLangOpts(),
+ If->getElse()->getSourceRange());
+ if (!ElseRng)
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Could not obtain range of the 'else' branch. Macros?");
+
+ auto ThenCode = toSourceCode(SrcMgr, *ThenRng);
+ auto ElseCode = toSourceCode(SrcMgr, *ElseRng);
+
+ tooling::Replacements Result;
+ if (auto Err = Result.add(tooling::Replacement(Ctx.getSourceManager(),
+ ThenRng->getBegin(),
+ ThenCode.size(), ElseCode)))
+ return std::move(Err);
+ if (auto Err = Result.add(tooling::Replacement(Ctx.getSourceManager(),
+ ElseRng->getBegin(),
+ ElseCode.size(), ThenCode)))
+ return std::move(Err);
+ return Result;
+}
+
+std::string SwapIfBranches::title() const { return "Swap if branches"; }
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/clangd/test/CMakeLists.txt b/clangd/test/CMakeLists.txt
new file mode 100644
index 00000000..bbb582f1
--- /dev/null
+++ b/clangd/test/CMakeLists.txt
@@ -0,0 +1,36 @@
+# Set CLANG_TOOLS_DIR to buildtree/bin, or buildtree/%(build_mode)s/bin if the
+# location is dynamic. The latter must be interpolated by lit configs.
+# FIXME: this is duplicated in many places.
+if (CMAKE_CFG_INTDIR STREQUAL ".")
+ set(LLVM_BUILD_MODE ".")
+else ()
+ set(LLVM_BUILD_MODE "%(build_mode)s")
+endif ()
+string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} CLANG_TOOLS_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR})
+
+set(CLANGD_TEST_DEPS
+ clangd
+ ClangdTests
+ # No tests for these, but we should still make sure they build.
+ clangd-indexer
+ dexp
+ )
+
+if(CLANGD_BUILD_XPC)
+ list(APPEND CLANGD_TEST_DEPS clangd-xpc-test-client)
+ list(APPEND CLANGD_TEST_DEPS ClangdXpcUnitTests)
+endif()
+
+foreach(dep FileCheck count not)
+ if(TARGET ${dep})
+ list(APPEND CLANGD_TEST_DEPS ${dep})
+ endif()
+endforeach()
+
+configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py)
+
+add_lit_testsuite(check-clangd "Running the Clangd regression tests"
+ ${CMAKE_CURRENT_BINARY_DIR}/../unittests;${CMAKE_CURRENT_BINARY_DIR}
+ DEPENDS ${CLANGD_TEST_DEPS})
diff --git a/test/clangd/Inputs/BenchmarkHeader.h b/clangd/test/Inputs/BenchmarkHeader.h
index 3b7620ad..3b7620ad 100644
--- a/test/clangd/Inputs/BenchmarkHeader.h
+++ b/clangd/test/Inputs/BenchmarkHeader.h
diff --git a/test/clangd/Inputs/BenchmarkSource.cpp b/clangd/test/Inputs/BenchmarkSource.cpp
index 1924df9a..1924df9a 100644
--- a/test/clangd/Inputs/BenchmarkSource.cpp
+++ b/clangd/test/Inputs/BenchmarkSource.cpp
diff --git a/test/clangd/Inputs/background-index/compile_commands.json b/clangd/test/Inputs/background-index/compile_commands.json
index 1bb835f6..1bb835f6 100644
--- a/test/clangd/Inputs/background-index/compile_commands.json
+++ b/clangd/test/Inputs/background-index/compile_commands.json
diff --git a/test/clangd/Inputs/background-index/definition.jsonrpc b/clangd/test/Inputs/background-index/definition.jsonrpc
index 89d50482..933e7791 100644
--- a/test/clangd/Inputs/background-index/definition.jsonrpc
+++ b/clangd/test/Inputs/background-index/definition.jsonrpc
@@ -44,7 +44,7 @@
}
}
}
-# CHECK: "uri": "file://DIRECTORY/foo.cpp"
+# CHECK: "uri": "file://{{.*}}/foo.cpp"
---
{"jsonrpc":"2.0","id":3,"method":"shutdown"}
---
diff --git a/test/clangd/Inputs/background-index/foo.cpp b/clangd/test/Inputs/background-index/foo.cpp
index c42ca4d0..c42ca4d0 100644
--- a/test/clangd/Inputs/background-index/foo.cpp
+++ b/clangd/test/Inputs/background-index/foo.cpp
diff --git a/test/clangd/Inputs/background-index/foo.h b/clangd/test/Inputs/background-index/foo.h
index 9539f1d7..9539f1d7 100644
--- a/test/clangd/Inputs/background-index/foo.h
+++ b/clangd/test/Inputs/background-index/foo.h
diff --git a/test/clangd/Inputs/requests.json b/clangd/test/Inputs/requests.json
index ee91cf24..ee91cf24 100644
--- a/test/clangd/Inputs/requests.json
+++ b/clangd/test/Inputs/requests.json
diff --git a/test/clangd/Inputs/symbols.test.yaml b/clangd/test/Inputs/symbols.test.yaml
index 40068e36..40068e36 100644
--- a/test/clangd/Inputs/symbols.test.yaml
+++ b/clangd/test/Inputs/symbols.test.yaml
diff --git a/test/clangd/background-index.test b/clangd/test/background-index.test
index 34c419ac..1d11736d 100644
--- a/test/clangd/background-index.test
+++ b/clangd/test/background-index.test
@@ -13,7 +13,7 @@
# RUN: clangd -background-index -background-index-rebuild-period=0 -lit-test < %t/definition.jsonrpc | FileCheck %t/definition.jsonrpc
# Test that the index is writing files in the expected location.
-# RUN: ls %t/.clangd-index/foo.cpp.*.idx
+# RUN: ls %t/.clangd/index/foo.cpp.*.idx
# Test the index is read from disk: delete code and restart clangd.
# RUN: rm %t/foo.cpp
diff --git a/test/clangd/compile-commands-path-in-initialize.test b/clangd/test/compile-commands-path-in-initialize.test
index 87086e3c..2905bad4 100644
--- a/test/clangd/compile-commands-path-in-initialize.test
+++ b/clangd/test/compile-commands-path-in-initialize.test
@@ -21,6 +21,7 @@
# CHECK-NEXT: "params": {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
+# CHECK-NEXT: "code": "-W#pragma-messages",
# CHECK-NEXT: "message": "MACRO is one",
---
{"jsonrpc":"2.0","id":10000,"method":"shutdown"}
diff --git a/test/clangd/completion-auto-trigger.test b/clangd/test/completion-auto-trigger.test
index db3cc537..96830285 100644
--- a/test/clangd/completion-auto-trigger.test
+++ b/clangd/test/completion-auto-trigger.test
@@ -23,7 +23,7 @@
# CHECK-NEXT: "insertTextFormat": 1,
# CHECK-NEXT: "kind": 5,
# CHECK-NEXT: "label": " size",
-# CHECK-NEXT: "sortText": "3eacccccsize",
+# CHECK-NEXT: "sortText": "{{.*}}size",
# CHECK-NEXT: "textEdit": {
# CHECK-NEXT: "newText": "size",
# CHECK-NEXT: "range": {
@@ -45,7 +45,7 @@
# CHECK-NEXT: "insertTextFormat": 1,
# CHECK-NEXT: "kind": 10,
# CHECK-NEXT: "label": " default_capacity",
-# CHECK-NEXT: "sortText": "3fd70a3ddefault_capacity",
+# CHECK-NEXT: "sortText": "{{.*}}default_capacity",
# CHECK-NEXT: "textEdit": {
# CHECK-NEXT: "newText": "default_capacity",
# CHECK-NEXT: "range": {
@@ -84,7 +84,7 @@
# CHECK-NEXT: "insertTextFormat": 1,
# CHECK-NEXT: "kind": 6,
# CHECK-NEXT: "label": " ns_member",
-# CHECK-NEXT: "sortText": "3f2cccccns_member",
+# CHECK-NEXT: "sortText": "{{.*}}ns_member",
# CHECK-NEXT: "textEdit": {
# CHECK-NEXT: "newText": "ns_member",
# CHECK-NEXT: "range": {
diff --git a/test/clangd/completion-snippets.test b/clangd/test/completion-snippets.test
index 22cd0821..22cd0821 100644
--- a/test/clangd/completion-snippets.test
+++ b/clangd/test/completion-snippets.test
diff --git a/test/clangd/completion.test b/clangd/test/completion.test
index 0094d474..0094d474 100644
--- a/test/clangd/completion.test
+++ b/clangd/test/completion.test
diff --git a/test/clangd/crash-non-added-files.test b/clangd/test/crash-non-added-files.test
index d86f7d26..d86f7d26 100644
--- a/test/clangd/crash-non-added-files.test
+++ b/clangd/test/crash-non-added-files.test
diff --git a/test/clangd/delimited-input-comment-at-the-end.test b/clangd/test/delimited-input-comment-at-the-end.test
index 34a248df..34a248df 100644
--- a/test/clangd/delimited-input-comment-at-the-end.test
+++ b/clangd/test/delimited-input-comment-at-the-end.test
diff --git a/test/clangd/diagnostic-category.test b/clangd/test/diagnostic-category.test
index 440afbb1..39467746 100644
--- a/test/clangd/diagnostic-category.test
+++ b/clangd/test/diagnostic-category.test
@@ -7,7 +7,8 @@
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
# CHECK-NEXT: "category": "Semantic Issue",
-# CHECK-NEXT: "message": "Use of 'Point' with tag type that does not match previous declaration\n\nfoo.c:1:8: note: previous use is here",
+# CHECK-NEXT: "code": "use_with_wrong_tag",
+# CHECK-NEXT: "message": "Use of 'Point' with tag type that does not match previous declaration (fix available)\n\nfoo.c:1:8: note: previous use is here",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 22,
@@ -18,7 +19,8 @@
# CHECK-NEXT: "line": 0
# CHECK-NEXT: }
# CHECK-NEXT: },
-# CHECK-NEXT: "severity": 1
+# CHECK-NEXT: "severity": 1,
+# CHECK-NEXT: "source": "clang"
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "message": "Previous use is here\n\nfoo.c:1:18: error: use of 'Point' with tag type that does not match previous declaration",
diff --git a/clangd/test/diagnostics-notes.test b/clangd/test/diagnostics-notes.test
new file mode 100644
index 00000000..c04c5cf0
--- /dev/null
+++ b/clangd/test/diagnostics-notes.test
@@ -0,0 +1,48 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"textDocument":{"publishDiagnostics":{"relatedInformation":true}}},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.cc","languageId":"cpp","version":1,"text":"int x;\nint x;"}}}
+# CHECK: "method": "textDocument/publishDiagnostics",
+# CHECK-NEXT: "params": {
+# CHECK-NEXT: "diagnostics": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "code": "redefinition",
+# CHECK-NEXT: "message": "Redefinition of 'x'",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 5,
+# CHECK-NEXT: "line": 1
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 4,
+# CHECK-NEXT: "line": 1
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "relatedInformation": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "location": {
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 5,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 4,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "uri": "{{.*}}foo.cc"
+# CHECK-NEXT: },
+# CHECK-NEXT: "message": "Previous definition is here"
+# CHECK-NEXT: }
+# CHECK-NEXT: ],
+# CHECK-NEXT: "severity": 1,
+# CHECK-NEXT: "source": "clang"
+# CHECK-NEXT: }
+# CHECK-NEXT: ],
+# CHECK-NEXT: "uri": "file://{{.*}}/foo.cc"
+# CHECK-NEXT: }
+---
+{"jsonrpc":"2.0","id":5,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/clangd/test/diagnostics.test b/clangd/test/diagnostics.test
new file mode 100644
index 00000000..accfd17e
--- /dev/null
+++ b/clangd/test/diagnostics.test
@@ -0,0 +1,55 @@
+# RUN: clangd -lit-test -clang-tidy-checks=bugprone-sizeof-expression < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","version":1,"text":"void main() {\n(void)sizeof(42);\n}"}}}
+# CHECK: "method": "textDocument/publishDiagnostics",
+# CHECK-NEXT: "params": {
+# CHECK-NEXT: "diagnostics": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "code": "-Wmain-return-type",
+# CHECK-NEXT: "message": "Return type of 'main' is not 'int' (fix available)",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 4,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 0,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "severity": 2,
+# CHECK-NEXT: "source": "clang"
+# CHECK-NEXT: },
+# CHECK-NEXT: {
+# CHECK-NEXT: "code": "bugprone-sizeof-expression",
+# CHECK-NEXT: "message": "Suspicious usage of 'sizeof(K)'; did you mean 'K'?",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 12,
+# CHECK-NEXT: "line": 1
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 6,
+# CHECK-NEXT: "line": 1
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "severity": 2,
+# CHECK-NEXT: "source": "clang-tidy"
+# CHECK-NEXT: }
+# CHECK-NEXT: ],
+# CHECK-NEXT: "uri": "file://{{.*}}/foo.c"
+# CHECK-NEXT: }
+---
+{"jsonrpc":"2.0","id":2,"method":"sync","params":null}
+---
+{"jsonrpc":"2.0","method":"textDocument/didClose","params":{"textDocument":{"uri":"test:///foo.c"}}}
+# CHECK: "method": "textDocument/publishDiagnostics",
+# CHECK-NEXT: "params": {
+# CHECK-NEXT: "diagnostics": [],
+# CHECK-NEXT: "uri": "file://{{.*}}/foo.c"
+# CHECK-NEXT: }
+---
+{"jsonrpc":"2.0","id":5,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/test/clangd/did-change-configuration-params.test b/clangd/test/did-change-configuration-params.test
index 51b4a874..bd8ffafc 100644
--- a/test/clangd/did-change-configuration-params.test
+++ b/clangd/test/did-change-configuration-params.test
@@ -24,7 +24,8 @@
# CHECK-NEXT: "params": {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
-# CHECK-NEXT: "message": "Variable 'i' is uninitialized when used here",
+# CHECK-NEXT: "code": "-Wuninitialized",
+# CHECK-NEXT: "message": "Variable 'i' is uninitialized when used here (fix available)",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 28,
@@ -35,13 +36,16 @@
# CHECK-NEXT: "line": 0
# CHECK-NEXT: }
# CHECK-NEXT: },
-# CHECK-NEXT: "severity": 1
+# CHECK-NEXT: "severity": 1,
+# CHECK-NEXT: "source": "clang"
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "uri": "file://{{.*}}/foo.c"
# CHECK-NEXT: }
#
-# ERR: Updating file {{.*}}foo.c with command [{{.*}}clangd-test2] clang -c foo.c -Wall -Werror
+# ERR: Updating file {{.*}}foo.c with command
+# ERR: [{{.*}}clangd-test2]
+# ERR: clang -c foo.c -Wall -Werror
# Don't reparse the second file:
# ERR: Skipping rebuild of the AST for {{.*}}bar.c
---
diff --git a/test/clangd/execute-command.test b/clangd/test/execute-command.test
index 85d4b9b8..7abd79e5 100644
--- a/test/clangd/execute-command.test
+++ b/clangd/test/execute-command.test
@@ -6,7 +6,8 @@
# CHECK-NEXT: "params": {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
-# CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses",
+# CHECK-NEXT: "code": "-Wparentheses",
+# CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses (fixes available)",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 37,
@@ -17,7 +18,8 @@
# CHECK-NEXT: "line": 0
# CHECK-NEXT: }
# CHECK-NEXT: },
-# CHECK-NEXT: "severity": 2
+# CHECK-NEXT: "severity": 2,
+# CHECK-NEXT: "source": "clang"
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "uri": "file://{{.*}}/foo.c"
diff --git a/test/clangd/exit-with-shutdown.test b/clangd/test/exit-with-shutdown.test
index 99e412c7..99e412c7 100644
--- a/test/clangd/exit-with-shutdown.test
+++ b/clangd/test/exit-with-shutdown.test
diff --git a/test/clangd/exit-without-shutdown.test b/clangd/test/exit-without-shutdown.test
index 7b22d059..7b22d059 100644
--- a/test/clangd/exit-without-shutdown.test
+++ b/clangd/test/exit-without-shutdown.test
diff --git a/test/clangd/filestatus.test b/clangd/test/filestatus.test
index c485939b..c485939b 100644
--- a/test/clangd/filestatus.test
+++ b/clangd/test/filestatus.test
diff --git a/test/clangd/fixits-codeaction.test b/clangd/test/fixits-codeaction.test
index 97dd4ff2..e9190711 100644
--- a/test/clangd/fixits-codeaction.test
+++ b/clangd/test/fixits-codeaction.test
@@ -6,7 +6,8 @@
# CHECK-NEXT: "params": {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
-# CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses",
+# CHECK-NEXT: "code": "-Wparentheses",
+# CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses (fixes available)",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 37,
@@ -17,20 +18,22 @@
# CHECK-NEXT: "line": 0
# CHECK-NEXT: }
# CHECK-NEXT: },
-# CHECK-NEXT: "severity": 2
+# CHECK-NEXT: "severity": 2,
+# CHECK-NEXT: "source": "clang"
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "uri": "file://{{.*}}/foo.c"
# CHECK-NEXT: }
---
-{"jsonrpc":"2.0","id":2,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"test:///foo.c"},"range":{"start":{"line":104,"character":13},"end":{"line":0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 37}},"severity":2,"message":"Using the result of an assignment as a condition without parentheses"}]}}}
+{"jsonrpc":"2.0","id":2,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"test:///foo.c"},"range":{"start":{"line":0,"character":13},"end":{"line":0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 37}},"severity":2,"message":"Using the result of an assignment as a condition without parentheses (fixes available)", "code": "-Wparentheses", "source": "clang"}]}}}
# CHECK: "id": 2,
# CHECK-NEXT: "jsonrpc": "2.0",
# CHECK-NEXT: "result": [
# CHECK-NEXT: {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
-# CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses",
+# CHECK-NEXT: "code": "-Wparentheses",
+# CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses (fixes available)",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 37,
@@ -41,7 +44,8 @@
# CHECK-NEXT: "line": 0
# CHECK-NEXT: }
# CHECK-NEXT: },
-# CHECK-NEXT: "severity": 2
+# CHECK-NEXT: "severity": 2,
+# CHECK-NEXT: "source": "clang"
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "edit": {
@@ -82,7 +86,8 @@
# CHECK-NEXT: {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
-# CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses",
+# CHECK-NEXT: "code": "-Wparentheses",
+# CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses (fixes available)",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 37,
@@ -93,7 +98,8 @@
# CHECK-NEXT: "line": 0
# CHECK-NEXT: }
# CHECK-NEXT: },
-# CHECK-NEXT: "severity": 2
+# CHECK-NEXT: "severity": 2,
+# CHECK-NEXT: "source": "clang"
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "edit": {
diff --git a/test/clangd/fixits-command.test b/clangd/test/fixits-command.test
index 67f70dbe..9d43e701 100644
--- a/test/clangd/fixits-command.test
+++ b/clangd/test/fixits-command.test
@@ -6,7 +6,8 @@
# CHECK-NEXT: "params": {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
-# CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses",
+# CHECK-NEXT: "code": "-Wparentheses",
+# CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses (fixes available)",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 37,
@@ -17,13 +18,14 @@
# CHECK-NEXT: "line": 0
# CHECK-NEXT: }
# CHECK-NEXT: },
-# CHECK-NEXT: "severity": 2
+# CHECK-NEXT: "severity": 2,
+# CHECK-NEXT: "source": "clang"
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "uri": "file://{{.*}}/foo.c"
# CHECK-NEXT: }
---
-{"jsonrpc":"2.0","id":2,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"test:///foo.c"},"range":{"start":{"line":104,"character":13},"end":{"line":0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 37}},"severity":2,"message":"Using the result of an assignment as a condition without parentheses"}]}}}
+{"jsonrpc":"2.0","id":2,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"test:///foo.c"},"range":{"start":{"line":0,"character":13},"end":{"line":0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 37}},"severity":2,"message":"Using the result of an assignment as a condition without parentheses (fixes available)"}]}}}
# CHECK: "id": 2,
# CHECK-NEXT: "jsonrpc": "2.0",
# CHECK-NEXT: "result": [
@@ -92,7 +94,7 @@
# CHECK-NEXT: }
# CHECK-NEXT: ]
---
-{"jsonrpc":"2.0","id":3,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"test:///foo.c"},"range":{"start":{"line":104,"character":13},"end":{"line":0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 37}},"severity":2,"message":"Using the result of an assignment as a condition without parentheses"}]}}}
+{"jsonrpc":"2.0","id":3,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"test:///foo.c"},"range":{"start":{"line":0,"character":13},"end":{"line":0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 37}},"severity":2,"message":"Using the result of an assignment as a condition without parentheses (fixes available)"}]}}}
# Make sure unused "code" and "source" fields ignored gracefully
# CHECK: "id": 3,
# CHECK-NEXT: "jsonrpc": "2.0",
diff --git a/test/clangd/fixits-embed-in-diagnostic.test b/clangd/test/fixits-embed-in-diagnostic.test
index f1aa1cfe..7d2cccdb 100644
--- a/test/clangd/fixits-embed-in-diagnostic.test
+++ b/clangd/test/fixits-embed-in-diagnostic.test
@@ -6,6 +6,7 @@
# CHECK-NEXT: "params": {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
+# CHECK-NEXT: "code": "use_with_wrong_tag",
# CHECK-NEXT: "codeActions": [
# CHECK-NEXT: {
# CHECK-NEXT: "edit": {
@@ -31,7 +32,7 @@
# CHECK-NEXT: "title": "change 'union' to 'struct'"
# CHECK-NEXT: }
# CHECK-NEXT: ],
-# CHECK-NEXT: "message": "Use of 'Point' with tag type that does not match previous declaration\n\nfoo.c:1:8: note: previous use is here",
+# CHECK-NEXT: "message": "Use of 'Point' with tag type that does not match previous declaration (fix available)\n\nfoo.c:1:8: note: previous use is here",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 22,
@@ -42,7 +43,8 @@
# CHECK-NEXT: "line": 0
# CHECK-NEXT: }
# CHECK-NEXT: },
-# CHECK-NEXT: "severity": 1
+# CHECK-NEXT: "severity": 1,
+# CHECK-NEXT: "source": "clang"
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "message": "Previous use is here\n\nfoo.c:1:18: error: use of 'Point' with tag type that does not match previous declaration",
diff --git a/test/clangd/formatting.test b/clangd/test/formatting.test
index 9f8f3db9..9f8f3db9 100644
--- a/test/clangd/formatting.test
+++ b/clangd/test/formatting.test
diff --git a/test/clangd/hover.test b/clangd/test/hover.test
index 8f1ead05..8f1ead05 100644
--- a/test/clangd/hover.test
+++ b/clangd/test/hover.test
diff --git a/test/clangd/index-tools.test b/clangd/test/index-tools.test
index 93cf56fe..93cf56fe 100644
--- a/test/clangd/index-tools.test
+++ b/clangd/test/index-tools.test
diff --git a/test/clangd/initialize-params-invalid.test b/clangd/test/initialize-params-invalid.test
index f51a7279..f51a7279 100644
--- a/test/clangd/initialize-params-invalid.test
+++ b/clangd/test/initialize-params-invalid.test
diff --git a/test/clangd/initialize-params.test b/clangd/test/initialize-params.test
index 62f7b41a..488539d4 100644
--- a/test/clangd/initialize-params.test
+++ b/clangd/test/initialize-params.test
@@ -14,6 +14,7 @@
# CHECK-NEXT: ":"
# CHECK-NEXT: ]
# CHECK-NEXT: },
+# CHECK-NEXT: "declarationProvider": true,
# CHECK-NEXT: "definitionProvider": true,
# CHECK-NEXT: "documentFormattingProvider": true,
# CHECK-NEXT: "documentHighlightProvider": true,
@@ -25,7 +26,8 @@
# CHECK-NEXT: "documentSymbolProvider": true,
# CHECK-NEXT: "executeCommandProvider": {
# CHECK-NEXT: "commands": [
-# CHECK-NEXT: "clangd.applyFix"
+# CHECK-NEXT: "clangd.applyFix",
+# CHECK-NEXT: "clangd.applyTweak"
# CHECK-NEXT: ]
# CHECK-NEXT: },
# CHECK-NEXT: "hoverProvider": true,
@@ -38,6 +40,7 @@
# CHECK-NEXT: ]
# CHECK-NEXT: },
# CHECK-NEXT: "textDocumentSync": 2,
+# CHECK-NEXT: "typeHierarchyProvider": true
# CHECK-NEXT: "workspaceSymbolProvider": true
# CHECK-NEXT: }
# CHECK-NEXT: }
diff --git a/test/clangd/initialize-sequence.test b/clangd/test/initialize-sequence.test
index d1b82470..d1b82470 100644
--- a/test/clangd/initialize-sequence.test
+++ b/clangd/test/initialize-sequence.test
diff --git a/test/clangd/input-mirror.test b/clangd/test/input-mirror.test
index 52845621..52845621 100644
--- a/test/clangd/input-mirror.test
+++ b/clangd/test/input-mirror.test
diff --git a/clangd/test/lit.cfg.py b/clangd/test/lit.cfg.py
new file mode 100644
index 00000000..5030ca35
--- /dev/null
+++ b/clangd/test/lit.cfg.py
@@ -0,0 +1,19 @@
+import lit.llvm
+
+lit.llvm.initialize(lit_config, config)
+lit.llvm.llvm_config.use_clang()
+
+config.name = 'Clangd'
+config.suffixes = ['.test']
+config.excludes = ['Inputs']
+config.test_format = lit.formats.ShTest(not lit.llvm.llvm_config.use_lit_shell)
+config.test_source_root = config.clangd_source_dir + "/test"
+config.test_exec_root = config.clangd_binary_dir + "/test"
+
+# Clangd-specific lit environment.
+config.substitutions.append(('%clangd-benchmark-dir',
+ config.clangd_binary_dir + "/benchmarks"))
+
+if config.clangd_build_xpc:
+ config.available_features.add('clangd-xpc-support')
+
diff --git a/test/clangd/lit.local.cfg b/clangd/test/lit.local.cfg
index ef338c75..ef338c75 100644
--- a/test/clangd/lit.local.cfg
+++ b/clangd/test/lit.local.cfg
diff --git a/clangd/test/lit.site.cfg.py.in b/clangd/test/lit.site.cfg.py.in
new file mode 100644
index 00000000..0a8301f3
--- /dev/null
+++ b/clangd/test/lit.site.cfg.py.in
@@ -0,0 +1,28 @@
+@LIT_SITE_CFG_IN_HEADER@
+
+# Variables needed for common clang config.
+config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
+config.clang_tools_dir = "@CLANG_TOOLS_DIR@"
+config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
+config.clang_libs_dir = "@CLANG_LIBS_DIR@"
+config.llvm_libs_dir = "@LLVM_LIBS_DIR@"
+config.target_triple = "@TARGET_TRIPLE@"
+config.host_triple = "@LLVM_HOST_TRIPLE@"
+
+# Support substitution of the tools and libs dirs with user parameters. This is
+# used when we can't determine the tool dir at configuration time.
+try:
+ config.clang_tools_dir = config.clang_tools_dir % lit_config.params
+ config.llvm_tools_dir = config.llvm_tools_dir % lit_config.params
+ config.llvm_libs_dir = config.llvm_libs_dir % lit_config.params
+except KeyError:
+ e = sys.exc_info()[1]
+ key, = e.args
+ lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key))
+
+config.clangd_source_dir = "@CMAKE_CURRENT_SOURCE_DIR@/.."
+config.clangd_binary_dir = "@CMAKE_CURRENT_BINARY_DIR@/.."
+config.clangd_build_xpc = @CLANGD_BUILD_XPC@
+
+# Delegate logic to lit.cfg.py.
+lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg.py")
diff --git a/test/clangd/protocol.test b/clangd/test/protocol.test
index c218763d..c218763d 100644
--- a/test/clangd/protocol.test
+++ b/clangd/test/protocol.test
diff --git a/test/clangd/references.test b/clangd/test/references.test
index 964f5e7f..964f5e7f 100644
--- a/test/clangd/references.test
+++ b/clangd/test/references.test
diff --git a/test/clangd/rename.test b/clangd/test/rename.test
index caf8b200..7c504bd1 100644
--- a/test/clangd/rename.test
+++ b/clangd/test/rename.test
@@ -29,7 +29,7 @@
{"jsonrpc":"2.0","id":2,"method":"textDocument/rename","params":{"textDocument":{"uri":"test:///foo.cpp"},"position":{"line":0,"character":2},"newName":"bar"}}
# CHECK: "error": {
# CHECK-NEXT: "code": -32001,
-# CHECK-NEXT: "message": "clang diagnostic"
+# CHECK-NEXT: "message": "there is no symbol at the given location"
# CHECK-NEXT: },
# CHECK-NEXT: "id": 2,
# CHECK-NEXT: "jsonrpc": "2.0"
diff --git a/test/clangd/signature-help.test b/clangd/test/signature-help.test
index 37b8b500..37b8b500 100644
--- a/test/clangd/signature-help.test
+++ b/clangd/test/signature-help.test
diff --git a/test/clangd/spaces-in-delimited-input.test b/clangd/test/spaces-in-delimited-input.test
index 9636425e..9636425e 100644
--- a/test/clangd/spaces-in-delimited-input.test
+++ b/clangd/test/spaces-in-delimited-input.test
diff --git a/test/clangd/symbol-info.test b/clangd/test/symbol-info.test
index 65094a4b..65094a4b 100644
--- a/test/clangd/symbol-info.test
+++ b/clangd/test/symbol-info.test
diff --git a/test/clangd/symbols.test b/clangd/test/symbols.test
index a15d7028..a15d7028 100644
--- a/test/clangd/symbols.test
+++ b/clangd/test/symbols.test
diff --git a/test/clangd/test-uri-posix.test b/clangd/test/test-uri-posix.test
index 2b67fa03..2b67fa03 100644
--- a/test/clangd/test-uri-posix.test
+++ b/clangd/test/test-uri-posix.test
diff --git a/test/clangd/test-uri-windows.test b/clangd/test/test-uri-windows.test
index 381c48fa..381c48fa 100644
--- a/test/clangd/test-uri-windows.test
+++ b/clangd/test/test-uri-windows.test
diff --git a/test/clangd/textdocument-didchange-fail.test b/clangd/test/textdocument-didchange-fail.test
index 33350c4a..33350c4a 100644
--- a/test/clangd/textdocument-didchange-fail.test
+++ b/clangd/test/textdocument-didchange-fail.test
diff --git a/test/clangd/too_large.test b/clangd/test/too_large.test
index 7b846c37..7b846c37 100644
--- a/test/clangd/too_large.test
+++ b/clangd/test/too_large.test
diff --git a/test/clangd/trace.test b/clangd/test/trace.test
index 83b040a5..cb6a226b 100644
--- a/test/clangd/trace.test
+++ b/clangd/test/trace.test
@@ -3,22 +3,25 @@
---
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","version":1,"text":"void main() {}"}}}
# These assertions are a bit loose, to avoid brittleness.
-# CHECK: {"displayTimeUnit":"ns","traceEvents":[
# CHECK: {
-# CHECK: "args": {
-# CHECK: "File": "{{.*(/|\\)}}foo.c"
-# CHECK: },
-# CHECK: "name": "BuildPreamble",
-# CHECK: "ph": "X",
+# CHECK: "displayTimeUnit": "ns",
+# CHECK: "traceEvents": [
+# CHECK: {
+# CHECK: "ph": "X",
+# CHECK: "name": "BuildPreamble",
+# CHECK: "args": {
+# CHECK: "File": "{{.*(/|\\)}}foo.c"
+# CHECK: },
+# CHECK: }
+# CHECK: {
+# CHECK: "ph": "X",
+# CHECK: "name": "BuildAST",
+# CHECK: "args": {
+# CHECK: "File": "{{.*(/|\\)}}foo.c"
+# CHECK: },
+# CHECK: }
+# CHECK: ]
# CHECK: }
-# CHECK: {
-# CHECK: "args": {
-# CHECK: "File": "{{.*(/|\\)}}foo.c"
-# CHECK: },
-# CHECK: "name": "BuildAST",
-# CHECK: "ph": "X",
-# CHECK: }
-# CHECK: },
---
{"jsonrpc":"2.0","id":5,"method":"shutdown"}
---
diff --git a/clangd/test/tweaks-format.test b/clangd/test/tweaks-format.test
new file mode 100644
index 00000000..8fe7a112
--- /dev/null
+++ b/clangd/test/tweaks-format.test
@@ -0,0 +1,50 @@
+# RUN: clangd -lit-test < %s | FileCheck %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cc","languageId":"cpp","version":1,"text":"int f() { if (true) { return 1; } else {} }"}}}
+---
+{"jsonrpc":"2.0","id":5,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"test:///main.cc"},"range":{"start":{"line":0,"character":11},"end":{"line":0,"character":11}},"context":{"diagnostics":[]}}}
+---
+{"jsonrpc":"2.0","id":6,"method":"workspace/executeCommand","params":{"command":"clangd.applyTweak","arguments":[{"file":"test:///main.cc","selection":{"end":{"character":11,"line":0},"start":{"character":11,"line":0}},"tweakID":"SwapIfBranches"}]}}
+# CHECK: "newText": "\n ",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 10,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 9,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: {
+# CHECK-NEXT: "newText": "{\n }",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 33,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 20,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: {
+# CHECK-NEXT: "newText": "{\n return 1;\n }\n",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 42,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 39,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/clangd/test/type-hierarchy.test b/clangd/test/type-hierarchy.test
new file mode 100644
index 00000000..420f7fbf
--- /dev/null
+++ b/clangd/test/type-hierarchy.test
@@ -0,0 +1,92 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"struct Parent {};\nstruct Child1 : Parent {};\nstruct Child2 : Child1 {};"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/typeHierarchy","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":2,"character":11},"direction":1,"resolve":1}}
+# CHECK: "id": 1
+# CHECK-NEXT: "jsonrpc": "2.0",
+# CHECK-NEXT: "result": {
+# CHECK-NEXT: "kind": 23,
+# CHECK-NEXT: "name": "Child2",
+# CHECK-NEXT: "parents": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "kind": 23,
+# CHECK-NEXT: "name": "Child1",
+# CHECK-NEXT: "parents": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "kind": 23,
+# CHECK-NEXT: "name": "Parent",
+# CHECK-NEXT: "parents": [],
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 15,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 0,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "selectionRange": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 13,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 7,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "uri": "file:///clangd-test/main.cpp"
+# CHECK-NEXT: }
+# CHECK-NEXT: ],
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 24,
+# CHECK-NEXT: "line": 1
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 0,
+# CHECK-NEXT: "line": 1
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "selectionRange": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 13,
+# CHECK-NEXT: "line": 1
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 7,
+# CHECK-NEXT: "line": 1
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "uri": "file:///clangd-test/main.cpp"
+# CHECK-NEXT: }
+# CHECK-NEXT: ],
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 24,
+# CHECK-NEXT: "line": 2
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 0,
+# CHECK-NEXT: "line": 2
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "selectionRange": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 13,
+# CHECK-NEXT: "line": 2
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 7,
+# CHECK-NEXT: "line": 2
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "uri": "file:///clangd-test/main.cpp"
+# CHECK-NEXT: }
+---
+{"jsonrpc":"2.0","id":2,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/test/clangd/unsupported-method.test b/clangd/test/unsupported-method.test
index 9cdb12c3..9cdb12c3 100644
--- a/test/clangd/unsupported-method.test
+++ b/clangd/test/unsupported-method.test
diff --git a/clangd/test/utf8.test b/clangd/test/utf8.test
new file mode 100644
index 00000000..5a00c896
--- /dev/null
+++ b/clangd/test/utf8.test
@@ -0,0 +1,32 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+# This test verifies that we can negotiate UTF-8 offsets via protocol extension.
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"offsetEncoding":["utf-8","utf-16"]},"trace":"off"}}
+# CHECK: "offsetEncoding": "utf-8"
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"/*ö*/int x;\nint y=x;"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":1,"character":6}}}
+# /*ö*/int x;
+# 01234567890
+# x is character (and utf-16) range [9,10) but byte range [10,11).
+# CHECK: "id": 1,
+# CHECK-NEXT: "jsonrpc": "2.0",
+# CHECK-NEXT: "result": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 11,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 10,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "uri": "file://{{.*}}/main.cpp"
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+---
+{"jsonrpc":"2.0","id":10000,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/test/clangd/xpc/initialize.test b/clangd/test/xpc/initialize.test
index 44bef65b..44bef65b 100644
--- a/test/clangd/xpc/initialize.test
+++ b/clangd/test/xpc/initialize.test
diff --git a/test/clangd/xrefs.test b/clangd/test/xrefs.test
index 58ca44cb..128c97ff 100644
--- a/test/clangd/xrefs.test
+++ b/clangd/test/xrefs.test
@@ -1,9 +1,9 @@
# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
---
-{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"int x = 0;\nint y = x;"}}}
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"extern int x;\nint x = 0;\nint y = x;"}}}
---
-{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":1,"character":8}}}
+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":2,"character":8}}}
# CHECK: "id": 1,
# CHECK-NEXT: "jsonrpc": "2.0",
# CHECK-NEXT: "result": [
@@ -11,10 +11,30 @@
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 5,
-# CHECK-NEXT: "line": 0
+# CHECK-NEXT: "line": 1
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 4,
+# CHECK-NEXT: "line": 1
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "uri": "file://{{.*}}/{{([A-Z]:/)?}}main.cpp"
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+---
+# Toggle: we're on the definition, so jump to the declaration.
+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":1,"character":4}}}
+# CHECK: "id": 1,
+# CHECK-NEXT: "jsonrpc": "2.0",
+# CHECK-NEXT: "result": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 12,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 11,
# CHECK-NEXT: "line": 0
# CHECK-NEXT: }
# CHECK-NEXT: },
@@ -22,7 +42,7 @@
# CHECK-NEXT: }
# CHECK-NEXT: ]
---
-{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":1,"character":8}}}
+{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":2,"character":8}}}
# CHECK: "id": 1
# CHECK-NEXT: "jsonrpc": "2.0",
# CHECK-NEXT: "result": [
@@ -30,25 +50,38 @@
# CHECK-NEXT: "kind": 1,
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
-# CHECK-NEXT: "character": 5,
+# CHECK-NEXT: "character": 12,
# CHECK-NEXT: "line": 0
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
-# CHECK-NEXT: "character": 4,
+# CHECK-NEXT: "character": 11,
# CHECK-NEXT: "line": 0
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: },
# CHECK-NEXT: {
+# CHECK-NEXT: "kind": 1,
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 5,
+# CHECK-NEXT: "line": 1
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 4,
+# CHECK-NEXT: "line": 1
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: {
# CHECK-NEXT: "kind": 2,
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 9,
-# CHECK-NEXT: "line": 1
+# CHECK-NEXT: "line": 2
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 8,
-# CHECK-NEXT: "line": 1
+# CHECK-NEXT: "line": 2
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: }
diff --git a/clangd/tool/CMakeLists.txt b/clangd/tool/CMakeLists.txt
index 1ad2ca1b..93d7f145 100644
--- a/clangd/tool/CMakeLists.txt
+++ b/clangd/tool/CMakeLists.txt
@@ -3,6 +3,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}/..)
add_clang_tool(clangd
ClangdMain.cpp
+ $<TARGET_OBJECTS:obj.clangDaemonTweaks>
)
set(LLVM_LINK_COMPONENTS
@@ -16,7 +17,9 @@ endif()
target_link_libraries(clangd
PRIVATE
+ clangAST
clangBasic
+ clangTidy
clangDaemon
clangFormat
clangFrontend
diff --git a/clangd/tool/ClangdMain.cpp b/clangd/tool/ClangdMain.cpp
index 34e81d3b..b066283a 100644
--- a/clangd/tool/ClangdMain.cpp
+++ b/clangd/tool/ClangdMain.cpp
@@ -1,19 +1,23 @@
//===--- ClangdMain.cpp - clangd server loop ------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "Features.inc"
#include "ClangdLSPServer.h"
+#include "CodeComplete.h"
+#include "Features.inc"
#include "Path.h"
+#include "Protocol.h"
#include "Trace.h"
#include "Transport.h"
+#include "index/Background.h"
#include "index/Serialization.h"
#include "clang/Basic/Version.h"
+#include "clang/Format/Format.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -32,7 +36,7 @@ namespace clangd {
static llvm::cl::opt<bool>
UseDex("use-dex-index",
llvm::cl::desc("Use experimental Dex dynamic index."),
- llvm::cl::init(false), llvm::cl::Hidden);
+ llvm::cl::init(true), llvm::cl::Hidden);
static llvm::cl::opt<Path> CompileCommandsDir(
"compile-commands-dir",
@@ -91,7 +95,7 @@ static llvm::cl::opt<Logger::Level> LogLevel(
static llvm::cl::opt<bool>
Test("lit-test",
llvm::cl::desc("Abbreviation for -input-style=delimited -pretty "
- "-run-synchronously -enable-test-scheme. "
+ "-run-synchronously -enable-test-scheme -log=verbose. "
"Intended to simplify lit tests."),
llvm::cl::init(false), llvm::cl::Hidden);
@@ -153,6 +157,20 @@ static llvm::cl::opt<bool> ShowOrigins(
"debug-origin", llvm::cl::desc("Show origins of completion items"),
llvm::cl::init(CodeCompleteOptions().ShowOrigins), llvm::cl::Hidden);
+static llvm::cl::opt<CodeCompleteOptions::IncludeInsertion> HeaderInsertion(
+ "header-insertion",
+ llvm::cl::desc("Add #include directives when accepting code completions"),
+ llvm::cl::init(CodeCompleteOptions().InsertIncludes),
+ llvm::cl::values(
+ clEnumValN(CodeCompleteOptions::IWYU, "iwyu",
+ "Include what you use. "
+ "Insert the owning header for top-level symbols, unless the "
+ "header is already directly included or the symbol is "
+ "forward-declared."),
+ clEnumValN(
+ CodeCompleteOptions::NeverInsert, "never",
+ "Never insert #include directives as part of code completion")));
+
static llvm::cl::opt<bool> HeaderInsertionDecorators(
"header-insertion-decorators",
llvm::cl::desc("Prepend a circular dot or space before the completion "
@@ -164,7 +182,7 @@ static llvm::cl::opt<Path> IndexFile(
"index-file",
llvm::cl::desc(
"Index file to build the static index. The file must have been created "
- "by a compatible clangd-index.\n"
+ "by a compatible clangd-indexer.\n"
"WARNING: This option is experimental only, and will be removed "
"eventually. Don't rely on it."),
llvm::cl::init(""), llvm::cl::Hidden);
@@ -202,6 +220,48 @@ static llvm::cl::opt<bool> EnableFunctionArgSnippets(
"placeholders for method parameters."),
llvm::cl::init(CodeCompleteOptions().EnableFunctionArgSnippets));
+static llvm::cl::opt<std::string> ClangTidyChecks(
+ "clang-tidy-checks",
+ llvm::cl::desc(
+ "List of clang-tidy checks to run (this will override "
+ ".clang-tidy files). Only meaningful when -clang-tidy flag is on."),
+ llvm::cl::init(""));
+
+static llvm::cl::opt<bool> EnableClangTidy(
+ "clang-tidy",
+ llvm::cl::desc("Enable clang-tidy diagnostics."),
+ llvm::cl::init(true));
+
+static llvm::cl::opt<std::string>
+ FallbackStyle("fallback-style",
+ llvm::cl::desc("clang-format style to apply by default when "
+ "no .clang-format file is found"),
+ llvm::cl::init(clang::format::DefaultFallbackStyle));
+
+static llvm::cl::opt<bool> SuggestMissingIncludes(
+ "suggest-missing-includes",
+ llvm::cl::desc("Attempts to fix diagnostic errors caused by missing "
+ "includes using index."),
+ llvm::cl::init(true));
+
+static llvm::cl::opt<OffsetEncoding> ForceOffsetEncoding(
+ "offset-encoding",
+ llvm::cl::desc("Force the offsetEncoding used for character positions. "
+ "This bypasses negotiation via client capabilities."),
+ llvm::cl::values(clEnumValN(OffsetEncoding::UTF8, "utf-8",
+ "Offsets are in UTF-8 bytes"),
+ clEnumValN(OffsetEncoding::UTF16, "utf-16",
+ "Offsets are in UTF-16 code units")),
+ llvm::cl::init(OffsetEncoding::UnsupportedEncoding));
+
+static llvm::cl::opt<bool> AllowFallbackCompletion(
+ "allow-fallback-completion",
+ llvm::cl::desc(
+ "Allow falling back to code completion without compiling files (using "
+ "identifiers and symbol indexes), when file cannot be built or the "
+ "build is not ready."),
+ llvm::cl::init(false));
+
namespace {
/// \brief Supports a test URI scheme with relaxed constraints for lit tests.
@@ -278,8 +338,10 @@ int main(int argc, char *argv[]) {
if (Test) {
RunSynchronously = true;
InputStyle = JSONStreamStyle::Delimited;
+ LogLevel = Logger::Verbose;
PrettyPrint = true;
- preventThreadStarvationInTests(); // Ensure background index makes progress.
+ // Ensure background index makes progress.
+ BackgroundIndex::preventThreadStarvationInTests();
}
if (Test || EnableTestScheme) {
static URISchemeRegistry::Add<TestScheme> X(
@@ -297,6 +359,8 @@ int main(int argc, char *argv[]) {
llvm::errs() << "Ignoring -j because -run-synchronously is set.\n";
WorkerThreadsCount = 0;
}
+ if (FallbackStyle.getNumOccurrences())
+ clang::format::DefaultFallbackStyle = FallbackStyle.c_str();
// Validate command line arguments.
llvm::Optional<llvm::raw_fd_ostream> InputMirrorStream;
@@ -401,6 +465,7 @@ int main(int argc, char *argv[]) {
CCOpts.Limit = LimitResults;
CCOpts.BundleOverloads = CompletionStyle != Detailed;
CCOpts.ShowOrigins = ShowOrigins;
+ CCOpts.InsertIncludes = HeaderInsertion;
if (!HeaderInsertionDecorators) {
CCOpts.IncludeIndicator.Insert.clear();
CCOpts.IncludeIndicator.NoInsert.clear();
@@ -408,7 +473,9 @@ int main(int argc, char *argv[]) {
CCOpts.SpeculativeIndexRequest = Opts.StaticIndex;
CCOpts.EnableFunctionArgSnippets = EnableFunctionArgSnippets;
CCOpts.AllScopes = AllScopesCompletion;
+ CCOpts.AllowFallback = AllowFallbackCompletion;
+ RealFileSystemProvider FSProvider;
// Initialize and run ClangdLSPServer.
// Change stdin to binary to not lose \r\n on windows.
llvm::sys::ChangeStdinToBinary();
@@ -428,9 +495,25 @@ int main(int argc, char *argv[]) {
PrettyPrint, InputStyle);
}
+ // Create an empty clang-tidy option.
+ std::unique_ptr<tidy::ClangTidyOptionsProvider> ClangTidyOptProvider;
+ if (EnableClangTidy) {
+ auto OverrideClangTidyOptions = tidy::ClangTidyOptions::getDefaults();
+ OverrideClangTidyOptions.Checks = ClangTidyChecks;
+ ClangTidyOptProvider = llvm::make_unique<tidy::FileOptionsProvider>(
+ tidy::ClangTidyGlobalOptions(),
+ /* Default */ tidy::ClangTidyOptions::getDefaults(),
+ /* Override */ OverrideClangTidyOptions, FSProvider.getFileSystem());
+ }
+ Opts.ClangTidyOptProvider = ClangTidyOptProvider.get();
+ Opts.SuggestMissingIncludes = SuggestMissingIncludes;
+ llvm::Optional<OffsetEncoding> OffsetEncodingFromFlag;
+ if (ForceOffsetEncoding != OffsetEncoding::UnsupportedEncoding)
+ OffsetEncodingFromFlag = ForceOffsetEncoding;
ClangdLSPServer LSPServer(
- *TransportLayer, CCOpts, CompileCommandsDirPath,
- /*UseDirBasedCDB=*/CompileArgsFrom == FilesystemCompileArgs, Opts);
+ *TransportLayer, FSProvider, CCOpts, CompileCommandsDirPath,
+ /*UseDirBasedCDB=*/CompileArgsFrom == FilesystemCompileArgs,
+ OffsetEncodingFromFlag, Opts);
llvm::set_thread_name("clangd.main");
return LSPServer.run() ? 0
: static_cast<int>(ErrorResultCode::NoShutdownRequest);
diff --git a/clangd/unittests/Annotations.cpp b/clangd/unittests/Annotations.cpp
new file mode 100644
index 00000000..edb0ea9a
--- /dev/null
+++ b/clangd/unittests/Annotations.cpp
@@ -0,0 +1,53 @@
+//===--- Annotations.cpp - Annotated source code for unit tests --*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Annotations.h"
+#include "SourceCode.h"
+
+namespace clang {
+namespace clangd {
+
+Position Annotations::point(llvm::StringRef Name) const {
+ return offsetToPosition(code(), Base::point(Name));
+}
+
+std::vector<Position> Annotations::points(llvm::StringRef Name) const {
+ auto Offsets = Base::points(Name);
+
+ std::vector<Position> Ps;
+ Ps.reserve(Offsets.size());
+ for (size_t O : Offsets)
+ Ps.push_back(offsetToPosition(code(), O));
+
+ return Ps;
+}
+
+static clangd::Range toLSPRange(llvm::StringRef Code, Annotations::Range R) {
+ clangd::Range LSPRange;
+ LSPRange.start = offsetToPosition(Code, R.Begin);
+ LSPRange.end = offsetToPosition(Code, R.End);
+ return LSPRange;
+}
+
+clangd::Range Annotations::range(llvm::StringRef Name) const {
+ return toLSPRange(code(), Base::range(Name));
+}
+
+std::vector<clangd::Range> Annotations::ranges(llvm::StringRef Name) const {
+ auto OffsetRanges = Base::ranges(Name);
+
+ std::vector<clangd::Range> Rs;
+ Rs.reserve(OffsetRanges.size());
+ for (Annotations::Range R : OffsetRanges)
+ Rs.push_back(toLSPRange(code(), R));
+
+ return Rs;
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/clangd/unittests/Annotations.h b/clangd/unittests/Annotations.h
new file mode 100644
index 00000000..846c36a5
--- /dev/null
+++ b/clangd/unittests/Annotations.h
@@ -0,0 +1,39 @@
+//===--- Annotations.h - Annotated source code for tests ---------*- 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
+//
+//===----------------------------------------------------------------------===//
+// A clangd-specific version of llvm/Testing/Support/Annotations.h, replaces
+// offsets and offset-based ranges with types from the LSP protocol.
+//===---------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_ANNOTATIONS_H
+#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_ANNOTATIONS_H
+
+#include "Protocol.h"
+#include "llvm/Testing/Support/Annotations.h"
+
+namespace clang {
+namespace clangd {
+
+/// Same as llvm::Annotations, but adjusts functions to LSP-specific types for
+/// positions and ranges.
+class Annotations : public llvm::Annotations {
+ using Base = llvm::Annotations;
+
+public:
+ using llvm::Annotations::Annotations;
+
+ Position point(llvm::StringRef Name = "") const;
+ std::vector<Position> points(llvm::StringRef Name = "") const;
+
+ clangd::Range range(llvm::StringRef Name = "") const;
+ std::vector<clangd::Range> ranges(llvm::StringRef Name = "") const;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_ANNOTATIONS_H
diff --git a/unittests/clangd/BackgroundIndexTests.cpp b/clangd/unittests/BackgroundIndexTests.cpp
index 639d35c8..86f87009 100644
--- a/unittests/clangd/BackgroundIndexTests.cpp
+++ b/clangd/unittests/BackgroundIndexTests.cpp
@@ -7,12 +7,12 @@
#include "gtest/gtest.h"
#include <thread>
-using testing::_;
-using testing::AllOf;
-using testing::Contains;
-using testing::ElementsAre;
-using testing::Not;
-using testing::UnorderedElementsAre;
+using ::testing::_;
+using ::testing::AllOf;
+using ::testing::Contains;
+using ::testing::ElementsAre;
+using ::testing::Not;
+using ::testing::UnorderedElementsAre;
namespace clang {
namespace clangd {
@@ -23,9 +23,9 @@ MATCHER(Declared, "") {
}
MATCHER(Defined, "") { return !StringRef(arg.Definition.FileURI).empty(); }
MATCHER_P(FileURI, F, "") { return StringRef(arg.Location.FileURI) == F; }
-testing::Matcher<const RefSlab &>
-RefsAre(std::vector<testing::Matcher<Ref>> Matchers) {
- return ElementsAre(testing::Pair(_, UnorderedElementsAreArray(Matchers)));
+::testing::Matcher<const RefSlab &>
+RefsAre(std::vector<::testing::Matcher<Ref>> Matchers) {
+ return ElementsAre(::testing::Pair(_, UnorderedElementsAreArray(Matchers)));
}
// URI cannot be empty since it references keys in the IncludeGraph.
MATCHER(EmptyIncludeNode, "") {
@@ -44,12 +44,14 @@ public:
llvm::Error storeShard(llvm::StringRef ShardIdentifier,
IndexFileOut Shard) const override {
std::lock_guard<std::mutex> Lock(StorageMu);
+ AccessedPaths.insert(ShardIdentifier);
Storage[ShardIdentifier] = llvm::to_string(Shard);
return llvm::Error::success();
}
std::unique_ptr<IndexFileIn>
loadShard(llvm::StringRef ShardIdentifier) const override {
std::lock_guard<std::mutex> Lock(StorageMu);
+ AccessedPaths.insert(ShardIdentifier);
if (Storage.find(ShardIdentifier) == Storage.end()) {
return nullptr;
}
@@ -62,11 +64,13 @@ public:
CacheHits++;
return llvm::make_unique<IndexFileIn>(std::move(*IndexFile));
}
+
+ mutable llvm::StringSet<> AccessedPaths;
};
class BackgroundIndexTest : public ::testing::Test {
protected:
- BackgroundIndexTest() { preventThreadStarvationInTests(); }
+ BackgroundIndexTest() { BackgroundIndex::preventThreadStarvationInTests(); }
};
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile) {
@@ -76,7 +80,7 @@ TEST_F(BackgroundIndexTest, NoCrashOnErrorFile) {
size_t CacheHits = 0;
MemoryShardStorage MSS(Storage, CacheHits);
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(Context::empty(), "", FS, CDB,
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
[&](llvm::StringRef) { return &MSS; });
tooling::CompileCommand Cmd;
@@ -113,7 +117,7 @@ TEST_F(BackgroundIndexTest, IndexTwoFiles) {
size_t CacheHits = 0;
MemoryShardStorage MSS(Storage, CacheHits);
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(Context::empty(), "", FS, CDB,
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
[&](llvm::StringRef) { return &MSS; });
tooling::CompileCommand Cmd;
@@ -168,7 +172,7 @@ TEST_F(BackgroundIndexTest, ShardStorageTest) {
// Check nothing is loaded from Storage, but A.cc and A.h has been stored.
{
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(Context::empty(), "", FS, CDB,
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
[&](llvm::StringRef) { return &MSS; });
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -178,7 +182,7 @@ TEST_F(BackgroundIndexTest, ShardStorageTest) {
{
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(Context::empty(), "", FS, CDB,
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
[&](llvm::StringRef) { return &MSS; });
CDB.setCompileCommand(testPath("root"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -224,7 +228,7 @@ TEST_F(BackgroundIndexTest, DirectIncludesTest) {
Cmd.CommandLine = {"clang++", testPath("root/A.cc")};
{
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(Context::empty(), "", FS, CDB,
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
[&](llvm::StringRef) { return &MSS; });
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -262,7 +266,7 @@ TEST_F(BackgroundIndexTest, DISABLED_PeriodicalIndex) {
MemoryShardStorage MSS(Storage, CacheHits);
OverlayCDB CDB(/*Base=*/nullptr);
BackgroundIndex Idx(
- Context::empty(), "", FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; },
/*BuildIndexPeriodMs=*/500);
FS.Files[testPath("root/A.cc")] = "#include \"A.h\"";
@@ -310,7 +314,7 @@ TEST_F(BackgroundIndexTest, ShardStorageLoad) {
// Check nothing is loaded from Storage, but A.cc and A.h has been stored.
{
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(Context::empty(), "", FS, CDB,
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
[&](llvm::StringRef) { return &MSS; });
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -325,7 +329,7 @@ TEST_F(BackgroundIndexTest, ShardStorageLoad) {
)cpp";
{
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(Context::empty(), "", FS, CDB,
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
[&](llvm::StringRef) { return &MSS; });
CDB.setCompileCommand(testPath("root"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -343,7 +347,7 @@ TEST_F(BackgroundIndexTest, ShardStorageLoad) {
{
CacheHits = 0;
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(Context::empty(), "", FS, CDB,
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
[&](llvm::StringRef) { return &MSS; });
CDB.setCompileCommand(testPath("root"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -384,7 +388,7 @@ TEST_F(BackgroundIndexTest, ShardStorageEmptyFile) {
// Check that A.cc, A.h and B.h has been stored.
{
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(Context::empty(), "", FS, CDB,
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
[&](llvm::StringRef) { return &MSS; });
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -400,7 +404,7 @@ TEST_F(BackgroundIndexTest, ShardStorageEmptyFile) {
{
CacheHits = 0;
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(Context::empty(), "", FS, CDB,
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
[&](llvm::StringRef) { return &MSS; });
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -416,7 +420,7 @@ TEST_F(BackgroundIndexTest, ShardStorageEmptyFile) {
{
CacheHits = 0;
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(Context::empty(), "", FS, CDB,
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
[&](llvm::StringRef) { return &MSS; });
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -428,5 +432,34 @@ TEST_F(BackgroundIndexTest, ShardStorageEmptyFile) {
Contains(AllOf(Named("new_func"), Declared(), Not(Defined()))));
}
+TEST_F(BackgroundIndexTest, NoDotsInAbsPath) {
+ MockFSProvider FS;
+ llvm::StringMap<std::string> Storage;
+ size_t CacheHits = 0;
+ MemoryShardStorage MSS(Storage, CacheHits);
+ OverlayCDB CDB(/*Base=*/nullptr);
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
+ [&](llvm::StringRef) { return &MSS; });
+
+ tooling::CompileCommand Cmd;
+ FS.Files[testPath("root/A.cc")] = "";
+ Cmd.Filename = "../A.cc";
+ Cmd.Directory = testPath("root/build");
+ Cmd.CommandLine = {"clang++", "../A.cc"};
+ CDB.setCompileCommand(testPath("root/build/../A.cc"), Cmd);
+
+ FS.Files[testPath("root/B.cc")] = "";
+ Cmd.Filename = "./B.cc";
+ Cmd.Directory = testPath("root");
+ Cmd.CommandLine = {"clang++", "./B.cc"};
+ CDB.setCompileCommand(testPath("root/./B.cc"), Cmd);
+
+ ASSERT_TRUE(Idx.blockUntilIdleForTest());
+ for (llvm::StringRef AbsPath : MSS.AccessedPaths.keys()) {
+ EXPECT_FALSE(AbsPath.contains("./")) << AbsPath;
+ EXPECT_FALSE(AbsPath.contains("../")) << AbsPath;
+ }
+}
+
} // namespace clangd
} // namespace clang
diff --git a/unittests/clangd/CMakeLists.txt b/clangd/unittests/CMakeLists.txt
index ccc19275..96b1d360 100644
--- a/unittests/clangd/CMakeLists.txt
+++ b/clangd/unittests/CMakeLists.txt
@@ -4,20 +4,35 @@ set(LLVM_LINK_COMPONENTS
get_filename_component(CLANGD_SOURCE_DIR
${CMAKE_CURRENT_SOURCE_DIR}/../../clangd REALPATH)
+get_filename_component(CLANGD_BINARY_DIR
+ ${CMAKE_CURRENT_BINARY_DIR}/../../clangd REALPATH)
include_directories(
${CLANGD_SOURCE_DIR}
+ ${CLANGD_BINARY_DIR}
)
-add_extra_unittest(ClangdTests
+if(CLANG_BUILT_STANDALONE)
+ # LLVMTestingSupport library is needed for clangd tests.
+ if (EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Testing/Support
+ AND NOT TARGET LLVMTestingSupport)
+ add_subdirectory(${LLVM_MAIN_SRC_DIR}/lib/Testing/Support
+ lib/Testing/Support)
+ endif()
+endif()
+
+add_custom_target(ClangdUnitTests)
+add_unittest(ClangdUnitTests ClangdTests
Annotations.cpp
BackgroundIndexTests.cpp
CancellationTests.cpp
+ CanonicalIncludesTests.cpp
ClangdTests.cpp
ClangdUnitTests.cpp
CodeCompleteTests.cpp
CodeCompletionStringsTests.cpp
ContextTests.cpp
DexTests.cpp
+ DiagnosticsTests.cpp
DraftStoreTests.cpp
ExpectedTypeTest.cpp
FileDistanceTests.cpp
@@ -31,8 +46,10 @@ add_extra_unittest(ClangdTests
IndexActionTests.cpp
IndexTests.cpp
JSONTransportTests.cpp
+ PrintASTTests.cpp
QualityTests.cpp
RIFFTests.cpp
+ SelectionTests.cpp
SerializationTests.cpp
SourceCodeTests.cpp
SymbolCollectorTests.cpp
@@ -44,8 +61,12 @@ add_extra_unittest(ClangdTests
TestTU.cpp
ThreadingTests.cpp
TraceTests.cpp
+ TypeHierarchyTests.cpp
+ TweakTests.cpp
URITests.cpp
XRefsTests.cpp
+
+ $<TARGET_OBJECTS:obj.clangDaemonTweaks>
)
target_link_libraries(ClangdTests
@@ -59,6 +80,7 @@ target_link_libraries(ClangdTests
clangLex
clangSema
clangSerialization
+ clangTidy
clangTooling
clangToolingCore
clangToolingInclusions
@@ -69,3 +91,7 @@ target_link_libraries(ClangdTests
if (CLANGD_BUILD_XPC)
add_subdirectory(xpc)
endif ()
+
+configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py)
diff --git a/unittests/clangd/CancellationTests.cpp b/clangd/unittests/CancellationTests.cpp
index 611ce07d..611ce07d 100644
--- a/unittests/clangd/CancellationTests.cpp
+++ b/clangd/unittests/CancellationTests.cpp
diff --git a/clangd/unittests/CanonicalIncludesTests.cpp b/clangd/unittests/CanonicalIncludesTests.cpp
new file mode 100644
index 00000000..9fd78841
--- /dev/null
+++ b/clangd/unittests/CanonicalIncludesTests.cpp
@@ -0,0 +1,62 @@
+//===-- CanonicalIncludesTests.cpp - --------------------------------------===//
+//
+// 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 "index/CanonicalIncludes.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(CanonicalIncludesTest, CXXStandardLibrary) {
+ CanonicalIncludes CI;
+ addSystemHeadersMapping(&CI);
+
+ // Usual standard library symbols are mapped correctly.
+ EXPECT_EQ("<vector>", CI.mapHeader("path/vector.h", "std::vector"));
+ // std::move is ambiguous, currently mapped only based on path
+ EXPECT_EQ("<utility>", CI.mapHeader("libstdc++/bits/move.h", "std::move"));
+ EXPECT_EQ("path/utility.h", CI.mapHeader("path/utility.h", "std::move"));
+ // Unknown std symbols aren't mapped.
+ EXPECT_EQ("foo/bar.h", CI.mapHeader("foo/bar.h", "std::notathing"));
+ // iosfwd declares some symbols it doesn't own.
+ EXPECT_EQ("<ostream>", CI.mapHeader("iosfwd", "std::ostream"));
+ // And (for now) we assume it owns the others.
+ EXPECT_EQ("<iosfwd>", CI.mapHeader("iosfwd", "std::notwathing"));
+}
+
+TEST(CanonicalIncludesTest, PathMapping) {
+ // As used for IWYU pragmas.
+ CanonicalIncludes CI;
+ CI.addMapping("foo/bar", "<baz>");
+
+ EXPECT_EQ("<baz>", CI.mapHeader("foo/bar", "some::symbol"));
+ EXPECT_EQ("bar/bar", CI.mapHeader("bar/bar", "some::symbol"));
+}
+
+TEST(CanonicalIncludesTest, SymbolMapping) {
+ // As used for standard library.
+ CanonicalIncludes CI;
+ CI.addSymbolMapping("some::symbol", "<baz>");
+
+ EXPECT_EQ("<baz>", CI.mapHeader("foo/bar", "some::symbol"));
+ EXPECT_EQ("foo/bar", CI.mapHeader("foo/bar", "other::symbol"));
+}
+
+TEST(CanonicalIncludesTest, Precedence) {
+ CanonicalIncludes CI;
+ CI.addMapping("some/path", "<path>");
+ CI.addSymbolMapping("some::symbol", "<symbol>");
+
+ // Symbol mapping beats path mapping.
+ EXPECT_EQ("<symbol>", CI.mapHeader("some/path", "some::symbol"));
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/unittests/clangd/ClangdTests.cpp b/clangd/unittests/ClangdTests.cpp
index c1cc623a..5d98bdc2 100644
--- a/unittests/clangd/ClangdTests.cpp
+++ b/clangd/unittests/ClangdTests.cpp
@@ -1,20 +1,22 @@
//===-- ClangdTests.cpp - Clangd unit tests ---------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "Annotations.h"
#include "ClangdLSPServer.h"
#include "ClangdServer.h"
+#include "GlobalCompilationDatabase.h"
#include "Matchers.h"
#include "SyncAPI.h"
#include "TestFS.h"
+#include "Threading.h"
#include "URI.h"
#include "clang/Config/config.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Errc.h"
@@ -36,15 +38,15 @@ namespace clangd {
namespace {
using ::testing::ElementsAre;
-using ::testing::Eq;
using ::testing::Field;
using ::testing::Gt;
using ::testing::IsEmpty;
using ::testing::Pair;
using ::testing::UnorderedElementsAre;
-MATCHER_P2(FileRange, File, Range, "") {
- return Location{URIForFile::canonicalize(File, testRoot()), Range} == arg;
+MATCHER_P2(DeclAt, File, Range, "") {
+ return arg.PreferredDeclaration ==
+ Location{URIForFile::canonicalize(File, testRoot()), Range};
}
bool diagsContainErrors(const std::vector<Diag> &Diagnostics) {
@@ -458,10 +460,9 @@ int hello;
UnorderedElementsAre(Pair(FooCpp, false), Pair(BarCpp, true),
Pair(BazCpp, false)));
- auto Locations = runFindDefinitions(Server, FooCpp, FooSource.point());
+ auto Locations = runLocateSymbolAt(Server, FooCpp, FooSource.point());
EXPECT_TRUE(bool(Locations));
- EXPECT_THAT(*Locations,
- ElementsAre(FileRange(FooCpp, FooSource.range("one"))));
+ EXPECT_THAT(*Locations, ElementsAre(DeclAt(FooCpp, FooSource.range("one"))));
// Undefine MACRO, close baz.cpp.
CDB.ExtraClangFlags.clear();
@@ -474,10 +475,9 @@ int hello;
EXPECT_THAT(DiagConsumer.filesWithDiags(),
UnorderedElementsAre(Pair(FooCpp, false), Pair(BarCpp, false)));
- Locations = runFindDefinitions(Server, FooCpp, FooSource.point());
+ Locations = runLocateSymbolAt(Server, FooCpp, FooSource.point());
EXPECT_TRUE(bool(Locations));
- EXPECT_THAT(*Locations,
- ElementsAre(FileRange(FooCpp, FooSource.range("two"))));
+ EXPECT_THAT(*Locations, ElementsAre(DeclAt(FooCpp, FooSource.range("two"))));
}
TEST_F(ClangdVFSTest, MemoryUsage) {
@@ -532,15 +532,15 @@ TEST_F(ClangdVFSTest, InvalidCompileCommand) {
runAddDocument(Server, FooCpp, "int main() {}");
EXPECT_EQ(runDumpAST(Server, FooCpp), "<no-ast>");
- EXPECT_ERROR(runFindDefinitions(Server, FooCpp, Position()));
+ EXPECT_ERROR(runLocateSymbolAt(Server, FooCpp, Position()));
EXPECT_ERROR(runFindDocumentHighlights(Server, FooCpp, Position()));
EXPECT_ERROR(runRename(Server, FooCpp, Position(), "new_name"));
- // FIXME: codeComplete and signatureHelp should also return errors when they
- // can't parse the file.
+ // Identifier-based fallback completion.
EXPECT_THAT(cantFail(runCodeComplete(Server, FooCpp, Position(),
clangd::CodeCompleteOptions()))
.Completions,
- IsEmpty());
+ ElementsAre(Field(&CodeCompletion::Name, "int"),
+ Field(&CodeCompletion::Name, "main")));
auto SigHelp = runSignatureHelp(Server, FooCpp, Position());
ASSERT_TRUE(bool(SigHelp)) << "signatureHelp returned an error";
EXPECT_THAT(SigHelp->signatures, IsEmpty());
@@ -717,7 +717,7 @@ int d;
clangd::CodeCompleteOptions()));
};
- auto FindDefinitionsRequest = [&]() {
+ auto LocateSymbolRequest = [&]() {
unsigned FileIndex = FileIndexDist(RandGen);
// Make sure we don't violate the ClangdServer's contract.
if (ReqStats[FileIndex].FileIsRemoved)
@@ -727,13 +727,13 @@ int d;
Pos.line = LineDist(RandGen);
Pos.character = ColumnDist(RandGen);
- ASSERT_TRUE(!!runFindDefinitions(Server, FilePaths[FileIndex], Pos));
+ ASSERT_TRUE(!!runLocateSymbolAt(Server, FilePaths[FileIndex], Pos));
};
std::vector<std::function<void()>> AsyncRequests = {
AddDocumentRequest, ForceReparseRequest, RemoveDocumentRequest};
std::vector<std::function<void()>> BlockingRequests = {
- CodeCompletionRequest, FindDefinitionsRequest};
+ CodeCompletionRequest, LocateSymbolRequest};
// Bash requests to ClangdServer in a loop.
std::uniform_int_distribution<int> AsyncRequestIndexDist(
@@ -1037,6 +1037,126 @@ TEST(ClangdTests, PreambleVFSStatCache) {
}
#endif
+TEST_F(ClangdVFSTest, FlagsWithPlugins) {
+ MockFSProvider FS;
+ ErrorCheckingDiagConsumer DiagConsumer;
+ MockCompilationDatabase CDB;
+ CDB.ExtraClangFlags = {
+ "-Xclang",
+ "-add-plugin",
+ "-Xclang",
+ "random-plugin",
+ };
+ OverlayCDB OCDB(&CDB);
+ ClangdServer Server(OCDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+ auto FooCpp = testPath("foo.cpp");
+ const auto SourceContents = "int main() { return 0; }";
+ FS.Files[FooCpp] = FooCpp;
+ Server.addDocument(FooCpp, SourceContents);
+ auto Result = dumpASTWithoutMemoryLocs(Server, FooCpp);
+ EXPECT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for diagnostics";
+ EXPECT_NE(Result, "<no-ast>");
+}
+
+TEST_F(ClangdVFSTest, FallbackWhenPreambleIsNotReady) {
+ MockFSProvider FS;
+ ErrorCheckingDiagConsumer DiagConsumer;
+ MockCompilationDatabase CDB;
+ ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+ auto FooCpp = testPath("foo.cpp");
+ Annotations Code(R"cpp(
+ namespace ns { int xyz; }
+ using namespace ns;
+ int main() {
+ xy^
+ })cpp");
+ FS.Files[FooCpp] = FooCpp;
+
+ auto Opts = clangd::CodeCompleteOptions();
+ Opts.AllowFallback = true;
+
+ // This will make compile command broken and preamble absent.
+ CDB.ExtraClangFlags = {"yolo.cc"};
+ Server.addDocument(FooCpp, Code.code());
+ ASSERT_TRUE(Server.blockUntilIdleForTest());
+ auto Res = cantFail(runCodeComplete(Server, FooCpp, Code.point(), Opts));
+ EXPECT_EQ(Res.Context, CodeCompletionContext::CCC_Recovery);
+ // Identifier-based fallback completion doesn't know about "symbol" scope.
+ EXPECT_THAT(Res.Completions,
+ ElementsAre(AllOf(Field(&CodeCompletion::Name, "xyz"),
+ Field(&CodeCompletion::Scope, ""))));
+
+ // Make the compile command work again.
+ CDB.ExtraClangFlags = {"-std=c++11"};
+ Server.addDocument(FooCpp, Code.code());
+ ASSERT_TRUE(Server.blockUntilIdleForTest());
+ EXPECT_THAT(cantFail(runCodeComplete(Server, FooCpp, Code.point(),
+ clangd::CodeCompleteOptions()))
+ .Completions,
+ ElementsAre(AllOf(Field(&CodeCompletion::Name, "xyz"),
+ Field(&CodeCompletion::Scope, "ns::"))));
+}
+
+TEST_F(ClangdVFSTest, FallbackWhenWaitingForCompileCommand) {
+ MockFSProvider FS;
+ ErrorCheckingDiagConsumer DiagConsumer;
+ // Returns compile command only when notified.
+ class DelayedCompilationDatabase : public GlobalCompilationDatabase {
+ public:
+ DelayedCompilationDatabase(Notification &CanReturnCommand)
+ : CanReturnCommand(CanReturnCommand) {}
+
+ llvm::Optional<tooling::CompileCommand>
+ getCompileCommand(PathRef File, ProjectInfo * = nullptr) const override {
+ // FIXME: make this timeout and fail instead of waiting forever in case
+ // something goes wrong.
+ CanReturnCommand.wait();
+ auto FileName = llvm::sys::path::filename(File);
+ std::vector<std::string> CommandLine = {"clangd", "-ffreestanding", File};
+ return {tooling::CompileCommand(llvm::sys::path::parent_path(File),
+ FileName, std::move(CommandLine), "")};
+ }
+
+ std::vector<std::string> ExtraClangFlags;
+
+ private:
+ Notification &CanReturnCommand;
+ };
+
+ Notification CanReturnCommand;
+ DelayedCompilationDatabase CDB(CanReturnCommand);
+ ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+ auto FooCpp = testPath("foo.cpp");
+ Annotations Code(R"cpp(
+ namespace ns { int xyz; }
+ using namespace ns;
+ int main() {
+ xy^
+ })cpp");
+ FS.Files[FooCpp] = FooCpp;
+ Server.addDocument(FooCpp, Code.code());
+
+ // Sleep for some time to make sure code completion is not run because update
+ // hasn't been scheduled.
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ auto Opts = clangd::CodeCompleteOptions();
+ Opts.AllowFallback = true;
+
+ auto Res = cantFail(runCodeComplete(Server, FooCpp, Code.point(), Opts));
+ EXPECT_EQ(Res.Context, CodeCompletionContext::CCC_Recovery);
+
+ CanReturnCommand.notify();
+ ASSERT_TRUE(Server.blockUntilIdleForTest());
+ EXPECT_THAT(cantFail(runCodeComplete(Server, FooCpp, Code.point(),
+ clangd::CodeCompleteOptions()))
+ .Completions,
+ ElementsAre(AllOf(Field(&CodeCompletion::Name, "xyz"),
+ Field(&CodeCompletion::Scope, "ns::"))));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
diff --git a/clangd/unittests/ClangdUnitTests.cpp b/clangd/unittests/ClangdUnitTests.cpp
new file mode 100644
index 00000000..2c239ce7
--- /dev/null
+++ b/clangd/unittests/ClangdUnitTests.cpp
@@ -0,0 +1,86 @@
+//===-- ClangdUnitTests.cpp - ClangdUnit tests ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Annotations.h"
+#include "ClangdUnit.h"
+#include "SourceCode.h"
+#include "TestTU.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+using ::testing::ElementsAre;
+
+TEST(ClangdUnitTest, GetBeginningOfIdentifier) {
+ std::string Preamble = R"cpp(
+struct Bar { int func(); };
+#define MACRO(X) void f() { X; }
+Bar* bar;
+ )cpp";
+ // First ^ is the expected beginning, last is the search position.
+ for (std::string Text : std::vector<std::string>{
+ "int ^f^oo();", // inside identifier
+ "int ^foo();", // beginning of identifier
+ "int ^foo^();", // end of identifier
+ "int foo(^);", // non-identifier
+ "^int foo();", // beginning of file (can't back up)
+ "int ^f0^0();", // after a digit (lexing at N-1 is wrong)
+ "int ^λλ^λ();", // UTF-8 handled properly when backing up
+
+ // identifier in macro arg
+ "MACRO(bar->^func())", // beginning of identifier
+ "MACRO(bar->^fun^c())", // inside identifier
+ "MACRO(bar->^func^())", // end of identifier
+ "MACRO(^bar->func())", // begin identifier
+ "MACRO(^bar^->func())", // end identifier
+ "^MACRO(bar->func())", // beginning of macro name
+ "^MAC^RO(bar->func())", // inside macro name
+ "^MACRO^(bar->func())", // end of macro name
+ }) {
+ std::string WithPreamble = Preamble + Text;
+ Annotations TestCase(WithPreamble);
+ auto AST = TestTU::withCode(TestCase.code()).build();
+ const auto &SourceMgr = AST.getASTContext().getSourceManager();
+ SourceLocation Actual = getBeginningOfIdentifier(
+ AST, TestCase.points().back(), SourceMgr.getMainFileID());
+ Position ActualPos = offsetToPosition(
+ TestCase.code(),
+ SourceMgr.getFileOffset(SourceMgr.getSpellingLoc(Actual)));
+ EXPECT_EQ(TestCase.points().front(), ActualPos) << Text;
+ }
+}
+
+MATCHER_P(DeclNamed, Name, "") {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(arg))
+ if (ND->getName() == Name)
+ return true;
+ if (auto *Stream = result_listener->stream()) {
+ llvm::raw_os_ostream OS(*Stream);
+ arg->dump(OS);
+ }
+ return false;
+}
+
+TEST(ClangdUnitTest, TopLevelDecls) {
+ TestTU TU;
+ TU.HeaderCode = R"(
+ int header1();
+ int header2;
+ )";
+ TU.Code = "int main();";
+ auto AST = TU.build();
+ EXPECT_THAT(AST.getLocalTopLevelDecls(), ElementsAre(DeclNamed("main")));
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/unittests/clangd/CodeCompleteTests.cpp b/clangd/unittests/CodeCompleteTests.cpp
index 02f12eab..e584597e 100644
--- a/unittests/clangd/CodeCompleteTests.cpp
+++ b/clangd/unittests/CodeCompleteTests.cpp
@@ -1,9 +1,8 @@
//===-- CodeCompleteTests.cpp -----------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -17,9 +16,14 @@
#include "SourceCode.h"
#include "SyncAPI.h"
#include "TestFS.h"
+#include "TestIndex.h"
+#include "TestTU.h"
+#include "index/Index.h"
#include "index/MemIndex.h"
#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/Path.h"
#include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -31,7 +35,6 @@ namespace {
using ::llvm::Failed;
using ::testing::AllOf;
using ::testing::Contains;
-using ::testing::Each;
using ::testing::ElementsAre;
using ::testing::Field;
using ::testing::HasSubstr;
@@ -138,53 +141,25 @@ CodeCompleteResult completions(llvm::StringRef Text,
FilePath);
}
-std::string replace(llvm::StringRef Haystack, llvm::StringRef Needle,
- llvm::StringRef Repl) {
- std::string Result;
- llvm::raw_string_ostream OS(Result);
- std::pair<llvm::StringRef, llvm::StringRef> Split;
- for (Split = Haystack.split(Needle); !Split.second.empty();
- Split = Split.first.split(Needle))
- OS << Split.first << Repl;
- Result += Split.first;
- OS.flush();
- return Result;
-}
-
-// Helpers to produce fake index symbols for memIndex() or completions().
-// USRFormat is a regex replacement string for the unqualified part of the USR.
-Symbol sym(llvm::StringRef QName, index::SymbolKind Kind,
- llvm::StringRef USRFormat) {
- Symbol Sym;
- std::string USR = "c:"; // We synthesize a few simple cases of USRs by hand!
- size_t Pos = QName.rfind("::");
- if (Pos == llvm::StringRef::npos) {
- Sym.Name = QName;
- Sym.Scope = "";
- } else {
- Sym.Name = QName.substr(Pos + 2);
- Sym.Scope = QName.substr(0, Pos + 2);
- USR += "@N@" + replace(QName.substr(0, Pos), "::", "@N@"); // ns:: -> @N@ns
+// Builds a server and runs code completion.
+// If IndexSymbols is non-empty, an index will be built and passed to opts.
+CodeCompleteResult completionsNoCompile(llvm::StringRef Text,
+ std::vector<Symbol> IndexSymbols = {},
+ clangd::CodeCompleteOptions Opts = {},
+ PathRef FilePath = "foo.cpp") {
+ std::unique_ptr<SymbolIndex> OverrideIndex;
+ if (!IndexSymbols.empty()) {
+ assert(!Opts.Index && "both Index and IndexSymbols given!");
+ OverrideIndex = memIndex(std::move(IndexSymbols));
+ Opts.Index = OverrideIndex.get();
}
- USR += llvm::Regex("^.*$").sub(USRFormat, Sym.Name); // e.g. func -> @F@func#
- Sym.ID = SymbolID(USR);
- Sym.SymInfo.Kind = Kind;
- Sym.Flags |= Symbol::IndexedForCodeCompletion;
- Sym.Origin = SymbolOrigin::Static;
- return Sym;
-}
-Symbol func(llvm::StringRef Name) { // Assumes the function has no args.
- return sym(Name, index::SymbolKind::Function, "@F@\\0#"); // no args
-}
-Symbol cls(llvm::StringRef Name) {
- return sym(Name, index::SymbolKind::Class, "@S@\\0");
-}
-Symbol var(llvm::StringRef Name) {
- return sym(Name, index::SymbolKind::Variable, "@\\0");
-}
-Symbol ns(llvm::StringRef Name) {
- return sym(Name, index::SymbolKind::Namespace, "@N@\\0");
+
+ MockFSProvider FS;
+ Annotations Test(Text);
+ return codeComplete(FilePath, tooling::CompileCommand(), /*Preamble=*/nullptr,
+ Test.code(), Test.point(), FS.getFileSystem(), Opts);
}
+
Symbol withReferences(int N, Symbol S) {
S.References = N;
return S;
@@ -199,6 +174,7 @@ struct ClassWithMembers {
int BBB();
int CCC();
};
+
int main() { ClassWithMembers().^ }
)cpp",
/*IndexSymbols=*/{}, Opts);
@@ -259,6 +235,7 @@ void TestAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
)cpp",
{cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
+ EXPECT_TRUE(Results.RanParser);
// Class members. The only items that must be present in after-dot
// completion.
EXPECT_THAT(Results.Completions,
@@ -308,6 +285,7 @@ void TestGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
)cpp",
{cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
+ EXPECT_TRUE(Results.RanParser);
// Class members. Should never be present in global completions.
EXPECT_THAT(Results.Completions,
Not(AnyOf(Has("method"), Has("method()"), Has("field"))));
@@ -349,7 +327,7 @@ TEST(CompletionTest, CompletionOptions) {
}
}
-TEST(CompletionTest, Priorities) {
+TEST(CompletionTest, Accessible) {
auto Internal = completions(R"cpp(
class Foo {
public: void pub();
@@ -359,7 +337,7 @@ TEST(CompletionTest, Priorities) {
void Foo::pub() { this->^ }
)cpp");
EXPECT_THAT(Internal.Completions,
- HasSubsequence(Named("priv"), Named("prot"), Named("pub")));
+ AllOf(Has("priv"), Has("prot"), Has("pub")));
auto External = completions(R"cpp(
class Foo {
@@ -527,6 +505,21 @@ TEST(CompletionTest, ReferencesAffectRanking) {
HasSubsequence(Named("absl"), Named("absb")));
}
+TEST(CompletionTest, ContextWords) {
+ auto Results = completions(R"cpp(
+ enum class Color { RED, YELLOW, BLUE };
+
+ // (blank lines so the definition above isn't "context")
+
+ // "It was a yellow car," he said. "Big yellow car, new."
+ auto Finish = Color::^
+ )cpp");
+ // Yellow would normally sort last (alphabetic).
+ // But the recent mention shuold bump it up.
+ ASSERT_THAT(Results.Completions,
+ HasSubsequence(Named("YELLOW"), Named("BLUE")));
+}
+
TEST(CompletionTest, GlobalQualified) {
auto Results = completions(
R"cpp(
@@ -602,6 +595,16 @@ TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
{Sym});
EXPECT_THAT(Results.Completions,
ElementsAre(AllOf(Named("X"), InsertInclude("\"bar.h\""))));
+ // Can be disabled via option.
+ CodeCompleteOptions NoInsertion;
+ NoInsertion.InsertIncludes = CodeCompleteOptions::NeverInsert;
+ Results = completions(Server,
+ R"cpp(
+ int main() { ns::^ }
+ )cpp",
+ {Sym}, NoInsertion);
+ EXPECT_THAT(Results.Completions,
+ ElementsAre(AllOf(Named("X"), Not(InsertInclude()))));
// Duplicate based on inclusions in preamble.
Results = completions(Server,
R"cpp(
@@ -692,6 +695,39 @@ TEST(CompletionTest, CompletionInPreamble) {
EXPECT_THAT(Results, ElementsAre(Named("ifndef")));
}
+TEST(CompletionTest, DynamicIndexIncludeInsertion) {
+ MockFSProvider FS;
+ MockCompilationDatabase CDB;
+ IgnoreDiagnostics DiagConsumer;
+ ClangdServer::Options Opts = ClangdServer::optsForTest();
+ Opts.BuildDynamicSymbolIndex = true;
+ ClangdServer Server(CDB, FS, DiagConsumer, Opts);
+
+ FS.Files[testPath("foo_header.h")] = R"cpp(
+ #pragma once
+ struct Foo {
+ // Member doc
+ int foo();
+ };
+ )cpp";
+ const std::string FileContent(R"cpp(
+ #include "foo_header.h"
+ int Foo::foo() {
+ return 42;
+ }
+ )cpp");
+ Server.addDocument(testPath("foo_impl.cpp"), FileContent);
+ // Wait for the dynamic index being built.
+ ASSERT_TRUE(Server.blockUntilIdleForTest());
+ EXPECT_THAT(completions(Server, "Foo^ foo;").Completions,
+ ElementsAre(AllOf(Named("Foo"),
+ HasInclude('"' +
+ llvm::sys::path::convert_to_slash(
+ testPath("foo_header.h")) +
+ '"'),
+ InsertInclude())));
+}
+
TEST(CompletionTest, DynamicIndexMultiFile) {
MockFSProvider FS;
MockCompilationDatabase CDB;
@@ -1111,8 +1147,10 @@ TEST(CompletionTest, UnresolvedQualifierIdQuery) {
} // namespace ns
)cpp");
- EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
- UnorderedElementsAre("bar::"))));
+ EXPECT_THAT(Requests,
+ ElementsAre(Field(
+ &FuzzyFindRequest::Scopes,
+ UnorderedElementsAre("a::bar::", "ns::bar::", "bar::"))));
}
TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
@@ -1371,7 +1409,7 @@ TEST(CompletionTest, NonDocComments) {
// FIXME: Auto-completion in a template requires disabling delayed template
// parsing.
CDB.ExtraClangFlags.push_back("-fno-delayed-template-parsing");
- Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes);
+ runAddDocument(Server, FooCpp, Source.code(), WantDiagnostics::Yes);
CodeCompleteResult Completions = cantFail(runCodeComplete(
Server, FooCpp, Source.point(), clangd::CodeCompleteOptions()));
@@ -1929,28 +1967,37 @@ TEST(CompletionTest, OverridesNonIdentName) {
)cpp");
}
-TEST(SpeculateCompletionFilter, Filters) {
- Annotations F(R"cpp($bof^
- $bol^
- ab$ab^
- x.ab$dot^
- x.$dotempty^
- x::ab$scoped^
- x::$scopedempty^
-
- )cpp");
- auto speculate = [&](StringRef PointName) {
- auto Filter = speculateCompletionFilter(F.code(), F.point(PointName));
- assert(Filter);
- return *Filter;
- };
- EXPECT_EQ(speculate("bof"), "");
- EXPECT_EQ(speculate("bol"), "");
- EXPECT_EQ(speculate("ab"), "ab");
- EXPECT_EQ(speculate("dot"), "ab");
- EXPECT_EQ(speculate("dotempty"), "");
- EXPECT_EQ(speculate("scoped"), "ab");
- EXPECT_EQ(speculate("scopedempty"), "");
+TEST(GuessCompletionPrefix, Filters) {
+ for (llvm::StringRef Case : {
+ "[[scope::]][[ident]]^",
+ "[[]][[]]^",
+ "\n[[]][[]]^",
+ "[[]][[ab]]^",
+ "x.[[]][[ab]]^",
+ "x.[[]][[]]^",
+ "[[x::]][[ab]]^",
+ "[[x::]][[]]^",
+ "[[::x::]][[ab]]^",
+ "some text [[scope::more::]][[identif]]^ier",
+ "some text [[scope::]][[mor]]^e::identifier",
+ "weird case foo::[[::bar::]][[baz]]^",
+ }) {
+ Annotations F(Case);
+ auto Offset = cantFail(positionToOffset(F.code(), F.point()));
+ auto ToStringRef = [&](Range R) {
+ return F.code().slice(cantFail(positionToOffset(F.code(), R.start)),
+ cantFail(positionToOffset(F.code(), R.end)));
+ };
+ auto WantQualifier = ToStringRef(F.ranges()[0]),
+ WantName = ToStringRef(F.ranges()[1]);
+
+ auto Prefix = guessCompletionPrefix(F.code(), Offset);
+ // Even when components are empty, check their offsets are correct.
+ EXPECT_EQ(WantQualifier, Prefix.Qualifier) << Case;
+ EXPECT_EQ(WantQualifier.begin(), Prefix.Qualifier.begin()) << Case;
+ EXPECT_EQ(WantName, Prefix.Name) << Case;
+ EXPECT_EQ(WantName.begin(), Prefix.Name.begin()) << Case;
+ }
}
TEST(CompletionTest, EnableSpeculativeIndexRequest) {
@@ -2044,19 +2091,28 @@ TEST(CompletionTest, MergeMacrosFromIndexAndSema) {
UnorderedElementsAre(Named("Clangd_Macro_Test")));
}
-TEST(CompletionTest, NoMacroFromPreambleIfIndexIsSet) {
+TEST(CompletionTest, MacroFromPreamble) {
+ MockFSProvider FS;
+ MockCompilationDatabase CDB;
+ std::string FooHeader = testPath("foo.h");
+ FS.Files[FooHeader] = "#define CLANGD_PREAMBLE_HEADER x\n";
+ IgnoreDiagnostics DiagConsumer;
+ ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
auto Results = completions(
- R"cpp(#define CLANGD_PREAMBLE x
+ R"cpp(#include "foo.h"
+ #define CLANGD_PREAMBLE_MAIN x
int x = 0;
#define CLANGD_MAIN x
void f() { CLANGD_^ }
)cpp",
{func("CLANGD_INDEX")});
- // Index is overriden in code completion options, so the preamble symbol is
- // not seen.
- EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("CLANGD_MAIN"),
- Named("CLANGD_INDEX")));
+ // We should get results from the main file, including the preamble section.
+ // However no results from included files (the index should cover them).
+ EXPECT_THAT(Results.Completions,
+ UnorderedElementsAre(Named("CLANGD_PREAMBLE_MAIN"),
+ Named("CLANGD_MAIN"),
+ Named("CLANGD_INDEX")));
}
TEST(CompletionTest, DeprecatedResults) {
@@ -2320,6 +2376,176 @@ TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
EXPECT_THAT(C, ElementsAre(SnippetSuffix("${1:(unsigned int)}")));
}
+TEST(CompletionTest, WorksWithNullType) {
+ auto R = completions(R"cpp(
+ int main() {
+ for (auto [loopVar] : y ) { // y has to be unresolved.
+ int z = loopV^;
+ }
+ }
+ )cpp");
+ EXPECT_THAT(R.Completions, ElementsAre(Named("loopVar")));
+}
+
+TEST(CompletionTest, UsingDecl) {
+ const char *Header(R"cpp(
+ void foo(int);
+ namespace std {
+ using ::foo;
+ })cpp");
+ const char *Source(R"cpp(
+ void bar() {
+ std::^;
+ })cpp");
+ auto Index = TestTU::withHeaderCode(Header).index();
+ clangd::CodeCompleteOptions Opts;
+ Opts.Index = Index.get();
+ Opts.AllScopes = true;
+ auto R = completions(Source, {}, Opts);
+ EXPECT_THAT(R.Completions,
+ ElementsAre(AllOf(Scope("std::"), Named("foo"),
+ Kind(CompletionItemKind::Reference))));
+}
+
+TEST(CompletionTest, ScopeIsUnresolved) {
+ clangd::CodeCompleteOptions Opts = {};
+ Opts.AllScopes = true;
+
+ auto Results = completions(R"cpp(
+ namespace a {
+ void f() { b::X^ }
+ }
+ )cpp",
+ {cls("a::b::XYZ")}, Opts);
+ EXPECT_THAT(Results.Completions,
+ UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ"))));
+}
+
+TEST(CompletionTest, NestedScopeIsUnresolved) {
+ clangd::CodeCompleteOptions Opts = {};
+ Opts.AllScopes = true;
+
+ auto Results = completions(R"cpp(
+ namespace a {
+ namespace b {}
+ void f() { b::c::X^ }
+ }
+ )cpp",
+ {cls("a::b::c::XYZ")}, Opts);
+ EXPECT_THAT(Results.Completions,
+ UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ"))));
+}
+
+// Clang parser gets confused here and doesn't report the ns:: prefix.
+// Naive behavior is to insert it again. We examine the source and recover.
+TEST(CompletionTest, NamespaceDoubleInsertion) {
+ clangd::CodeCompleteOptions Opts = {};
+
+ auto Results = completions(R"cpp(
+ namespace foo {
+ namespace ns {}
+ #define M(X) < X
+ M(ns::ABC^
+ }
+ )cpp",
+ {cls("foo::ns::ABCDE")}, Opts);
+ EXPECT_THAT(Results.Completions,
+ UnorderedElementsAre(AllOf(Qualifier(""), Named("ABCDE"))));
+}
+
+TEST(NoCompileCompletionTest, Basic) {
+ auto Results = completionsNoCompile(R"cpp(
+ void func() {
+ int xyz;
+ int abc;
+ ^
+ }
+ )cpp");
+ EXPECT_FALSE(Results.RanParser);
+ EXPECT_THAT(Results.Completions,
+ UnorderedElementsAre(Named("void"), Named("func"), Named("int"),
+ Named("xyz"), Named("abc")));
+}
+
+TEST(NoCompileCompletionTest, WithFilter) {
+ auto Results = completionsNoCompile(R"cpp(
+ void func() {
+ int sym1;
+ int sym2;
+ int xyz1;
+ int xyz2;
+ sy^
+ }
+ )cpp");
+ EXPECT_THAT(Results.Completions,
+ UnorderedElementsAre(Named("sym1"), Named("sym2")));
+}
+
+TEST(NoCompileCompletionTest, WithIndex) {
+ std::vector<Symbol> Syms = {func("xxx"), func("a::xxx"), func("ns::b::xxx"),
+ func("c::xxx"), func("ns::d::xxx")};
+ auto Results = completionsNoCompile(
+ R"cpp(
+ // Current-scopes, unqualified completion.
+ using namespace a;
+ namespace ns {
+ using namespace b;
+ void foo() {
+ xx^
+ }
+ )cpp",
+ Syms);
+ EXPECT_THAT(Results.Completions,
+ UnorderedElementsAre(AllOf(Qualifier(""), Scope("")),
+ AllOf(Qualifier(""), Scope("a::")),
+ AllOf(Qualifier(""), Scope("ns::b::"))));
+ CodeCompleteOptions Opts;
+ Opts.AllScopes = true;
+ Results = completionsNoCompile(
+ R"cpp(
+ // All-scopes unqualified completion.
+ using namespace a;
+ namespace ns {
+ using namespace b;
+ void foo() {
+ xx^
+ }
+ )cpp",
+ Syms, Opts);
+ EXPECT_THAT(Results.Completions,
+ UnorderedElementsAre(AllOf(Qualifier(""), Scope("")),
+ AllOf(Qualifier(""), Scope("a::")),
+ AllOf(Qualifier(""), Scope("ns::b::")),
+ AllOf(Qualifier("c::"), Scope("c::")),
+ AllOf(Qualifier("d::"), Scope("ns::d::"))));
+ Results = completionsNoCompile(
+ R"cpp(
+ // Qualified completion.
+ using namespace a;
+ namespace ns {
+ using namespace b;
+ void foo() {
+ b::xx^
+ }
+ )cpp",
+ Syms, Opts);
+ EXPECT_THAT(Results.Completions,
+ ElementsAre(AllOf(Qualifier(""), Scope("ns::b::"))));
+ Results = completionsNoCompile(
+ R"cpp(
+ // Absolutely qualified completion.
+ using namespace a;
+ namespace ns {
+ using namespace b;
+ void foo() {
+ ::a::xx^
+ }
+ )cpp",
+ Syms, Opts);
+ EXPECT_THAT(Results.Completions,
+ ElementsAre(AllOf(Qualifier(""), Scope("a::"))));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
diff --git a/unittests/clangd/CodeCompletionStringsTests.cpp b/clangd/unittests/CodeCompletionStringsTests.cpp
index eab35e14..43429c86 100644
--- a/unittests/clangd/CodeCompletionStringsTests.cpp
+++ b/clangd/unittests/CodeCompletionStringsTests.cpp
@@ -1,9 +1,8 @@
//===-- CodeCompletionStringsTests.cpp --------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clangd/ContextTests.cpp b/clangd/unittests/ContextTests.cpp
index d5cb3ce6..d760f4eb 100644
--- a/unittests/clangd/ContextTests.cpp
+++ b/clangd/unittests/ContextTests.cpp
@@ -1,9 +1,8 @@
//===-- ContextTests.cpp - Context tests ------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clangd/DexTests.cpp b/clangd/unittests/DexTests.cpp
index 078bae27..11aedec5 100644
--- a/unittests/clangd/DexTests.cpp
+++ b/clangd/unittests/DexTests.cpp
@@ -1,9 +1,8 @@
//===-- DexTests.cpp ---------------------------------*- C++ -*-----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -12,6 +11,7 @@
#include "TestIndex.h"
#include "index/Index.h"
#include "index/Merge.h"
+#include "index/SymbolID.h"
#include "index/dex/Dex.h"
#include "index/dex/Iterator.h"
#include "index/dex/Token.h"
@@ -25,6 +25,7 @@
using ::testing::AnyOf;
using ::testing::ElementsAre;
+using ::testing::IsEmpty;
using ::testing::UnorderedElementsAre;
namespace clang {
@@ -351,16 +352,16 @@ TEST(DexIterators, Optimizations) {
// Search token tests.
//===----------------------------------------------------------------------===//
-testing::Matcher<std::vector<Token>>
+::testing::Matcher<std::vector<Token>>
tokensAre(std::initializer_list<std::string> Strings, Token::Kind Kind) {
std::vector<Token> Tokens;
for (const auto &TokenData : Strings) {
Tokens.push_back(Token(Kind, TokenData));
}
- return testing::UnorderedElementsAreArray(Tokens);
+ return ::testing::UnorderedElementsAreArray(Tokens);
}
-testing::Matcher<std::vector<Token>>
+::testing::Matcher<std::vector<Token>>
trigramsAre(std::initializer_list<std::string> Trigrams) {
return tokensAre(Trigrams, Token::Kind::Trigram);
}
@@ -689,6 +690,63 @@ TEST(DexTests, Refs) {
EXPECT_THAT(Files, ElementsAre(AnyOf("foo.h", "foo.cc")));
}
+TEST(DexTest, PreferredTypesBoosting) {
+ auto Sym1 = symbol("t1");
+ Sym1.Type = "T1";
+ auto Sym2 = symbol("t2");
+ Sym2.Type = "T2";
+
+ std::vector<Symbol> Symbols{Sym1, Sym2};
+ Dex I(Symbols, RefSlab());
+
+ FuzzyFindRequest Req;
+ Req.AnyScope = true;
+ Req.Query = "t";
+ // The best candidate can change depending on the preferred type.
+ Req.Limit = 1;
+
+ Req.PreferredTypes = {Sym1.Type};
+ EXPECT_THAT(match(I, Req), ElementsAre("t1"));
+
+ Req.PreferredTypes = {Sym2.Type};
+ EXPECT_THAT(match(I, Req), ElementsAre("t2"));
+}
+
+TEST(DexTest, TemplateSpecialization) {
+ SymbolSlab::Builder B;
+
+ Symbol S = symbol("TempSpec");
+ S.ID = SymbolID("0");
+ B.insert(S);
+
+ S = symbol("TempSpec");
+ S.ID = SymbolID("1");
+ S.TemplateSpecializationArgs = "<int, bool>";
+ S.SymInfo.Properties = static_cast<index::SymbolPropertySet>(
+ index::SymbolProperty::TemplateSpecialization);
+ B.insert(S);
+
+ S = symbol("TempSpec");
+ S.ID = SymbolID("2");
+ S.TemplateSpecializationArgs = "<int, U>";
+ S.SymInfo.Properties = static_cast<index::SymbolPropertySet>(
+ index::SymbolProperty::TemplatePartialSpecialization);
+ B.insert(S);
+
+ auto I = dex::Dex::build(std::move(B).build(), RefSlab());
+ FuzzyFindRequest Req;
+ Req.AnyScope = true;
+
+ Req.Query = "TempSpec";
+ EXPECT_THAT(match(*I, Req),
+ UnorderedElementsAre("TempSpec", "TempSpec<int, bool>",
+ "TempSpec<int, U>"));
+
+ // FIXME: Add filtering for template argument list.
+ Req.Query = "TempSpec<int";
+ EXPECT_THAT(match(*I, Req), IsEmpty());
+}
+
} // namespace
} // namespace dex
} // namespace clangd
diff --git a/clangd/unittests/DiagnosticsTests.cpp b/clangd/unittests/DiagnosticsTests.cpp
new file mode 100644
index 00000000..826428ca
--- /dev/null
+++ b/clangd/unittests/DiagnosticsTests.cpp
@@ -0,0 +1,773 @@
+//===--- DiagnosticsTests.cpp ------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Annotations.h"
+#include "ClangdUnit.h"
+#include "Diagnostics.h"
+#include "Path.h"
+#include "Protocol.h"
+#include "SourceCode.h"
+#include "TestFS.h"
+#include "TestIndex.h"
+#include "TestTU.h"
+#include "index/MemIndex.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticSema.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <algorithm>
+
+namespace clang {
+namespace clangd {
+namespace {
+
+using ::testing::_;
+using ::testing::ElementsAre;
+using ::testing::Field;
+using ::testing::IsEmpty;
+using ::testing::Pair;
+using ::testing::UnorderedElementsAre;
+
+::testing::Matcher<const Diag &> WithFix(::testing::Matcher<Fix> FixMatcher) {
+ return Field(&Diag::Fixes, ElementsAre(FixMatcher));
+}
+
+::testing::Matcher<const Diag &> WithFix(::testing::Matcher<Fix> FixMatcher1,
+ ::testing::Matcher<Fix> FixMatcher2) {
+ return Field(&Diag::Fixes, UnorderedElementsAre(FixMatcher1, FixMatcher2));
+}
+
+::testing::Matcher<const Diag &>
+WithNote(::testing::Matcher<Note> NoteMatcher) {
+ return Field(&Diag::Notes, ElementsAre(NoteMatcher));
+}
+
+MATCHER_P2(Diag, Range, Message,
+ "Diag at " + llvm::to_string(Range) + " = [" + Message + "]") {
+ return arg.Range == Range && arg.Message == Message;
+}
+
+MATCHER_P3(Fix, Range, Replacement, Message,
+ "Fix " + llvm::to_string(Range) + " => " +
+ ::testing::PrintToString(Replacement) + " = [" + Message + "]") {
+ return arg.Message == Message && arg.Edits.size() == 1 &&
+ arg.Edits[0].range == Range && arg.Edits[0].newText == Replacement;
+}
+
+MATCHER_P(EqualToLSPDiag, LSPDiag,
+ "LSP diagnostic " + llvm::to_string(LSPDiag)) {
+ if (toJSON(arg) != toJSON(LSPDiag)) {
+ *result_listener << llvm::formatv("expected:\n{0:2}\ngot\n{1:2}",
+ toJSON(LSPDiag), toJSON(arg))
+ .str();
+ return false;
+ }
+ return true;
+}
+
+MATCHER_P(DiagSource, S, "") { return arg.Source == S; }
+MATCHER_P(DiagName, N, "") { return arg.Name == N; }
+
+MATCHER_P(EqualToFix, Fix, "LSP fix " + llvm::to_string(Fix)) {
+ if (arg.Message != Fix.Message)
+ return false;
+ if (arg.Edits.size() != Fix.Edits.size())
+ return false;
+ for (std::size_t I = 0; I < arg.Edits.size(); ++I) {
+ if (arg.Edits[I].range != Fix.Edits[I].range ||
+ arg.Edits[I].newText != Fix.Edits[I].newText)
+ return false;
+ }
+ return true;
+}
+
+// Helper function to make tests shorter.
+Position pos(int line, int character) {
+ Position Res;
+ Res.line = line;
+ Res.character = character;
+ return Res;
+}
+
+TEST(DiagnosticsTest, DiagnosticRanges) {
+ // Check we report correct ranges, including various edge-cases.
+ Annotations Test(R"cpp(
+ namespace test{};
+ void $decl[[foo]]();
+ int main() {
+ $typo[[go\
+o]]();
+ foo()$semicolon[[]]//with comments
+ $unk[[unknown]]();
+ double $type[[bar]] = "foo";
+ struct Foo { int x; }; Foo a;
+ a.$nomember[[y]];
+ test::$nomembernamespace[[test]];
+ }
+ )cpp");
+ EXPECT_THAT(
+ TestTU::withCode(Test.code()).build().getDiagnostics(),
+ ElementsAre(
+ // This range spans lines.
+ AllOf(Diag(Test.range("typo"),
+ "use of undeclared identifier 'goo'; did you mean 'foo'?"),
+ DiagSource(Diag::Clang), DiagName("undeclared_var_use_suggest"),
+ WithFix(
+ Fix(Test.range("typo"), "foo", "change 'go\\ o' to 'foo'")),
+ // This is a pretty normal range.
+ WithNote(Diag(Test.range("decl"), "'foo' declared here"))),
+ // This range is zero-width and insertion. Therefore make sure we are
+ // not expanding it into other tokens. Since we are not going to
+ // replace those.
+ AllOf(Diag(Test.range("semicolon"), "expected ';' after expression"),
+ WithFix(Fix(Test.range("semicolon"), ";", "insert ';'"))),
+ // This range isn't provided by clang, we expand to the token.
+ Diag(Test.range("unk"), "use of undeclared identifier 'unknown'"),
+ Diag(Test.range("type"),
+ "cannot initialize a variable of type 'double' with an lvalue "
+ "of type 'const char [4]'"),
+ Diag(Test.range("nomember"), "no member named 'y' in 'Foo'"),
+ Diag(Test.range("nomembernamespace"),
+ "no member named 'test' in namespace 'test'")));
+}
+
+TEST(DiagnosticsTest, FlagsMatter) {
+ Annotations Test("[[void]] main() {}");
+ auto TU = TestTU::withCode(Test.code());
+ EXPECT_THAT(TU.build().getDiagnostics(),
+ ElementsAre(AllOf(Diag(Test.range(), "'main' must return 'int'"),
+ WithFix(Fix(Test.range(), "int",
+ "change 'void' to 'int'")))));
+ // Same code built as C gets different diagnostics.
+ TU.Filename = "Plain.c";
+ EXPECT_THAT(
+ TU.build().getDiagnostics(),
+ ElementsAre(AllOf(
+ Diag(Test.range(), "return type of 'main' is not 'int'"),
+ WithFix(Fix(Test.range(), "int", "change return type to 'int'")))));
+}
+
+TEST(DiagnosticsTest, DiagnosticPreamble) {
+ Annotations Test(R"cpp(
+ #include $[["not-found.h"]]
+ )cpp");
+
+ auto TU = TestTU::withCode(Test.code());
+ EXPECT_THAT(TU.build().getDiagnostics(),
+ ElementsAre(::testing::AllOf(
+ Diag(Test.range(), "'not-found.h' file not found"),
+ DiagSource(Diag::Clang), DiagName("pp_file_not_found"))));
+}
+
+TEST(DiagnosticsTest, ClangTidy) {
+ Annotations Test(R"cpp(
+ #include $deprecated[["assert.h"]]
+
+ #define $macrodef[[SQUARE]](X) (X)*(X)
+ int main() {
+ return $doubled[[sizeof]](sizeof(int));
+ }
+ int square() {
+ int y = 4;
+ return SQUARE($macroarg[[++]]y);
+ }
+ )cpp");
+ auto TU = TestTU::withCode(Test.code());
+ TU.HeaderFilename = "assert.h"; // Suppress "not found" error.
+ TU.ClangTidyChecks =
+ "-*, bugprone-sizeof-expression, bugprone-macro-repeated-side-effects, "
+ "modernize-deprecated-headers";
+ EXPECT_THAT(
+ TU.build().getDiagnostics(),
+ UnorderedElementsAre(
+ AllOf(Diag(Test.range("deprecated"),
+ "inclusion of deprecated C++ header 'assert.h'; consider "
+ "using 'cassert' instead"),
+ DiagSource(Diag::ClangTidy),
+ DiagName("modernize-deprecated-headers"),
+ WithFix(Fix(Test.range("deprecated"), "<cassert>",
+ "change '\"assert.h\"' to '<cassert>'"))),
+ Diag(Test.range("doubled"),
+ "suspicious usage of 'sizeof(sizeof(...))'"),
+ AllOf(
+ Diag(Test.range("macroarg"),
+ "side effects in the 1st macro argument 'X' are repeated in "
+ "macro expansion"),
+ DiagSource(Diag::ClangTidy),
+ DiagName("bugprone-macro-repeated-side-effects"),
+ WithNote(
+ Diag(Test.range("macrodef"), "macro 'SQUARE' defined here"))),
+ Diag(Test.range("macroarg"),
+ "multiple unsequenced modifications to 'y'")));
+}
+
+TEST(DiagnosticsTest, Preprocessor) {
+ // This looks like a preamble, but there's an #else in the middle!
+ // Check that:
+ // - the #else doesn't generate diagnostics (we had this bug)
+ // - we get diagnostics from the taken branch
+ // - we get no diagnostics from the not taken branch
+ Annotations Test(R"cpp(
+ #ifndef FOO
+ #define FOO
+ int a = [[b]];
+ #else
+ int x = y;
+ #endif
+ )cpp");
+ EXPECT_THAT(
+ TestTU::withCode(Test.code()).build().getDiagnostics(),
+ ElementsAre(Diag(Test.range(), "use of undeclared identifier 'b'")));
+}
+
+TEST(DiagnosticsTest, InsideMacros) {
+ Annotations Test(R"cpp(
+ #define TEN 10
+ #define RET(x) return x + 10
+
+ int* foo() {
+ RET($foo[[0]]);
+ }
+ int* bar() {
+ return $bar[[TEN]];
+ }
+ )cpp");
+ EXPECT_THAT(TestTU::withCode(Test.code()).build().getDiagnostics(),
+ ElementsAre(Diag(Test.range("foo"),
+ "cannot initialize return object of type "
+ "'int *' with an rvalue of type 'int'"),
+ Diag(Test.range("bar"),
+ "cannot initialize return object of type "
+ "'int *' with an rvalue of type 'int'")));
+}
+
+TEST(DiagnosticsTest, NoFixItInMacro) {
+ Annotations Test(R"cpp(
+ #define Define(name) void name() {}
+
+ [[Define]](main)
+ )cpp");
+ auto TU = TestTU::withCode(Test.code());
+ EXPECT_THAT(TU.build().getDiagnostics(),
+ ElementsAre(AllOf(Diag(Test.range(), "'main' must return 'int'"),
+ Not(WithFix(_)))));
+}
+
+TEST(DiagnosticsTest, ToLSP) {
+ URIForFile MainFile =
+ URIForFile::canonicalize(testPath("foo/bar/main.cpp"), "");
+ URIForFile HeaderFile =
+ URIForFile::canonicalize(testPath("foo/bar/header.h"), "");
+
+ clangd::Diag D;
+ D.ID = clang::diag::err_enum_class_reference;
+ D.Name = "enum_class_reference";
+ D.Source = clangd::Diag::Clang;
+ D.Message = "something terrible happened";
+ D.Range = {pos(1, 2), pos(3, 4)};
+ D.InsideMainFile = true;
+ D.Severity = DiagnosticsEngine::Error;
+ D.File = "foo/bar/main.cpp";
+ D.AbsFile = MainFile.file();
+
+ clangd::Note NoteInMain;
+ NoteInMain.Message = "declared somewhere in the main file";
+ NoteInMain.Range = {pos(5, 6), pos(7, 8)};
+ NoteInMain.Severity = DiagnosticsEngine::Remark;
+ NoteInMain.File = "../foo/bar/main.cpp";
+ NoteInMain.InsideMainFile = true;
+ NoteInMain.AbsFile = MainFile.file();
+
+ D.Notes.push_back(NoteInMain);
+
+ clangd::Note NoteInHeader;
+ NoteInHeader.Message = "declared somewhere in the header file";
+ NoteInHeader.Range = {pos(9, 10), pos(11, 12)};
+ NoteInHeader.Severity = DiagnosticsEngine::Note;
+ NoteInHeader.File = "../foo/baz/header.h";
+ NoteInHeader.InsideMainFile = false;
+ NoteInHeader.AbsFile = HeaderFile.file();
+ D.Notes.push_back(NoteInHeader);
+
+ clangd::Fix F;
+ F.Message = "do something";
+ D.Fixes.push_back(F);
+
+ // Diagnostics should turn into these:
+ clangd::Diagnostic MainLSP;
+ MainLSP.range = D.Range;
+ MainLSP.severity = getSeverity(DiagnosticsEngine::Error);
+ MainLSP.code = "enum_class_reference";
+ MainLSP.source = "clang";
+ MainLSP.message =
+ R"(Something terrible happened (fix available)
+
+main.cpp:6:7: remark: declared somewhere in the main file
+
+../foo/baz/header.h:10:11:
+note: declared somewhere in the header file)";
+
+ clangd::Diagnostic NoteInMainLSP;
+ NoteInMainLSP.range = NoteInMain.Range;
+ NoteInMainLSP.severity = getSeverity(DiagnosticsEngine::Remark);
+ NoteInMainLSP.message = R"(Declared somewhere in the main file
+
+main.cpp:2:3: error: something terrible happened)";
+
+ ClangdDiagnosticOptions Opts;
+ // Transform diagnostics and check the results.
+ std::vector<std::pair<clangd::Diagnostic, std::vector<clangd::Fix>>> LSPDiags;
+ toLSPDiags(D, MainFile, Opts,
+ [&](clangd::Diagnostic LSPDiag, ArrayRef<clangd::Fix> Fixes) {
+ LSPDiags.push_back(
+ {std::move(LSPDiag),
+ std::vector<clangd::Fix>(Fixes.begin(), Fixes.end())});
+ });
+
+ EXPECT_THAT(
+ LSPDiags,
+ ElementsAre(Pair(EqualToLSPDiag(MainLSP), ElementsAre(EqualToFix(F))),
+ Pair(EqualToLSPDiag(NoteInMainLSP), IsEmpty())));
+ EXPECT_EQ(LSPDiags[0].first.code, "enum_class_reference");
+ EXPECT_EQ(LSPDiags[0].first.source, "clang");
+ EXPECT_EQ(LSPDiags[1].first.code, "");
+ EXPECT_EQ(LSPDiags[1].first.source, "");
+
+ // Same thing, but don't flatten notes into the main list.
+ LSPDiags.clear();
+ Opts.EmitRelatedLocations = true;
+ toLSPDiags(D, MainFile, Opts,
+ [&](clangd::Diagnostic LSPDiag, ArrayRef<clangd::Fix> Fixes) {
+ LSPDiags.push_back(
+ {std::move(LSPDiag),
+ std::vector<clangd::Fix>(Fixes.begin(), Fixes.end())});
+ });
+ MainLSP.message = "Something terrible happened (fix available)";
+ DiagnosticRelatedInformation NoteInMainDRI;
+ NoteInMainDRI.message = "Declared somewhere in the main file";
+ NoteInMainDRI.location.range = NoteInMain.Range;
+ NoteInMainDRI.location.uri = MainFile;
+ MainLSP.relatedInformation = {NoteInMainDRI};
+ DiagnosticRelatedInformation NoteInHeaderDRI;
+ NoteInHeaderDRI.message = "Declared somewhere in the header file";
+ NoteInHeaderDRI.location.range = NoteInHeader.Range;
+ NoteInHeaderDRI.location.uri = HeaderFile;
+ MainLSP.relatedInformation = {NoteInMainDRI, NoteInHeaderDRI};
+ EXPECT_THAT(LSPDiags, ElementsAre(Pair(EqualToLSPDiag(MainLSP),
+ ElementsAre(EqualToFix(F)))));
+}
+
+struct SymbolWithHeader {
+ std::string QName;
+ std::string DeclaringFile;
+ std::string IncludeHeader;
+};
+
+std::unique_ptr<SymbolIndex>
+buildIndexWithSymbol(llvm::ArrayRef<SymbolWithHeader> Syms) {
+ SymbolSlab::Builder Slab;
+ for (const auto &S : Syms) {
+ Symbol Sym = cls(S.QName);
+ Sym.Flags |= Symbol::IndexedForCodeCompletion;
+ Sym.CanonicalDeclaration.FileURI = S.DeclaringFile.c_str();
+ Sym.Definition.FileURI = S.DeclaringFile.c_str();
+ Sym.IncludeHeaders.emplace_back(S.IncludeHeader, 1);
+ Slab.insert(Sym);
+ }
+ return MemIndex::build(std::move(Slab).build(), RefSlab());
+}
+
+TEST(IncludeFixerTest, IncompleteType) {
+ Annotations Test(R"cpp(
+$insert[[]]namespace ns {
+ class X;
+ $nested[[X::]]Nested n;
+}
+class Y : $base[[public ns::X]] {};
+int main() {
+ ns::X *x;
+ x$access[[->]]f();
+}
+ )cpp");
+ auto TU = TestTU::withCode(Test.code());
+ auto Index = buildIndexWithSymbol(
+ {SymbolWithHeader{"ns::X", "unittest:///x.h", "\"x.h\""}});
+ TU.ExternalIndex = Index.get();
+
+ EXPECT_THAT(
+ TU.build().getDiagnostics(),
+ UnorderedElementsAre(
+ AllOf(Diag(Test.range("nested"),
+ "incomplete type 'ns::X' named in nested name specifier"),
+ WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+ "Add include \"x.h\" for symbol ns::X"))),
+ AllOf(Diag(Test.range("base"), "base class has incomplete type"),
+ WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+ "Add include \"x.h\" for symbol ns::X"))),
+ AllOf(Diag(Test.range("access"),
+ "member access into incomplete type 'ns::X'"),
+ WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+ "Add include \"x.h\" for symbol ns::X")))));
+}
+
+TEST(IncludeFixerTest, NoSuggestIncludeWhenNoDefinitionInHeader) {
+ Annotations Test(R"cpp(
+$insert[[]]namespace ns {
+ class X;
+}
+class Y : $base[[public ns::X]] {};
+int main() {
+ ns::X *x;
+ x$access[[->]]f();
+}
+ )cpp");
+ auto TU = TestTU::withCode(Test.code());
+ Symbol Sym = cls("ns::X");
+ Sym.Flags |= Symbol::IndexedForCodeCompletion;
+ Sym.CanonicalDeclaration.FileURI = "unittest:///x.h";
+ Sym.Definition.FileURI = "unittest:///x.cc";
+ Sym.IncludeHeaders.emplace_back("\"x.h\"", 1);
+
+ SymbolSlab::Builder Slab;
+ Slab.insert(Sym);
+ auto Index = MemIndex::build(std::move(Slab).build(), RefSlab());
+ TU.ExternalIndex = Index.get();
+
+ EXPECT_THAT(TU.build().getDiagnostics(),
+ UnorderedElementsAre(
+ Diag(Test.range("base"), "base class has incomplete type"),
+ Diag(Test.range("access"),
+ "member access into incomplete type 'ns::X'")));
+}
+
+TEST(IncludeFixerTest, Typo) {
+ Annotations Test(R"cpp(
+$insert[[]]namespace ns {
+void foo() {
+ $unqualified1[[X]] x;
+ // No fix if the unresolved type is used as specifier. (ns::)X::Nested will be
+ // considered the unresolved type.
+ $unqualified2[[X]]::Nested n;
+}
+}
+void bar() {
+ ns::$qualified1[[X]] x; // ns:: is valid.
+ ns::$qualified2[[X]](); // Error: no member in namespace
+
+ ::$global[[Global]] glob;
+}
+ )cpp");
+ auto TU = TestTU::withCode(Test.code());
+ auto Index = buildIndexWithSymbol(
+ {SymbolWithHeader{"ns::X", "unittest:///x.h", "\"x.h\""},
+ SymbolWithHeader{"Global", "unittest:///global.h", "\"global.h\""}});
+ TU.ExternalIndex = Index.get();
+
+ EXPECT_THAT(
+ TU.build().getDiagnostics(),
+ UnorderedElementsAre(
+ AllOf(Diag(Test.range("unqualified1"), "unknown type name 'X'"),
+ WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+ "Add include \"x.h\" for symbol ns::X"))),
+ Diag(Test.range("unqualified2"), "use of undeclared identifier 'X'"),
+ AllOf(Diag(Test.range("qualified1"),
+ "no type named 'X' in namespace 'ns'"),
+ WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+ "Add include \"x.h\" for symbol ns::X"))),
+ AllOf(Diag(Test.range("qualified2"),
+ "no member named 'X' in namespace 'ns'"),
+ WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+ "Add include \"x.h\" for symbol ns::X"))),
+ AllOf(Diag(Test.range("global"),
+ "no type named 'Global' in the global namespace"),
+ WithFix(Fix(Test.range("insert"), "#include \"global.h\"\n",
+ "Add include \"global.h\" for symbol Global")))));
+}
+
+TEST(IncludeFixerTest, MultipleMatchedSymbols) {
+ Annotations Test(R"cpp(
+$insert[[]]namespace na {
+namespace nb {
+void foo() {
+ $unqualified[[X]] x;
+}
+}
+}
+ )cpp");
+ auto TU = TestTU::withCode(Test.code());
+ auto Index = buildIndexWithSymbol(
+ {SymbolWithHeader{"na::X", "unittest:///a.h", "\"a.h\""},
+ SymbolWithHeader{"na::nb::X", "unittest:///b.h", "\"b.h\""}});
+ TU.ExternalIndex = Index.get();
+
+ EXPECT_THAT(TU.build().getDiagnostics(),
+ UnorderedElementsAre(AllOf(
+ Diag(Test.range("unqualified"), "unknown type name 'X'"),
+ WithFix(Fix(Test.range("insert"), "#include \"a.h\"\n",
+ "Add include \"a.h\" for symbol na::X"),
+ Fix(Test.range("insert"), "#include \"b.h\"\n",
+ "Add include \"b.h\" for symbol na::nb::X")))));
+}
+
+TEST(IncludeFixerTest, NoCrashMemebrAccess) {
+ Annotations Test(R"cpp(
+ struct X { int xyz; };
+ void g() { X x; x.$[[xy]] }
+ )cpp");
+ auto TU = TestTU::withCode(Test.code());
+ auto Index = buildIndexWithSymbol(
+ SymbolWithHeader{"na::X", "unittest:///a.h", "\"a.h\""});
+ TU.ExternalIndex = Index.get();
+
+ EXPECT_THAT(
+ TU.build().getDiagnostics(),
+ UnorderedElementsAre(Diag(Test.range(), "no member named 'xy' in 'X'")));
+}
+
+TEST(IncludeFixerTest, UseCachedIndexResults) {
+ // As index results for the identical request are cached, more than 5 fixes
+ // are generated.
+ Annotations Test(R"cpp(
+$insert[[]]void foo() {
+ $x1[[X]] x;
+ $x2[[X]] x;
+ $x3[[X]] x;
+ $x4[[X]] x;
+ $x5[[X]] x;
+ $x6[[X]] x;
+ $x7[[X]] x;
+}
+
+class X;
+void bar(X *x) {
+ x$a1[[->]]f();
+ x$a2[[->]]f();
+ x$a3[[->]]f();
+ x$a4[[->]]f();
+ x$a5[[->]]f();
+ x$a6[[->]]f();
+ x$a7[[->]]f();
+}
+ )cpp");
+ auto TU = TestTU::withCode(Test.code());
+ auto Index =
+ buildIndexWithSymbol(SymbolWithHeader{"X", "unittest:///a.h", "\"a.h\""});
+ TU.ExternalIndex = Index.get();
+
+ auto Parsed = TU.build();
+ for (const auto &D : Parsed.getDiagnostics()) {
+ EXPECT_EQ(D.Fixes.size(), 1u);
+ EXPECT_EQ(D.Fixes[0].Message,
+ std::string("Add include \"a.h\" for symbol X"));
+ }
+}
+
+TEST(IncludeFixerTest, UnresolvedNameAsSpecifier) {
+ Annotations Test(R"cpp(
+$insert[[]]namespace ns {
+}
+void g() { ns::$[[scope]]::X_Y(); }
+ )cpp");
+ auto TU = TestTU::withCode(Test.code());
+ auto Index = buildIndexWithSymbol(
+ SymbolWithHeader{"ns::scope::X_Y", "unittest:///x.h", "\"x.h\""});
+ TU.ExternalIndex = Index.get();
+
+ EXPECT_THAT(
+ TU.build().getDiagnostics(),
+ UnorderedElementsAre(AllOf(
+ Diag(Test.range(), "no member named 'scope' in namespace 'ns'"),
+ WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+ "Add include \"x.h\" for symbol ns::scope::X_Y")))));
+}
+
+TEST(IncludeFixerTest, UnresolvedSpecifierWithSemaCorrection) {
+ Annotations Test(R"cpp(
+$insert[[]]namespace clang {
+void f() {
+ // "clangd::" will be corrected to "clang::" by Sema.
+ $q1[[clangd]]::$x[[X]] x;
+ $q2[[clangd]]::$ns[[ns]]::Y y;
+}
+}
+ )cpp");
+ auto TU = TestTU::withCode(Test.code());
+ auto Index = buildIndexWithSymbol(
+ {SymbolWithHeader{"clang::clangd::X", "unittest:///x.h", "\"x.h\""},
+ SymbolWithHeader{"clang::clangd::ns::Y", "unittest:///y.h", "\"y.h\""}});
+ TU.ExternalIndex = Index.get();
+
+ EXPECT_THAT(
+ TU.build().getDiagnostics(),
+ UnorderedElementsAre(
+ AllOf(
+ Diag(Test.range("q1"), "use of undeclared identifier 'clangd'; "
+ "did you mean 'clang'?"),
+ WithFix(_, // change clangd to clang
+ Fix(Test.range("insert"), "#include \"x.h\"\n",
+ "Add include \"x.h\" for symbol clang::clangd::X"))),
+ AllOf(
+ Diag(Test.range("x"), "no type named 'X' in namespace 'clang'"),
+ WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+ "Add include \"x.h\" for symbol clang::clangd::X"))),
+ AllOf(
+ Diag(Test.range("q2"), "use of undeclared identifier 'clangd'; "
+ "did you mean 'clang'?"),
+ WithFix(
+ _, // change clangd to clangd
+ Fix(Test.range("insert"), "#include \"y.h\"\n",
+ "Add include \"y.h\" for symbol clang::clangd::ns::Y"))),
+ AllOf(Diag(Test.range("ns"),
+ "no member named 'ns' in namespace 'clang'"),
+ WithFix(Fix(
+ Test.range("insert"), "#include \"y.h\"\n",
+ "Add include \"y.h\" for symbol clang::clangd::ns::Y")))));
+}
+
+TEST(IncludeFixerTest, SpecifiedScopeIsNamespaceAlias) {
+ Annotations Test(R"cpp(
+$insert[[]]namespace a {}
+namespace b = a;
+namespace c {
+ b::$[[X]] x;
+}
+ )cpp");
+ auto TU = TestTU::withCode(Test.code());
+ auto Index = buildIndexWithSymbol(
+ SymbolWithHeader{"a::X", "unittest:///x.h", "\"x.h\""});
+ TU.ExternalIndex = Index.get();
+
+ EXPECT_THAT(TU.build().getDiagnostics(),
+ UnorderedElementsAre(AllOf(
+ Diag(Test.range(), "no type named 'X' in namespace 'a'"),
+ WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+ "Add include \"x.h\" for symbol a::X")))));
+}
+
+TEST(DiagsInHeaders, DiagInsideHeader) {
+ Annotations Main(R"cpp(
+ #include [["a.h"]]
+ void foo() {})cpp");
+ Annotations Header("[[no_type_spec]];");
+ TestTU TU = TestTU::withCode(Main.code());
+ TU.AdditionalFiles = {{"a.h", Header.code()}};
+ EXPECT_THAT(TU.build().getDiagnostics(),
+ UnorderedElementsAre(AllOf(
+ Diag(Main.range(), "in included file: C++ requires a "
+ "type specifier for all declarations"),
+ WithNote(Diag(Header.range(), "error occurred here")))));
+}
+
+TEST(DiagsInHeaders, DiagInTransitiveInclude) {
+ Annotations Main(R"cpp(
+ #include [["a.h"]]
+ void foo() {})cpp");
+ TestTU TU = TestTU::withCode(Main.code());
+ TU.AdditionalFiles = {{"a.h", "#include \"b.h\""}, {"b.h", "no_type_spec;"}};
+ EXPECT_THAT(TU.build().getDiagnostics(),
+ UnorderedElementsAre(
+ Diag(Main.range(), "in included file: C++ requires a "
+ "type specifier for all declarations")));
+}
+
+TEST(DiagsInHeaders, DiagInMultipleHeaders) {
+ Annotations Main(R"cpp(
+ #include $a[["a.h"]]
+ #include $b[["b.h"]]
+ void foo() {})cpp");
+ TestTU TU = TestTU::withCode(Main.code());
+ TU.AdditionalFiles = {{"a.h", "no_type_spec;"}, {"b.h", "no_type_spec;"}};
+ EXPECT_THAT(TU.build().getDiagnostics(),
+ UnorderedElementsAre(
+ Diag(Main.range("a"), "in included file: C++ requires a type "
+ "specifier for all declarations"),
+ Diag(Main.range("b"), "in included file: C++ requires a type "
+ "specifier for all declarations")));
+}
+
+TEST(DiagsInHeaders, PreferExpansionLocation) {
+ Annotations Main(R"cpp(
+ #include [["a.h"]]
+ #include "b.h"
+ void foo() {})cpp");
+ TestTU TU = TestTU::withCode(Main.code());
+ TU.AdditionalFiles = {{"a.h", "#include \"b.h\"\n"},
+ {"b.h", "#ifndef X\n#define X\nno_type_spec;\n#endif"}};
+ EXPECT_THAT(TU.build().getDiagnostics(),
+ UnorderedElementsAre(Diag(Main.range(),
+ "in included file: C++ requires a type "
+ "specifier for all declarations")));
+}
+
+TEST(DiagsInHeaders, PreferExpansionLocationMacros) {
+ Annotations Main(R"cpp(
+ #define X
+ #include "a.h"
+ #undef X
+ #include [["b.h"]]
+ void foo() {})cpp");
+ TestTU TU = TestTU::withCode(Main.code());
+ TU.AdditionalFiles = {{"a.h", "#include \"c.h\"\n"},
+ {"b.h", "#include \"c.h\"\n"},
+ {"c.h", "#ifndef X\n#define X\nno_type_spec;\n#endif"}};
+ EXPECT_THAT(TU.build().getDiagnostics(),
+ UnorderedElementsAre(
+ Diag(Main.range(), "in included file: C++ requires a "
+ "type specifier for all declarations")));
+}
+
+TEST(DiagsInHeaders, LimitDiagsOutsideMainFile) {
+ Annotations Main(R"cpp(
+ #include [["a.h"]]
+ #include "b.h"
+ void foo() {})cpp");
+ TestTU TU = TestTU::withCode(Main.code());
+ TU.AdditionalFiles = {{"a.h", "#include \"c.h\"\n"},
+ {"b.h", "#include \"c.h\"\n"},
+ {"c.h", R"cpp(
+ #ifndef X
+ #define X
+ no_type_spec_0;
+ no_type_spec_1;
+ no_type_spec_2;
+ no_type_spec_3;
+ no_type_spec_4;
+ no_type_spec_5;
+ no_type_spec_6;
+ no_type_spec_7;
+ no_type_spec_8;
+ no_type_spec_9;
+ no_type_spec_10;
+ #endif)cpp"}};
+ EXPECT_THAT(TU.build().getDiagnostics(),
+ UnorderedElementsAre(
+ Diag(Main.range(), "in included file: C++ requires a "
+ "type specifier for all declarations")));
+}
+
+TEST(DiagsInHeaders, OnlyErrorOrFatal) {
+ Annotations Main(R"cpp(
+ #include [["a.h"]]
+ void foo() {})cpp");
+ Annotations Header(R"cpp(
+ [[no_type_spec]];
+ int x = 5/0;)cpp");
+ TestTU TU = TestTU::withCode(Main.code());
+ TU.AdditionalFiles = {{"a.h", Header.code()}};
+ auto diags = TU.build().getDiagnostics();
+ EXPECT_THAT(TU.build().getDiagnostics(),
+ UnorderedElementsAre(AllOf(
+ Diag(Main.range(), "in included file: C++ requires "
+ "a type specifier for all declarations"),
+ WithNote(Diag(Header.range(), "error occurred here")))));
+}
+} // namespace
+
+} // namespace clangd
+} // namespace clang
diff --git a/unittests/clangd/DraftStoreTests.cpp b/clangd/unittests/DraftStoreTests.cpp
index 78057f3a..1840892c 100644
--- a/unittests/clangd/DraftStoreTests.cpp
+++ b/clangd/unittests/DraftStoreTests.cpp
@@ -1,9 +1,8 @@
//===-- DraftStoreTests.cpp -------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -241,7 +240,7 @@ TEST(DraftStoreIncrementalUpdateTest, StartCharOutOfRange) {
EXPECT_TRUE(!Result);
EXPECT_EQ(toString(Result.takeError()),
- "UTF-16 offset 100 is invalid for line 0");
+ "utf-16 offset 100 is invalid for line 0");
}
TEST(DraftStoreIncrementalUpdateTest, EndCharOutOfRange) {
@@ -262,7 +261,7 @@ TEST(DraftStoreIncrementalUpdateTest, EndCharOutOfRange) {
EXPECT_TRUE(!Result);
EXPECT_EQ(toString(Result.takeError()),
- "UTF-16 offset 100 is invalid for line 0");
+ "utf-16 offset 100 is invalid for line 0");
}
TEST(DraftStoreIncrementalUpdateTest, StartLineOutOfRange) {
@@ -336,7 +335,7 @@ TEST(DraftStoreIncrementalUpdateTest, InvalidRangeInASequence) {
EXPECT_TRUE(!Result);
EXPECT_EQ(toString(Result.takeError()),
- "UTF-16 offset 100 is invalid for line 0");
+ "utf-16 offset 100 is invalid for line 0");
Optional<std::string> Contents = DS.getDraft(File);
EXPECT_TRUE(Contents);
diff --git a/unittests/clangd/ExpectedTypeTest.cpp b/clangd/unittests/ExpectedTypeTest.cpp
index de3b486d..8d2d60eb 100644
--- a/unittests/clangd/ExpectedTypeTest.cpp
+++ b/clangd/unittests/ExpectedTypeTest.cpp
@@ -1,9 +1,8 @@
//===-- ExpectedTypeTest.cpp -----------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -13,7 +12,6 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "llvm/ADT/StringRef.h"
-#include "gmock/gmock-matchers.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
diff --git a/unittests/clangd/FSTests.cpp b/clangd/unittests/FSTests.cpp
index 6c0bfec5..044452ca 100644
--- a/unittests/clangd/FSTests.cpp
+++ b/clangd/unittests/FSTests.cpp
@@ -1,9 +1,8 @@
//===-- FSTests.cpp - File system related tests -----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clangd/FileDistanceTests.cpp b/clangd/unittests/FileDistanceTests.cpp
index 6d7d4777..30035829 100644
--- a/unittests/clangd/FileDistanceTests.cpp
+++ b/clangd/unittests/FileDistanceTests.cpp
@@ -1,9 +1,8 @@
//===-- FileDistanceTests.cpp ------------------------*- C++ -*-----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clangd/FileIndexTests.cpp b/clangd/unittests/FileIndexTests.cpp
index c3b11aef..142e2554 100644
--- a/unittests/clangd/FileIndexTests.cpp
+++ b/clangd/unittests/FileIndexTests.cpp
@@ -1,9 +1,8 @@
//===-- FileIndexTests.cpp ---------------------------*- C++ -*-----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -13,10 +12,10 @@
#include "SyncAPI.h"
#include "TestFS.h"
#include "TestTU.h"
+#include "index/CanonicalIncludes.h"
#include "index/FileIndex.h"
#include "index/Index.h"
#include "clang/Frontend/CompilerInvocation.h"
-#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Frontend/Utils.h"
#include "clang/Index/IndexSymbol.h"
#include "clang/Lex/Preprocessor.h"
@@ -24,13 +23,13 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using testing::_;
-using testing::AllOf;
-using testing::Contains;
-using testing::ElementsAre;
-using testing::IsEmpty;
-using testing::Pair;
-using testing::UnorderedElementsAre;
+using ::testing::_;
+using ::testing::AllOf;
+using ::testing::Contains;
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
+using ::testing::Pair;
+using ::testing::UnorderedElementsAre;
MATCHER_P(RefRange, Range, "") {
return std::make_tuple(arg.Location.Start.line(), arg.Location.Start.column(),
@@ -50,9 +49,9 @@ MATCHER_P(QName, N, "") { return (arg.Scope + arg.Name).str() == N; }
namespace clang {
namespace clangd {
namespace {
-testing::Matcher<const RefSlab &>
-RefsAre(std::vector<testing::Matcher<Ref>> Matchers) {
- return ElementsAre(testing::Pair(_, UnorderedElementsAreArray(Matchers)));
+::testing::Matcher<const RefSlab &>
+RefsAre(std::vector<::testing::Matcher<Ref>> Matchers) {
+ return ElementsAre(::testing::Pair(_, UnorderedElementsAreArray(Matchers)));
}
Symbol symbol(llvm::StringRef ID) {
@@ -148,8 +147,8 @@ void update(FileIndex &M, llvm::StringRef Basename, llvm::StringRef Code) {
File.HeaderFilename = (Basename + ".h").str();
File.HeaderCode = Code;
auto AST = File.build();
- M.updatePreamble(File.Filename, AST.getASTContext(),
- AST.getPreprocessorPtr());
+ M.updatePreamble(File.Filename, AST.getASTContext(), AST.getPreprocessorPtr(),
+ AST.getCanonicalIncludes());
}
TEST(FileIndexTest, CustomizedURIScheme) {
@@ -200,13 +199,27 @@ TEST(FileIndexTest, ClassMembers) {
QName("X::f")));
}
-TEST(FileIndexTest, NoIncludeCollected) {
+TEST(FileIndexTest, IncludeCollected) {
FileIndex M;
- update(M, "f", "class string {};");
+ update(
+ M, "f",
+ "// IWYU pragma: private, include <the/good/header.h>\nclass string {};");
auto Symbols = runFuzzyFind(M, "");
EXPECT_THAT(Symbols, ElementsAre(_));
- EXPECT_THAT(Symbols.begin()->IncludeHeaders, IsEmpty());
+ EXPECT_THAT(Symbols.begin()->IncludeHeaders.front().IncludeHeader,
+ "<the/good/header.h>");
+}
+
+TEST(FileIndexTest, HasSystemHeaderMappingsInPreamble) {
+ TestTU TU;
+ TU.HeaderCode = "class Foo{};";
+ TU.HeaderFilename = "algorithm";
+
+ auto Symbols = runFuzzyFind(*TU.index(), "");
+ EXPECT_THAT(Symbols, ElementsAre(_));
+ EXPECT_THAT(Symbols.begin()->IncludeHeaders.front().IncludeHeader,
+ "<algorithm>");
}
TEST(FileIndexTest, TemplateParamsInLabel) {
@@ -270,11 +283,12 @@ TEST(FileIndexTest, RebuildWithPreamble) {
bool IndexUpdated = false;
buildPreamble(
FooCpp, *CI, /*OldPreamble=*/nullptr, tooling::CompileCommand(), PI,
- std::make_shared<PCHContainerOperations>(), /*StoreInMemory=*/true,
- [&](ASTContext &Ctx, std::shared_ptr<Preprocessor> PP) {
+ /*StoreInMemory=*/true,
+ [&](ASTContext &Ctx, std::shared_ptr<Preprocessor> PP,
+ const CanonicalIncludes &CanonIncludes) {
EXPECT_FALSE(IndexUpdated) << "Expected only a single index update";
IndexUpdated = true;
- Index.updatePreamble(FooCpp, Ctx, std::move(PP));
+ Index.updatePreamble(FooCpp, Ctx, std::move(PP), CanonIncludes);
});
ASSERT_TRUE(IndexUpdated);
@@ -333,49 +347,23 @@ TEST(FileIndexTest, CollectMacros) {
}
TEST(FileIndexTest, ReferencesInMainFileWithPreamble) {
- const std::string Header = R"cpp(
- class Foo {};
- )cpp";
+ TestTU TU;
+ TU.HeaderCode = "class Foo{};";
Annotations Main(R"cpp(
#include "foo.h"
void f() {
[[Foo]] foo;
}
)cpp");
- auto MainFile = testPath("foo.cpp");
- auto HeaderFile = testPath("foo.h");
- std::vector<const char *> Cmd = {"clang", "-xc++", MainFile.c_str()};
- // Preparse ParseInputs.
- ParseInputs PI;
- PI.CompileCommand.Directory = testRoot();
- PI.CompileCommand.Filename = MainFile;
- PI.CompileCommand.CommandLine = {Cmd.begin(), Cmd.end()};
- PI.Contents = Main.code();
- PI.FS = buildTestFS({{MainFile, Main.code()}, {HeaderFile, Header}});
-
- // Prepare preamble.
- auto CI = buildCompilerInvocation(PI);
- auto PreambleData = buildPreamble(
- MainFile, *buildCompilerInvocation(PI), /*OldPreamble=*/nullptr,
- tooling::CompileCommand(), PI, std::make_shared<PCHContainerOperations>(),
- /*StoreInMemory=*/true,
- [&](ASTContext &Ctx, std::shared_ptr<Preprocessor> PP) {});
- // Build AST for main file with preamble.
- auto AST =
- ParsedAST::build(createInvocationFromCommandLine(Cmd), PreambleData,
- llvm::MemoryBuffer::getMemBufferCopy(Main.code()),
- std::make_shared<PCHContainerOperations>(), PI.FS);
- ASSERT_TRUE(AST);
+ TU.Code = Main.code();
+ auto AST = TU.build();
FileIndex Index;
- Index.updateMain(MainFile, *AST);
-
- auto Foo = findSymbol(TestTU::withHeaderCode(Header).headerSymbols(), "Foo");
- RefsRequest Request;
- Request.IDs.insert(Foo.ID);
+ Index.updateMain(testPath(TU.Filename), AST);
// Expect to see references in main file, references in headers are excluded
// because we only index main AST.
- EXPECT_THAT(getRefs(Index, Foo.ID), RefsAre({RefRange(Main.range())}));
+ EXPECT_THAT(getRefs(Index, findSymbol(TU.headerSymbols(), "Foo").ID),
+ RefsAre({RefRange(Main.range())}));
}
} // namespace
diff --git a/unittests/clangd/FindSymbolsTests.cpp b/clangd/unittests/FindSymbolsTests.cpp
index 9b631596..f3112371 100644
--- a/unittests/clangd/FindSymbolsTests.cpp
+++ b/clangd/unittests/FindSymbolsTests.cpp
@@ -1,9 +1,8 @@
//===-- FindSymbolsTests.cpp -------------------------*- C++ -*------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "Annotations.h"
@@ -45,7 +44,7 @@ MATCHER_P(SymRange, Range, "") { return arg.location.range == Range; }
// GMock helpers for matching DocumentSymbol.
MATCHER_P(SymNameRange, Range, "") { return arg.selectionRange == Range; }
template <class... ChildMatchers>
-testing::Matcher<DocumentSymbol> Children(ChildMatchers... ChildrenM) {
+::testing::Matcher<DocumentSymbol> Children(ChildMatchers... ChildrenM) {
return Field(&DocumentSymbol::children, ElementsAre(ChildrenM...));
}
@@ -88,13 +87,16 @@ protected:
} // namespace
-TEST_F(WorkspaceSymbolsTest, NoMacro) {
+TEST_F(WorkspaceSymbolsTest, Macros) {
addFile("foo.cpp", R"cpp(
- #define MACRO X
- )cpp");
-
- // Macros are not in the index.
- EXPECT_THAT(getSymbols("macro"), IsEmpty());
+ #define MACRO X
+ )cpp");
+
+ // LSP's SymbolKind doesn't have a "Macro" kind, and
+ // indexSymbolKindToSymbolKind() currently maps macros
+ // to SymbolKind::String.
+ EXPECT_THAT(getSymbols("macro"),
+ ElementsAre(AllOf(QName("MACRO"), WithKind(SymbolKind::String))));
}
TEST_F(WorkspaceSymbolsTest, NoLocals) {
@@ -145,8 +147,7 @@ TEST_F(WorkspaceSymbolsTest, InMainFile) {
int test() {}
static test2() {}
)cpp");
- EXPECT_THAT(getSymbols("test"),
- ElementsAre(QName("test"), QName("test2")));
+ EXPECT_THAT(getSymbols("test"), ElementsAre(QName("test"), QName("test2")));
}
TEST_F(WorkspaceSymbolsTest, Namespaces) {
@@ -299,6 +300,23 @@ TEST_F(WorkspaceSymbolsTest, WithLimit) {
EXPECT_THAT(getSymbols("foo"), ElementsAre(QName("foo")));
}
+TEST_F(WorkspaceSymbolsTest, TempSpecs) {
+ addFile("foo.h", R"cpp(
+ template <typename T, typename U, int X = 5> class Foo {};
+ template <typename T> class Foo<int, T> {};
+ template <> class Foo<bool, int> {};
+ template <> class Foo<bool, int, 3> {};
+ )cpp");
+ // Foo is higher ranked because of exact name match.
+ EXPECT_THAT(
+ getSymbols("Foo"),
+ UnorderedElementsAre(
+ AllOf(QName("Foo"), WithKind(SymbolKind::Class)),
+ AllOf(QName("Foo<int, T>"), WithKind(SymbolKind::Class)),
+ AllOf(QName("Foo<bool, int>"), WithKind(SymbolKind::Class)),
+ AllOf(QName("Foo<bool, int, 3>"), WithKind(SymbolKind::Class))));
+}
+
namespace {
class DocumentSymbolsTest : public ::testing::Test {
public:
@@ -366,9 +384,6 @@ TEST_F(DocumentSymbolsTest, BasicSymbols) {
// Namespace alias
namespace baz = bar;
- // FIXME: using declaration is not supported as the IndexAction will ignore
- // implicit declarations (the implicit using shadow declaration) by default,
- // and there is no way to customize this behavior at the moment.
using bar::v2;
} // namespace foo
)");
@@ -413,7 +428,7 @@ TEST_F(DocumentSymbolsTest, BasicSymbols) {
Children()))),
AllOf(WithName("baz"), WithKind(SymbolKind::Namespace),
Children()),
- AllOf(WithName("v2"), WithKind(SymbolKind::Variable))))}));
+ AllOf(WithName("v2"), WithKind(SymbolKind::Namespace))))}));
}
TEST_F(DocumentSymbolsTest, DeclarationDefinition) {
@@ -526,11 +541,9 @@ TEST_F(DocumentSymbolsTest, Template) {
AllOf(WithName("Tmpl<double>"), WithKind(SymbolKind::Struct),
Children()),
AllOf(WithName("funcTmpl"), Children()),
- // FIXME(ibiryukov): template args should be <int> to match the code.
- AllOf(WithName("funcTmpl<int, double, float>"), Children()),
+ AllOf(WithName("funcTmpl<int>"), Children()),
AllOf(WithName("varTmpl"), Children()),
- // FIXME(ibiryukov): template args should be <int> to match the code.
- AllOf(WithName("varTmpl<int, double>"), Children())));
+ AllOf(WithName("varTmpl<int>"), Children())));
}
TEST_F(DocumentSymbolsTest, Namespaces) {
@@ -560,7 +573,7 @@ TEST_F(DocumentSymbolsTest, Namespaces) {
)cpp");
EXPECT_THAT(
getSymbols(FilePath),
- ElementsAreArray<testing::Matcher<DocumentSymbol>>(
+ ElementsAreArray<::testing::Matcher<DocumentSymbol>>(
{AllOf(WithName("ans1"),
Children(AllOf(WithName("ai1"), Children()),
AllOf(WithName("ans2"), Children(WithName("ai2"))))),
@@ -654,5 +667,22 @@ TEST_F(DocumentSymbolsTest, UsingDirectives) {
WithName("using namespace ns_alias")));
}
+TEST_F(DocumentSymbolsTest, TempSpecs) {
+ addFile("foo.cpp", R"cpp(
+ template <typename T, typename U, int X = 5> class Foo {};
+ template <typename T> class Foo<int, T> {};
+ template <> class Foo<bool, int> {};
+ template <> class Foo<bool, int, 3> {};
+ )cpp");
+ // Foo is higher ranked because of exact name match.
+ EXPECT_THAT(
+ getSymbols("foo.cpp"),
+ UnorderedElementsAre(
+ AllOf(WithName("Foo"), WithKind(SymbolKind::Class)),
+ AllOf(WithName("Foo<int, T>"), WithKind(SymbolKind::Class)),
+ AllOf(WithName("Foo<bool, int>"), WithKind(SymbolKind::Class)),
+ AllOf(WithName("Foo<bool, int, 3>"), WithKind(SymbolKind::Class))));
+}
+
} // namespace clangd
} // namespace clang
diff --git a/unittests/clangd/FunctionTests.cpp b/clangd/unittests/FunctionTests.cpp
index 613190dd..0cd8b791 100644
--- a/unittests/clangd/FunctionTests.cpp
+++ b/clangd/unittests/FunctionTests.cpp
@@ -1,9 +1,8 @@
-//===-- FunctionsTests.cpp ------------------------------------------------===//
+//===-- FunctionTests.cpp -------------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clangd/FuzzyMatchTests.cpp b/clangd/unittests/FuzzyMatchTests.cpp
index 1c4062ca..33d202b4 100644
--- a/unittests/clangd/FuzzyMatchTests.cpp
+++ b/clangd/unittests/FuzzyMatchTests.cpp
@@ -1,9 +1,8 @@
//===-- FuzzyMatchTests.cpp - String fuzzy matcher tests --------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -16,7 +15,7 @@
namespace clang {
namespace clangd {
namespace {
-using testing::Not;
+using ::testing::Not;
struct ExpectedMatch {
// Annotations are optional, and will not be asserted if absent.
@@ -44,7 +43,7 @@ private:
llvm::Optional<llvm::StringRef> Annotated;
};
-struct MatchesMatcher : public testing::MatcherInterface<llvm::StringRef> {
+struct MatchesMatcher : public ::testing::MatcherInterface<llvm::StringRef> {
ExpectedMatch Candidate;
llvm::Optional<float> Score;
MatchesMatcher(ExpectedMatch Candidate, llvm::Optional<float> Score)
@@ -57,7 +56,7 @@ struct MatchesMatcher : public testing::MatcherInterface<llvm::StringRef> {
}
bool MatchAndExplain(llvm::StringRef Pattern,
- testing::MatchResultListener *L) const override {
+ ::testing::MatchResultListener *L) const override {
std::unique_ptr<llvm::raw_ostream> OS(
L->stream()
? (llvm::raw_ostream *)(new llvm::raw_os_ostream(*L->stream()))
@@ -66,15 +65,15 @@ struct MatchesMatcher : public testing::MatcherInterface<llvm::StringRef> {
auto Result = Matcher.match(Candidate.Word);
auto AnnotatedMatch = Matcher.dumpLast(*OS << "\n");
return Result && Candidate.accepts(AnnotatedMatch) &&
- (!Score || testing::Value(*Result, testing::FloatEq(*Score)));
+ (!Score || ::testing::Value(*Result, ::testing::FloatEq(*Score)));
}
};
// Accepts patterns that match a given word, optionally requiring a score.
// Dumps the debug tables on match failure.
-testing::Matcher<llvm::StringRef> matches(llvm::StringRef M,
- llvm::Optional<float> Score = {}) {
- return testing::MakeMatcher<llvm::StringRef>(new MatchesMatcher(M, Score));
+::testing::Matcher<llvm::StringRef> matches(llvm::StringRef M,
+ llvm::Optional<float> Score = {}) {
+ return ::testing::MakeMatcher<llvm::StringRef>(new MatchesMatcher(M, Score));
}
TEST(FuzzyMatch, Matches) {
@@ -180,7 +179,7 @@ TEST(FuzzyMatch, Matches) {
EXPECT_THAT("std", Not(matches("pthread_condattr_setpshared")));
}
-struct RankMatcher : public testing::MatcherInterface<llvm::StringRef> {
+struct RankMatcher : public ::testing::MatcherInterface<llvm::StringRef> {
std::vector<ExpectedMatch> RankedStrings;
RankMatcher(std::initializer_list<ExpectedMatch> RankedStrings)
: RankedStrings(RankedStrings) {}
@@ -194,7 +193,7 @@ struct RankMatcher : public testing::MatcherInterface<llvm::StringRef> {
}
bool MatchAndExplain(llvm::StringRef Pattern,
- testing::MatchResultListener *L) const override {
+ ::testing::MatchResultListener *L) const override {
std::unique_ptr<llvm::raw_ostream> OS(
L->stream()
? (llvm::raw_ostream *)(new llvm::raw_os_ostream(*L->stream()))
@@ -237,8 +236,8 @@ struct RankMatcher : public testing::MatcherInterface<llvm::StringRef> {
// Accepts patterns that match all the strings and rank them in the given order.
// Dumps the debug tables on match failure.
template <typename... T>
-testing::Matcher<llvm::StringRef> ranks(T... RankedStrings) {
- return testing::MakeMatcher<llvm::StringRef>(
+::testing::Matcher<llvm::StringRef> ranks(T... RankedStrings) {
+ return ::testing::MakeMatcher<llvm::StringRef>(
new RankMatcher{ExpectedMatch(RankedStrings)...});
}
@@ -248,6 +247,8 @@ TEST(FuzzyMatch, Ranking) {
EXPECT_THAT("foo", ranks("[foo]", "[Foo]"));
EXPECT_THAT("onMes",
ranks("[onMes]sage", "[onmes]sage", "[on]This[M]ega[Es]capes"));
+ EXPECT_THAT("onmes",
+ ranks("[onmes]sage", "[onMes]sage", "[on]This[M]ega[Es]capes"));
EXPECT_THAT("CC", ranks("[C]amel[C]ase", "[c]amel[C]ase"));
EXPECT_THAT("cC", ranks("[c]amel[C]ase", "[C]amel[C]ase"));
EXPECT_THAT("p", ranks("[p]", "[p]arse", "[p]osix", "[p]afdsa", "[p]ath"));
@@ -271,12 +272,18 @@ TEST(FuzzyMatch, Ranking) {
// Verify some bounds so we know scores fall in the right range.
// Testing exact scores is fragile, so we prefer Ranking tests.
TEST(FuzzyMatch, Scoring) {
- EXPECT_THAT("abs", matches("[a]w[B]xYz[S]", 0.f));
+ EXPECT_THAT("abs", matches("[a]w[B]xYz[S]", 7.f / 12.f));
EXPECT_THAT("abs", matches("[abs]l", 1.f));
EXPECT_THAT("abs", matches("[abs]", 2.f));
EXPECT_THAT("Abs", matches("[abs]", 2.f));
}
+TEST(FuzzyMatch, InitialismAndPrefix) {
+ // We want these scores to be roughly the same.
+ EXPECT_THAT("up", matches("[u]nique_[p]tr", 3.f / 4.f));
+ EXPECT_THAT("up", matches("[up]per_bound", 1.f));
+}
+
// Returns pretty-printed segmentation of Text.
// e.g. std::basic_string --> +-- +---- +-----
std::string segment(llvm::StringRef Text) {
diff --git a/unittests/clangd/GlobalCompilationDatabaseTests.cpp b/clangd/unittests/GlobalCompilationDatabaseTests.cpp
index b0052c75..7c7993cc 100644
--- a/unittests/clangd/GlobalCompilationDatabaseTests.cpp
+++ b/clangd/unittests/GlobalCompilationDatabaseTests.cpp
@@ -1,9 +1,8 @@
//===-- GlobalCompilationDatabaseTests.cpp ----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -17,15 +16,18 @@
namespace clang {
namespace clangd {
namespace {
+using ::testing::AllOf;
+using ::testing::Contains;
using ::testing::ElementsAre;
using ::testing::EndsWith;
+using ::testing::Not;
TEST(GlobalCompilationDatabaseTest, FallbackCommand) {
DirectoryBasedGlobalCompilationDatabase DB(None);
auto Cmd = DB.getFallbackCommand(testPath("foo/bar.cc"));
EXPECT_EQ(Cmd.Directory, testPath("foo"));
- EXPECT_THAT(Cmd.CommandLine, ElementsAre(
- EndsWith("clang"), testPath("foo/bar.cc")));
+ EXPECT_THAT(Cmd.CommandLine,
+ ElementsAre(EndsWith("clang"), testPath("foo/bar.cc")));
EXPECT_EQ(Cmd.Output, "");
// .h files have unknown language, so they are parsed liberally as obj-c++.
@@ -65,17 +67,19 @@ protected:
};
TEST_F(OverlayCDBTest, GetCompileCommand) {
- OverlayCDB CDB(Base.get());
- EXPECT_EQ(CDB.getCompileCommand(testPath("foo.cc")),
- Base->getCompileCommand(testPath("foo.cc")));
+ OverlayCDB CDB(Base.get(), {}, std::string(""));
+ EXPECT_THAT(CDB.getCompileCommand(testPath("foo.cc"))->CommandLine,
+ AllOf(Contains(testPath("foo.cc")), Contains("-DA=1")));
EXPECT_EQ(CDB.getCompileCommand(testPath("missing.cc")), llvm::None);
auto Override = cmd(testPath("foo.cc"), "-DA=3");
CDB.setCompileCommand(testPath("foo.cc"), Override);
- EXPECT_EQ(CDB.getCompileCommand(testPath("foo.cc")), Override);
+ EXPECT_THAT(CDB.getCompileCommand(testPath("foo.cc"))->CommandLine,
+ Contains("-DA=3"));
EXPECT_EQ(CDB.getCompileCommand(testPath("missing.cc")), llvm::None);
CDB.setCompileCommand(testPath("missing.cc"), Override);
- EXPECT_EQ(CDB.getCompileCommand(testPath("missing.cc")), Override);
+ EXPECT_THAT(CDB.getCompileCommand(testPath("missing.cc"))->CommandLine,
+ Contains("-DA=3"));
}
TEST_F(OverlayCDBTest, GetFallbackCommand) {
@@ -85,11 +89,12 @@ TEST_F(OverlayCDBTest, GetFallbackCommand) {
}
TEST_F(OverlayCDBTest, NoBase) {
- OverlayCDB CDB(nullptr, {"-DA=6"});
+ OverlayCDB CDB(nullptr, {"-DA=6"}, std::string(""));
EXPECT_EQ(CDB.getCompileCommand(testPath("bar.cc")), None);
auto Override = cmd(testPath("bar.cc"), "-DA=5");
CDB.setCompileCommand(testPath("bar.cc"), Override);
- EXPECT_EQ(CDB.getCompileCommand(testPath("bar.cc")), Override);
+ EXPECT_THAT(CDB.getCompileCommand(testPath("bar.cc"))->CommandLine,
+ Contains("-DA=5"));
EXPECT_THAT(CDB.getFallbackCommand(testPath("foo.cc")).CommandLine,
ElementsAre(EndsWith("clang"), testPath("foo.cc"), "-DA=6"));
@@ -112,6 +117,35 @@ TEST_F(OverlayCDBTest, Watch) {
ElementsAre("A.cpp"), ElementsAre("C.cpp")));
}
+TEST_F(OverlayCDBTest, Adjustments) {
+ OverlayCDB CDB(Base.get(), {}, std::string(""));
+ auto Cmd = CDB.getCompileCommand(testPath("foo.cc")).getValue();
+ // Delete the file name.
+ Cmd.CommandLine.pop_back();
+
+ // Check dependency file commands are dropped.
+ Cmd.CommandLine.push_back("-MF");
+ Cmd.CommandLine.push_back("random-dependency");
+
+ // Check plugin-related commands are dropped.
+ Cmd.CommandLine.push_back("-Xclang");
+ Cmd.CommandLine.push_back("-load");
+ Cmd.CommandLine.push_back("-Xclang");
+ Cmd.CommandLine.push_back("random-plugin");
+
+ Cmd.CommandLine.push_back("-DA=5");
+ Cmd.CommandLine.push_back(Cmd.Filename);
+
+ CDB.setCompileCommand(testPath("foo.cc"), Cmd);
+
+ EXPECT_THAT(CDB.getCompileCommand(testPath("foo.cc"))->CommandLine,
+ AllOf(Contains("-fsyntax-only"), Contains("-DA=5"),
+ Contains(testPath("foo.cc")), Not(Contains("-MF")),
+ Not(Contains("random-dependency")),
+ Not(Contains("-Xclang")), Not(Contains("-load")),
+ Not(Contains("random-plugin"))));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
diff --git a/unittests/clangd/HeadersTests.cpp b/clangd/unittests/HeadersTests.cpp
index 79f0b9cb..e1591abb 100644
--- a/unittests/clangd/HeadersTests.cpp
+++ b/clangd/unittests/HeadersTests.cpp
@@ -1,9 +1,8 @@
//===-- HeadersTests.cpp - Include headers unit tests -----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -16,6 +15,7 @@
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "llvm/Support/Path.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -52,8 +52,8 @@ private:
CI->getDiagnosticOpts().IgnoreWarnings = true;
auto Clang = prepareCompilerInstance(
std::move(CI), /*Preamble=*/nullptr,
- llvm::MemoryBuffer::getMemBuffer(FS.Files[MainFile], MainFile),
- std::make_shared<PCHContainerOperations>(), VFS, IgnoreDiags);
+ llvm::MemoryBuffer::getMemBuffer(FS.Files[MainFile], MainFile), VFS,
+ IgnoreDiags);
EXPECT_FALSE(Clang->getFrontendOpts().Inputs.empty());
return Clang;
@@ -91,14 +91,13 @@ protected:
IncludeInserter Inserter(MainFile, /*Code=*/"", format::getLLVMStyle(),
CDB.getCompileCommand(MainFile)->Directory,
- Clang->getPreprocessor().getHeaderSearchInfo());
+ &Clang->getPreprocessor().getHeaderSearchInfo());
for (const auto &Inc : Inclusions)
Inserter.addExisting(Inc);
- auto Declaring = ToHeaderFile(Original);
auto Inserted = ToHeaderFile(Preferred);
- if (!Inserter.shouldInsertInclude(Declaring, Inserted))
+ if (!Inserter.shouldInsertInclude(Original, Inserted))
return "";
- std::string Path = Inserter.calculateIncludePath(Declaring, Inserted);
+ std::string Path = Inserter.calculateIncludePath(Inserted);
Action.EndSourceFile();
return Path;
}
@@ -111,7 +110,7 @@ protected:
IncludeInserter Inserter(MainFile, /*Code=*/"", format::getLLVMStyle(),
CDB.getCompileCommand(MainFile)->Directory,
- Clang->getPreprocessor().getHeaderSearchInfo());
+ &Clang->getPreprocessor().getHeaderSearchInfo());
auto Edit = Inserter.insert(VerbatimHeader);
Action.EndSourceFile();
return Edit;
@@ -215,10 +214,16 @@ TEST_F(HeadersTest, DoNotInsertIfInSameFile) {
TEST_F(HeadersTest, ShortenedInclude) {
std::string BarHeader = testPath("sub/bar.h");
EXPECT_EQ(calculate(BarHeader), "\"bar.h\"");
+
+ SearchDirArg = (llvm::Twine("-I") + Subdir + "/..").str();
+ CDB.ExtraClangFlags = {SearchDirArg.c_str()};
+ BarHeader = testPath("sub/bar.h");
+ EXPECT_EQ(calculate(BarHeader), "\"sub/bar.h\"");
}
TEST_F(HeadersTest, NotShortenedInclude) {
- std::string BarHeader = testPath("sub-2/bar.h");
+ std::string BarHeader =
+ llvm::sys::path::convert_to_slash(testPath("sub-2/bar.h"));
EXPECT_EQ(calculate(BarHeader, ""), "\"" + BarHeader + "\"");
}
@@ -253,6 +258,22 @@ TEST_F(HeadersTest, PreferInserted) {
EXPECT_TRUE(StringRef(Edit->newText).contains("<y>"));
}
+TEST(Headers, NoHeaderSearchInfo) {
+ std::string MainFile = testPath("main.cpp");
+ IncludeInserter Inserter(MainFile, /*Code=*/"", format::getLLVMStyle(),
+ /*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr);
+
+ auto HeaderPath = testPath("sub/bar.h");
+ auto Inserting = HeaderFile{HeaderPath, /*Verbatim=*/false};
+ auto Verbatim = HeaderFile{"<x>", /*Verbatim=*/true};
+
+ EXPECT_EQ(Inserter.calculateIncludePath(Inserting), "\"" + HeaderPath + "\"");
+ EXPECT_EQ(Inserter.shouldInsertInclude(HeaderPath, Inserting), false);
+
+ EXPECT_EQ(Inserter.calculateIncludePath(Verbatim), "<x>");
+ EXPECT_EQ(Inserter.shouldInsertInclude(HeaderPath, Verbatim), true);
+}
+
} // namespace
} // namespace clangd
} // namespace clang
diff --git a/unittests/clangd/IndexActionTests.cpp b/clangd/unittests/IndexActionTests.cpp
index 6a3da53a..6adc8cc1 100644
--- a/unittests/clangd/IndexActionTests.cpp
+++ b/clangd/unittests/IndexActionTests.cpp
@@ -1,9 +1,8 @@
//===------ IndexActionTests.cpp -------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -30,13 +29,15 @@ MATCHER(IsTU, "") { return arg.IsTU; }
MATCHER_P(HasDigest, Digest, "") { return arg.Digest == Digest; }
+MATCHER_P(HasName, Name, "") { return arg.Name == Name; }
+
MATCHER(HasSameURI, "") {
- llvm::StringRef URI = testing::get<0>(arg);
- const std::string &Path = testing::get<1>(arg);
+ llvm::StringRef URI = ::testing::get<0>(arg);
+ const std::string &Path = ::testing::get<1>(arg);
return toUri(Path) == URI;
}
-testing::Matcher<const IncludeGraphNode &>
+::testing::Matcher<const IncludeGraphNode &>
IncludesAre(const std::vector<std::string> &Includes) {
return ::testing::Field(&IncludeGraphNode::DirectIncludes,
UnorderedPointwise(HasSameURI(), Includes));
@@ -44,6 +45,7 @@ IncludesAre(const std::vector<std::string> &Includes) {
void checkNodesAreInitialized(const IndexFileIn &IndexFile,
const std::vector<std::string> &Paths) {
+ ASSERT_TRUE(IndexFile.Sources);
EXPECT_THAT(Paths.size(), IndexFile.Sources->size());
for (llvm::StringRef Path : Paths) {
auto URI = toUri(Path);
@@ -225,6 +227,27 @@ TEST_F(IndexActionTest, IncludeGraphDynamicInclude) {
HasDigest(digest(HeaderCode))))));
}
+TEST_F(IndexActionTest, NoWarnings) {
+ std::string MainFilePath = testPath("main.cpp");
+ std::string MainCode = R"cpp(
+ void foo(int x) {
+ if (x = 1) // -Wparentheses
+ return;
+ if (x = 1) // -Wparentheses
+ return;
+ }
+ void bar() {}
+ )cpp";
+ addFile(MainFilePath, MainCode);
+ // We set -ferror-limit so the warning-promoted-to-error would be fatal.
+ // This would cause indexing to stop (if warnings weren't disabled).
+ IndexFileIn IndexFile = runIndexingAction(
+ MainFilePath, {"-ferror-limit=1", "-Wparentheses", "-Werror"});
+ ASSERT_TRUE(IndexFile.Sources);
+ ASSERT_NE(0u, IndexFile.Sources->size());
+ EXPECT_THAT(*IndexFile.Symbols, ElementsAre(HasName("foo"), HasName("bar")));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
diff --git a/unittests/clangd/IndexTests.cpp b/clangd/unittests/IndexTests.cpp
index 3b7d6ff2..8d8c8da7 100644
--- a/unittests/clangd/IndexTests.cpp
+++ b/clangd/unittests/IndexTests.cpp
@@ -1,9 +1,8 @@
//===-- IndexTests.cpp -------------------------------*- C++ -*-----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -14,16 +13,19 @@
#include "index/Index.h"
#include "index/MemIndex.h"
#include "index/Merge.h"
+#include "index/Symbol.h"
+#include "clang/Index/IndexSymbol.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using testing::_;
-using testing::AllOf;
-using testing::AnyOf;
-using testing::ElementsAre;
-using testing::Pair;
-using testing::Pointee;
-using testing::UnorderedElementsAre;
+using ::testing::_;
+using ::testing::AllOf;
+using ::testing::AnyOf;
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
+using ::testing::Pair;
+using ::testing::Pointee;
+using ::testing::UnorderedElementsAre;
namespace clang {
namespace clangd {
@@ -182,6 +184,41 @@ TEST(MemIndexTest, Lookup) {
EXPECT_THAT(lookup(*I, SymbolID("ns::nonono")), UnorderedElementsAre());
}
+TEST(MemIndexTest, TemplateSpecialization) {
+ SymbolSlab::Builder B;
+
+ Symbol S = symbol("TempSpec");
+ S.ID = SymbolID("1");
+ B.insert(S);
+
+ S = symbol("TempSpec");
+ S.ID = SymbolID("2");
+ S.TemplateSpecializationArgs = "<int, bool>";
+ S.SymInfo.Properties = static_cast<index::SymbolPropertySet>(
+ index::SymbolProperty::TemplateSpecialization);
+ B.insert(S);
+
+ S = symbol("TempSpec");
+ S.ID = SymbolID("3");
+ S.TemplateSpecializationArgs = "<int, U>";
+ S.SymInfo.Properties = static_cast<index::SymbolPropertySet>(
+ index::SymbolProperty::TemplatePartialSpecialization);
+ B.insert(S);
+
+ auto I = MemIndex::build(std::move(B).build(), RefSlab());
+ FuzzyFindRequest Req;
+ Req.AnyScope = true;
+
+ Req.Query = "TempSpec";
+ EXPECT_THAT(match(*I, Req),
+ UnorderedElementsAre("TempSpec", "TempSpec<int, bool>",
+ "TempSpec<int, U>"));
+
+ // FIXME: Add filtering for template argument list.
+ Req.Query = "TempSpec<int";
+ EXPECT_THAT(match(*I, Req), IsEmpty());
+}
+
TEST(MergeIndexTest, Lookup) {
auto I = MemIndex::build(generateSymbols({"ns::A", "ns::B"}), RefSlab()),
J = MemIndex::build(generateSymbols({"ns::B", "ns::C"}), RefSlab());
@@ -254,6 +291,22 @@ TEST(MergeTest, PreferSymbolWithDefn) {
EXPECT_EQ(M.Name, "right");
}
+TEST(MergeTest, PreferSymbolLocationInCodegenFile) {
+ Symbol L, R;
+
+ L.ID = R.ID = SymbolID("hello");
+ L.CanonicalDeclaration.FileURI = "file:/x.proto.h";
+ R.CanonicalDeclaration.FileURI = "file:/x.proto";
+
+ Symbol M = mergeSymbol(L, R);
+ EXPECT_EQ(StringRef(M.CanonicalDeclaration.FileURI), "file:/x.proto");
+
+ // Prefer L if both have codegen suffix.
+ L.CanonicalDeclaration.FileURI = "file:/y.proto";
+ M = mergeSymbol(L, R);
+ EXPECT_EQ(StringRef(M.CanonicalDeclaration.FileURI), "file:/y.proto");
+}
+
TEST(MergeIndexTest, Refs) {
FileIndex Dyn;
FileIndex StaticIndex;
diff --git a/unittests/clangd/JSONTransportTests.cpp b/clangd/unittests/JSONTransportTests.cpp
index 23c39346..3f71a10c 100644
--- a/unittests/clangd/JSONTransportTests.cpp
+++ b/clangd/unittests/JSONTransportTests.cpp
@@ -1,9 +1,8 @@
//===-- JSONTransportTests.cpp -------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "Protocol.h"
@@ -18,8 +17,8 @@ namespace {
// No fmemopen on windows or on versions of MacOS X earlier than 10.13, so we
// can't easily run this test.
-#if !(defined(WIN32) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
- __MAC_OS_X_VERSION_MIN_REQUIRED < 101300))
+#if !(defined(_WIN32) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
+ __MAC_OS_X_VERSION_MIN_REQUIRED < 101300))
// Fixture takes care of managing the input/output buffers for the transport.
class JSONTransportTest : public ::testing::Test {
diff --git a/unittests/clangd/Matchers.h b/clangd/unittests/Matchers.h
index d666de36..0946398d 100644
--- a/unittests/clangd/Matchers.h
+++ b/clangd/unittests/Matchers.h
@@ -1,9 +1,8 @@
//===-- Matchers.h ----------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -128,6 +127,73 @@ PolySubsequenceMatcher<Args...> HasSubsequence(Args &&... M) {
llvm::consumeError(ComputedValue.takeError()); \
} while (false)
+// Implements the HasValue(m) matcher for matching an Optional whose
+// value matches matcher m.
+template <typename InnerMatcher> class OptionalMatcher {
+public:
+ explicit OptionalMatcher(const InnerMatcher &matcher) : matcher_(matcher) {}
+
+ // This type conversion operator template allows Optional(m) to be
+ // used as a matcher for any Optional type whose value type is
+ // compatible with the inner matcher.
+ //
+ // The reason we do this instead of relying on
+ // MakePolymorphicMatcher() is that the latter is not flexible
+ // enough for implementing the DescribeTo() method of Optional().
+ template <typename Optional> operator Matcher<Optional>() const {
+ return MakeMatcher(new Impl<Optional>(matcher_));
+ }
+
+private:
+ // The monomorphic implementation that works for a particular optional type.
+ template <typename Optional>
+ class Impl : public ::testing::MatcherInterface<Optional> {
+ public:
+ using Value = typename std::remove_const<
+ typename std::remove_reference<Optional>::type>::type::value_type;
+
+ explicit Impl(const InnerMatcher &matcher)
+ : matcher_(::testing::MatcherCast<const Value &>(matcher)) {}
+
+ virtual void DescribeTo(::std::ostream *os) const {
+ *os << "has a value that ";
+ matcher_.DescribeTo(os);
+ }
+
+ virtual void DescribeNegationTo(::std::ostream *os) const {
+ *os << "does not have a value that ";
+ matcher_.DescribeTo(os);
+ }
+
+ virtual bool
+ MatchAndExplain(Optional optional,
+ ::testing::MatchResultListener *listener) const {
+ if (!optional.hasValue())
+ return false;
+
+ *listener << "which has a value ";
+ return MatchPrintAndExplain(*optional, matcher_, listener);
+ }
+
+ private:
+ const Matcher<const Value &> matcher_;
+
+ GTEST_DISALLOW_ASSIGN_(Impl);
+ };
+
+ const InnerMatcher matcher_;
+
+ GTEST_DISALLOW_ASSIGN_(OptionalMatcher);
+};
+
+// Creates a matcher that matches an Optional that has a value
+// that matches inner_matcher.
+template <typename InnerMatcher>
+inline OptionalMatcher<InnerMatcher>
+HasValue(const InnerMatcher &inner_matcher) {
+ return OptionalMatcher<InnerMatcher>(inner_matcher);
+}
+
} // namespace clangd
} // namespace clang
#endif
diff --git a/clangd/unittests/PrintASTTests.cpp b/clangd/unittests/PrintASTTests.cpp
new file mode 100644
index 00000000..9cf2e7d3
--- /dev/null
+++ b/clangd/unittests/PrintASTTests.cpp
@@ -0,0 +1,102 @@
+//===--- PrintASTTests.cpp ----------------------------------------- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "AST.h"
+#include "Annotations.h"
+#include "Protocol.h"
+#include "SourceCode.h"
+#include "TestTU.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest-param-test.h"
+#include "gtest/gtest.h"
+#include "gtest/internal/gtest-param-util-generated.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+using ::testing::ElementsAreArray;
+
+struct Case {
+ const char *AnnotatedCode;
+ std::vector<const char *> Expected;
+};
+class ASTUtils : public ::testing::Test,
+ public ::testing::WithParamInterface<Case> {};
+
+TEST_P(ASTUtils, PrintTemplateArgs) {
+ auto Pair = GetParam();
+ Annotations Test(Pair.AnnotatedCode);
+ auto AST = TestTU::withCode(Test.code()).build();
+ struct Visitor : RecursiveASTVisitor<Visitor> {
+ Visitor(std::vector<Position> Points) : Points(std::move(Points)) {}
+ bool VisitNamedDecl(const NamedDecl *ND) {
+ if (TemplateArgsAtPoints.size() == Points.size())
+ return true;
+ auto Pos = sourceLocToPosition(ND->getASTContext().getSourceManager(),
+ ND->getLocation());
+ if (Pos != Points[TemplateArgsAtPoints.size()])
+ return true;
+ TemplateArgsAtPoints.push_back(printTemplateSpecializationArgs(*ND));
+ return true;
+ }
+ std::vector<std::string> TemplateArgsAtPoints;
+ const std::vector<Position> Points;
+ };
+ Visitor V(Test.points());
+ V.TraverseDecl(AST.getASTContext().getTranslationUnitDecl());
+ EXPECT_THAT(V.TemplateArgsAtPoints, ElementsAreArray(Pair.Expected));
+}
+
+INSTANTIATE_TEST_CASE_P(ASTUtilsTests, ASTUtils,
+ ::testing::ValuesIn(std::vector<Case>({
+ {
+ R"cpp(
+ template <class X> class Bar {};
+ template <> class ^Bar<double> {};)cpp",
+ {"<double>"}},
+ {
+ R"cpp(
+ template <class X> class Bar {};
+ template <class T, class U,
+ template<typename> class Z, int Q>
+ struct Foo {};
+ template struct ^Foo<int, bool, Bar, 8>;
+ template <typename T>
+ struct ^Foo<T *, T, Bar, 3> {};)cpp",
+ {"<int, bool, Bar, 8>", "<T *, T, Bar, 3>"}},
+ {
+ R"cpp(
+ template <int ...> void Foz() {};
+ template <> void ^Foz<3, 5, 8>() {};)cpp",
+ {"<3, 5, 8>"}},
+ {
+ R"cpp(
+ template <class X> class Bar {};
+ template <template <class> class ...>
+ class Aux {};
+ template <> class ^Aux<Bar, Bar> {};
+ template <template <class> T>
+ class ^Aux<T, T> {};)cpp",
+ {"<Bar, Bar>", "<T, T>"}},
+ {
+ R"cpp(
+ template <typename T> T var = 1234;
+ template <> int ^var<int> = 1;)cpp",
+ {"<int>"}},
+ {
+ R"cpp(
+ template <typename T> struct Foo;
+ struct Bar { friend class Foo<int>; };
+ template <> struct ^Foo<int> {};)cpp",
+ {"<int>"}},
+ })));
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/unittests/clangd/QualityTests.cpp b/clangd/unittests/QualityTests.cpp
index 9175d6bc..0c739d7d 100644
--- a/unittests/clangd/QualityTests.cpp
+++ b/clangd/unittests/QualityTests.cpp
@@ -1,9 +1,8 @@
-//===-- SourceCodeTests.cpp ------------------------------------*- C++ -*-===//
+//===-- QualityTests.cpp ----------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -179,6 +178,19 @@ TEST(QualityTests, SymbolRelevanceSignalExtraction) {
BaseMember.InBaseClass = true;
Relevance.merge(BaseMember);
EXPECT_TRUE(Relevance.InBaseClass);
+
+ auto Index = Test.index();
+ FuzzyFindRequest Req;
+ Req.Query = "X";
+ Req.AnyScope = true;
+ bool Matched = false;
+ Index->fuzzyFind(Req, [&](const Symbol &S) {
+ Matched = true;
+ Relevance = {};
+ Relevance.merge(S);
+ EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FileScope);
+ });
+ EXPECT_TRUE(Matched);
}
// Do the signals move the scores in the direction we expect?
@@ -265,7 +277,7 @@ TEST(QualityTests, SymbolRelevanceSignalsSanity) {
SymbolRelevanceSignals Scoped;
Scoped.Scope = SymbolRelevanceSignals::FileScope;
- EXPECT_EQ(Scoped.evaluate(), Default.evaluate());
+ EXPECT_LT(Scoped.evaluate(), Default.evaluate());
Scoped.Query = SymbolRelevanceSignals::CodeComplete;
EXPECT_GT(Scoped.evaluate(), Default.evaluate());
@@ -280,6 +292,16 @@ TEST(QualityTests, SymbolRelevanceSignalsSanity) {
SymbolRelevanceSignals InBaseClass;
InBaseClass.InBaseClass = true;
EXPECT_LT(InBaseClass.evaluate(), Default.evaluate());
+
+ llvm::StringSet<> Words = {"one", "two", "three"};
+ SymbolRelevanceSignals WithoutMatchingWord;
+ WithoutMatchingWord.ContextWords = &Words;
+ WithoutMatchingWord.Name = "four";
+ EXPECT_EQ(WithoutMatchingWord.evaluate(), Default.evaluate());
+ SymbolRelevanceSignals WithMatchingWord;
+ WithMatchingWord.ContextWords = &Words;
+ WithMatchingWord.Name = "TheTwoTowers";
+ EXPECT_GT(WithMatchingWord.evaluate(), Default.evaluate());
}
TEST(QualityTests, ScopeProximity) {
diff --git a/unittests/clangd/RIFFTests.cpp b/clangd/unittests/RIFFTests.cpp
index 7ea1466e..4cd54f40 100644
--- a/unittests/clangd/RIFFTests.cpp
+++ b/clangd/unittests/RIFFTests.cpp
@@ -1,9 +1,8 @@
//===-- RIFFTests.cpp - Binary container unit tests -----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/unittests/SelectionTests.cpp b/clangd/unittests/SelectionTests.cpp
new file mode 100644
index 00000000..ac9facca
--- /dev/null
+++ b/clangd/unittests/SelectionTests.cpp
@@ -0,0 +1,259 @@
+//===-- SelectionTests.cpp - ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "Annotations.h"
+#include "Selection.h"
+#include "SourceCode.h"
+#include "TestTU.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+using ::testing::UnorderedElementsAreArray;
+
+SelectionTree makeSelectionTree(const StringRef MarkedCode, ParsedAST &AST) {
+ Annotations Test(MarkedCode);
+ switch (Test.points().size()) {
+ case 1: // Point selection.
+ return SelectionTree(AST.getASTContext(),
+ cantFail(positionToOffset(Test.code(), Test.point())));
+ case 2: // Range selection.
+ return SelectionTree(
+ AST.getASTContext(),
+ cantFail(positionToOffset(Test.code(), Test.points()[0])),
+ cantFail(positionToOffset(Test.code(), Test.points()[1])));
+ default:
+ ADD_FAILURE() << "Expected 1-2 points for selection.\n" << MarkedCode;
+ return SelectionTree(AST.getASTContext(), 0u, 0u);
+ }
+}
+
+Range nodeRange(const SelectionTree::Node *N, ParsedAST &AST) {
+ if (!N)
+ return Range{};
+ SourceManager &SM = AST.getASTContext().getSourceManager();
+ StringRef Buffer = SM.getBufferData(SM.getMainFileID());
+ SourceRange SR = N->ASTNode.getSourceRange();
+ SR.setBegin(SM.getFileLoc(SR.getBegin()));
+ SR.setEnd(SM.getFileLoc(SR.getEnd()));
+ CharSourceRange R =
+ Lexer::getAsCharRange(SR, SM, AST.getASTContext().getLangOpts());
+ return Range{offsetToPosition(Buffer, SM.getFileOffset(R.getBegin())),
+ offsetToPosition(Buffer, SM.getFileOffset(R.getEnd()))};
+}
+
+std::string nodeKind(const SelectionTree::Node *N) {
+ if (!N)
+ return "<null>";
+ return N->ASTNode.getNodeKind().asStringRef().str();
+}
+
+std::vector<const SelectionTree::Node *> allNodes(const SelectionTree &T) {
+ std::vector<const SelectionTree::Node *> Result = {T.root()};
+ for (unsigned I = 0; I < Result.size(); ++I) {
+ const SelectionTree::Node *N = Result[I];
+ Result.insert(Result.end(), N->Children.begin(), N->Children.end());
+ }
+ return Result;
+}
+
+// Returns true if Common is a descendent of Root.
+// Verifies nothing is selected above Common.
+bool verifyCommonAncestor(const SelectionTree::Node *Root,
+ const SelectionTree::Node *Common,
+ StringRef MarkedCode) {
+ if (Root == Common)
+ return true;
+ if (Root->Selected)
+ ADD_FAILURE() << "Selected nodes outside common ancestor\n" << MarkedCode;
+ bool Seen = false;
+ for (const SelectionTree::Node *Child : Root->Children)
+ if (verifyCommonAncestor(Child, Common, MarkedCode)) {
+ if (Seen)
+ ADD_FAILURE() << "Saw common ancestor twice\n" << MarkedCode;
+ Seen = true;
+ }
+ return Seen;
+}
+
+TEST(SelectionTest, CommonAncestor) {
+ struct Case {
+ // Selection is between ^marks^.
+ // common ancestor marked with a [[range]].
+ const char *Code;
+ const char *CommonAncestorKind;
+ };
+ Case Cases[] = {
+ {
+ R"cpp(
+ struct AAA { struct BBB { static int ccc(); };};
+ int x = AAA::[[B^B^B]]::ccc();
+ )cpp",
+ "TypeLoc",
+ },
+ {
+ R"cpp(
+ struct AAA { struct BBB { static int ccc(); };};
+ int x = AAA::[[B^BB^]]::ccc();
+ )cpp",
+ "TypeLoc",
+ },
+ {
+ R"cpp(
+ struct AAA { struct BBB { static int ccc(); };};
+ int x = [[AAA::BBB::c^c^c]]();
+ )cpp",
+ "DeclRefExpr",
+ },
+ {
+ R"cpp(
+ struct AAA { struct BBB { static int ccc(); };};
+ int x = [[AAA::BBB::cc^c(^)]];
+ )cpp",
+ "CallExpr",
+ },
+
+ {
+ R"cpp(
+ void foo() { [[if (1^11) { return; } else {^ }]] }
+ )cpp",
+ "IfStmt",
+ },
+ {
+ R"cpp(
+ void foo();
+ #define CALL_FUNCTION(X) X()
+ void bar() { CALL_FUNCTION([[f^o^o]]); }
+ )cpp",
+ "DeclRefExpr",
+ },
+ {
+ R"cpp(
+ void foo();
+ #define CALL_FUNCTION(X) X()
+ void bar() { CALL_FUNC^TION([[fo^o]]); }
+ )cpp",
+ "DeclRefExpr",
+ },
+ {
+ R"cpp(
+ void foo();
+ #define CALL_FUNCTION(X) X()
+ void bar() [[{ C^ALL_FUNC^TION(foo); }]]
+ )cpp",
+ "CompoundStmt",
+ },
+ {
+ R"cpp(
+ void foo();
+ #define CALL_FUNCTION(X) X^()^
+ void bar() { CALL_FUNCTION(foo); }
+ )cpp",
+ nullptr,
+ },
+
+ // Point selections.
+ {"void foo() { [[^foo]](); }", "DeclRefExpr"},
+ {"void foo() { [[f^oo]](); }", "DeclRefExpr"},
+ {"void foo() { [[fo^o]](); }", "DeclRefExpr"},
+ {"void foo() { [[foo^()]]; }", "CallExpr"},
+ {"void foo() { [[foo^]] (); }", "DeclRefExpr"},
+ {"int bar; void foo() [[{ foo (); }]]^", "CompoundStmt"},
+ {"[[^void]] foo();", "TypeLoc"},
+ {"^", nullptr},
+ {"void foo() { [[foo^^]] (); }", "DeclRefExpr"},
+
+ // FIXME: Ideally we'd get a declstmt or the VarDecl itself here.
+ // This doesn't happen now; the RAV doesn't traverse a node containing ;.
+ {"int x = 42;^", nullptr},
+ {"int x = 42^;", nullptr},
+
+ // Node types that have caused problems in the past.
+ {"template <typename T> void foo() { [[^T]] t; }", "TypeLoc"},
+
+ // No crash
+ {
+ R"cpp(
+ template <class T> struct Foo {};
+ template <[[template<class> class /*cursor here*/^U]]>
+ struct Foo<U<int>*> {};
+ )cpp",
+ "TemplateTemplateParmDecl"
+ },
+ };
+ for (const Case &C : Cases) {
+ Annotations Test(C.Code);
+ auto AST = TestTU::withCode(Test.code()).build();
+ auto T = makeSelectionTree(C.Code, AST);
+
+ if (Test.ranges().empty()) {
+ // If no [[range]] is marked in the example, there should be no selection.
+ EXPECT_FALSE(T.commonAncestor()) << C.Code << "\n" << T;
+ EXPECT_FALSE(T.root()) << C.Code << "\n" << T;
+ } else {
+ // If there is an expected selection, both common ancestor and root
+ // should exist with the appropriate node types in them.
+ EXPECT_EQ(C.CommonAncestorKind, nodeKind(T.commonAncestor()))
+ << C.Code << "\n"
+ << T;
+ EXPECT_EQ("TranslationUnitDecl", nodeKind(T.root())) << C.Code;
+ // Convert the reported common ancestor to a range and verify it.
+ EXPECT_EQ(nodeRange(T.commonAncestor(), AST), Test.range())
+ << C.Code << "\n"
+ << T;
+
+ // Check that common ancestor is reachable on exactly one path from root,
+ // and no nodes outside it are selected.
+ EXPECT_TRUE(verifyCommonAncestor(T.root(), T.commonAncestor(), C.Code))
+ << C.Code;
+ }
+ }
+}
+
+TEST(SelectionTest, Selected) {
+ // Selection with ^marks^.
+ // Partially selected nodes marked with a [[range]].
+ // Completely selected nodes marked with a $C[[range]].
+ const char *Cases[] = {
+ R"cpp( int abc, xyz = [[^ab^c]]; )cpp",
+ R"cpp( int abc, xyz = [[a^bc^]]; )cpp",
+ R"cpp( int abc, xyz = $C[[^abc^]]; )cpp",
+ R"cpp(
+ void foo() {
+ [[if ([[1^11]]) $C[[{
+ $C[[return]];
+ }]] else [[{^
+ }]]]]
+ }
+ )cpp",
+ R"cpp(
+ template <class T>
+ struct unique_ptr {};
+ void foo(^$C[[unique_ptr<unique_ptr<$C[[int]]>>]]^ a) {}
+ )cpp",
+ };
+ for (const char *C : Cases) {
+ Annotations Test(C);
+ auto AST = TestTU::withCode(Test.code()).build();
+ auto T = makeSelectionTree(C, AST);
+
+ std::vector<Range> Complete, Partial;
+ for (const SelectionTree::Node *N : allNodes(T))
+ if (N->Selected == SelectionTree::Complete)
+ Complete.push_back(nodeRange(N, AST));
+ else if (N->Selected == SelectionTree::Partial)
+ Partial.push_back(nodeRange(N, AST));
+ EXPECT_THAT(Complete, UnorderedElementsAreArray(Test.ranges("C"))) << C;
+ EXPECT_THAT(Partial, UnorderedElementsAreArray(Test.ranges())) << C;
+ }
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/unittests/clangd/SerializationTests.cpp b/clangd/unittests/SerializationTests.cpp
index a8ffaa1c..792da770 100644
--- a/unittests/clangd/SerializationTests.cpp
+++ b/clangd/unittests/SerializationTests.cpp
@@ -1,9 +1,8 @@
//===-- SerializationTests.cpp - Binary and YAML serialization unit tests -===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -14,11 +13,11 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using testing::_;
-using testing::AllOf;
-using testing::Pair;
-using testing::UnorderedElementsAre;
-using testing::UnorderedElementsAreArray;
+using ::testing::_;
+using ::testing::AllOf;
+using ::testing::Pair;
+using ::testing::UnorderedElementsAre;
+using ::testing::UnorderedElementsAreArray;
namespace clang {
namespace clangd {
@@ -41,8 +40,8 @@ CanonicalDeclaration:
End:
Line: 1
Column: 1
-Origin: 4
-Flags: 1
+Origin: 128
+Flags: 129
Documentation: 'Foo doc'
ReturnType: 'int'
IncludeHeaders:
@@ -116,7 +115,8 @@ TEST(SerializationTest, YAMLConversions) {
EXPECT_EQ(Sym1.Documentation, "Foo doc");
EXPECT_EQ(Sym1.ReturnType, "int");
EXPECT_EQ(StringRef(Sym1.CanonicalDeclaration.FileURI), "file:///path/foo.h");
- EXPECT_EQ(Sym1.Origin, SymbolOrigin::Static);
+ EXPECT_EQ(Sym1.Origin, static_cast<SymbolOrigin>(1 << 7));
+ EXPECT_EQ(static_cast<uint8_t>(Sym1.Flags), 129);
EXPECT_TRUE(Sym1.Flags & Symbol::IndexedForCodeCompletion);
EXPECT_FALSE(Sym1.Flags & Symbol::Deprecated);
EXPECT_THAT(Sym1.IncludeHeaders,
@@ -135,7 +135,7 @@ TEST(SerializationTest, YAMLConversions) {
EXPECT_THAT(
*ParsedYAML->Refs,
UnorderedElementsAre(Pair(cantFail(SymbolID::fromStr("057557CEBF6E6B2D")),
- testing::SizeIs(1))));
+ ::testing::SizeIs(1))));
auto Ref1 = ParsedYAML->Refs->begin()->second.front();
EXPECT_EQ(Ref1.Kind, RefKind::Reference);
EXPECT_EQ(StringRef(Ref1.Location.FileURI), "file:///path/foo.cc");
diff --git a/clangd/unittests/SourceCodeTests.cpp b/clangd/unittests/SourceCodeTests.cpp
new file mode 100644
index 00000000..9ca6fa1a
--- /dev/null
+++ b/clangd/unittests/SourceCodeTests.cpp
@@ -0,0 +1,409 @@
+//===-- SourceCodeTests.cpp ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "Annotations.h"
+#include "Context.h"
+#include "Protocol.h"
+#include "SourceCode.h"
+#include "clang/Format/Format.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_os_ostream.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+using llvm::Failed;
+using llvm::HasValue;
+using ::testing::UnorderedElementsAreArray;
+
+MATCHER_P2(Pos, Line, Col, "") {
+ return arg.line == int(Line) && arg.character == int(Col);
+}
+
+/// A helper to make tests easier to read.
+Position position(int line, int character) {
+ Position Pos;
+ Pos.line = line;
+ Pos.character = character;
+ return Pos;
+}
+
+Range range(const std::pair<int, int> p1, const std::pair<int, int> p2) {
+ Range range;
+ range.start = position(p1.first, p1.second);
+ range.end = position(p2.first, p2.second);
+ return range;
+}
+
+TEST(SourceCodeTests, lspLength) {
+ EXPECT_EQ(lspLength(""), 0UL);
+ EXPECT_EQ(lspLength("ascii"), 5UL);
+ // BMP
+ EXPECT_EQ(lspLength("↓"), 1UL);
+ EXPECT_EQ(lspLength("¥"), 1UL);
+ // astral
+ EXPECT_EQ(lspLength("😂"), 2UL);
+
+ WithContextValue UTF8(kCurrentOffsetEncoding, OffsetEncoding::UTF8);
+ EXPECT_EQ(lspLength(""), 0UL);
+ EXPECT_EQ(lspLength("ascii"), 5UL);
+ // BMP
+ EXPECT_EQ(lspLength("↓"), 3UL);
+ EXPECT_EQ(lspLength("¥"), 2UL);
+ // astral
+ EXPECT_EQ(lspLength("😂"), 4UL);
+
+ WithContextValue UTF32(kCurrentOffsetEncoding, OffsetEncoding::UTF32);
+ EXPECT_EQ(lspLength(""), 0UL);
+ EXPECT_EQ(lspLength("ascii"), 5UL);
+ // BMP
+ EXPECT_EQ(lspLength("↓"), 1UL);
+ EXPECT_EQ(lspLength("¥"), 1UL);
+ // astral
+ EXPECT_EQ(lspLength("😂"), 1UL);
+}
+
+// The = → 🡆 below are ASCII (1 byte), BMP (3 bytes), and astral (4 bytes).
+const char File[] = R"(0:0 = 0
+1:0 → 8
+2:0 🡆 18)";
+struct Line {
+ unsigned Number;
+ unsigned Offset;
+ unsigned Length;
+};
+Line FileLines[] = {Line{0, 0, 7}, Line{1, 8, 9}, Line{2, 18, 11}};
+
+TEST(SourceCodeTests, PositionToOffset) {
+ // line out of bounds
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), llvm::Failed());
+ // first line
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, -1)),
+ llvm::Failed()); // out of range
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 0)),
+ llvm::HasValue(0)); // first character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 3)),
+ llvm::HasValue(3)); // middle character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 6)),
+ llvm::HasValue(6)); // last character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7)),
+ llvm::HasValue(7)); // the newline itself
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7), false),
+ llvm::HasValue(7));
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8)),
+ llvm::HasValue(7)); // out of range
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8), false),
+ llvm::Failed()); // out of range
+ // middle line
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, -1)),
+ llvm::Failed()); // out of range
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 0)),
+ llvm::HasValue(8)); // first character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3)),
+ llvm::HasValue(11)); // middle character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3), false),
+ llvm::HasValue(11));
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 6)),
+ llvm::HasValue(16)); // last character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 7)),
+ llvm::HasValue(17)); // the newline itself
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8)),
+ llvm::HasValue(17)); // out of range
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8), false),
+ llvm::Failed()); // out of range
+ // last line
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, -1)),
+ llvm::Failed()); // out of range
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 0)),
+ llvm::HasValue(18)); // first character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 3)),
+ llvm::HasValue(21)); // middle character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5), false),
+ llvm::Failed()); // middle of surrogate pair
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5)),
+ llvm::HasValue(26)); // middle of surrogate pair
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 6), false),
+ llvm::HasValue(26)); // end of surrogate pair
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 8)),
+ llvm::HasValue(28)); // last character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 9)),
+ llvm::HasValue(29)); // EOF
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 10), false),
+ llvm::Failed()); // out of range
+ // line out of bounds
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), llvm::Failed());
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 1)), llvm::Failed());
+
+ // Codepoints are similar, except near astral characters.
+ WithContextValue UTF32(kCurrentOffsetEncoding, OffsetEncoding::UTF32);
+ // line out of bounds
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), llvm::Failed());
+ // first line
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, -1)),
+ llvm::Failed()); // out of range
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 0)),
+ llvm::HasValue(0)); // first character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 3)),
+ llvm::HasValue(3)); // middle character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 6)),
+ llvm::HasValue(6)); // last character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7)),
+ llvm::HasValue(7)); // the newline itself
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7), false),
+ llvm::HasValue(7));
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8)),
+ llvm::HasValue(7)); // out of range
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8), false),
+ llvm::Failed()); // out of range
+ // middle line
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, -1)),
+ llvm::Failed()); // out of range
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 0)),
+ llvm::HasValue(8)); // first character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3)),
+ llvm::HasValue(11)); // middle character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3), false),
+ llvm::HasValue(11));
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 6)),
+ llvm::HasValue(16)); // last character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 7)),
+ llvm::HasValue(17)); // the newline itself
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8)),
+ llvm::HasValue(17)); // out of range
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8), false),
+ llvm::Failed()); // out of range
+ // last line
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, -1)),
+ llvm::Failed()); // out of range
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 0)),
+ llvm::HasValue(18)); // first character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 4)),
+ llvm::HasValue(22)); // Before astral character.
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5), false),
+ llvm::HasValue(26)); // after astral character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 7)),
+ llvm::HasValue(28)); // last character
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 8)),
+ llvm::HasValue(29)); // EOF
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 9), false),
+ llvm::Failed()); // out of range
+ // line out of bounds
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), llvm::Failed());
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 1)), llvm::Failed());
+
+ // Test UTF-8, where transformations are trivial.
+ WithContextValue UTF8(kCurrentOffsetEncoding, OffsetEncoding::UTF8);
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), llvm::Failed());
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), llvm::Failed());
+ for (Line L : FileLines) {
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(L.Number, -1)),
+ llvm::Failed()); // out of range
+ for (unsigned I = 0; I <= L.Length; ++I)
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(L.Number, I)),
+ llvm::HasValue(L.Offset + I));
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(L.Number, L.Length+1)),
+ llvm::HasValue(L.Offset + L.Length));
+ EXPECT_THAT_EXPECTED(
+ positionToOffset(File, position(L.Number, L.Length + 1), false),
+ llvm::Failed()); // out of range
+ }
+}
+
+TEST(SourceCodeTests, OffsetToPosition) {
+ EXPECT_THAT(offsetToPosition(File, 0), Pos(0, 0)) << "start of file";
+ EXPECT_THAT(offsetToPosition(File, 3), Pos(0, 3)) << "in first line";
+ EXPECT_THAT(offsetToPosition(File, 6), Pos(0, 6)) << "end of first line";
+ EXPECT_THAT(offsetToPosition(File, 7), Pos(0, 7)) << "first newline";
+ EXPECT_THAT(offsetToPosition(File, 8), Pos(1, 0)) << "start of second line";
+ EXPECT_THAT(offsetToPosition(File, 12), Pos(1, 4)) << "before BMP char";
+ EXPECT_THAT(offsetToPosition(File, 13), Pos(1, 5)) << "in BMP char";
+ EXPECT_THAT(offsetToPosition(File, 15), Pos(1, 5)) << "after BMP char";
+ EXPECT_THAT(offsetToPosition(File, 16), Pos(1, 6)) << "end of second line";
+ EXPECT_THAT(offsetToPosition(File, 17), Pos(1, 7)) << "second newline";
+ EXPECT_THAT(offsetToPosition(File, 18), Pos(2, 0)) << "start of last line";
+ EXPECT_THAT(offsetToPosition(File, 21), Pos(2, 3)) << "in last line";
+ EXPECT_THAT(offsetToPosition(File, 22), Pos(2, 4)) << "before astral char";
+ EXPECT_THAT(offsetToPosition(File, 24), Pos(2, 6)) << "in astral char";
+ EXPECT_THAT(offsetToPosition(File, 26), Pos(2, 6)) << "after astral char";
+ EXPECT_THAT(offsetToPosition(File, 28), Pos(2, 8)) << "end of last line";
+ EXPECT_THAT(offsetToPosition(File, 29), Pos(2, 9)) << "EOF";
+ EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 9)) << "out of bounds";
+
+ // Codepoints are similar, except near astral characters.
+ WithContextValue UTF32(kCurrentOffsetEncoding, OffsetEncoding::UTF32);
+ EXPECT_THAT(offsetToPosition(File, 0), Pos(0, 0)) << "start of file";
+ EXPECT_THAT(offsetToPosition(File, 3), Pos(0, 3)) << "in first line";
+ EXPECT_THAT(offsetToPosition(File, 6), Pos(0, 6)) << "end of first line";
+ EXPECT_THAT(offsetToPosition(File, 7), Pos(0, 7)) << "first newline";
+ EXPECT_THAT(offsetToPosition(File, 8), Pos(1, 0)) << "start of second line";
+ EXPECT_THAT(offsetToPosition(File, 12), Pos(1, 4)) << "before BMP char";
+ EXPECT_THAT(offsetToPosition(File, 13), Pos(1, 5)) << "in BMP char";
+ EXPECT_THAT(offsetToPosition(File, 15), Pos(1, 5)) << "after BMP char";
+ EXPECT_THAT(offsetToPosition(File, 16), Pos(1, 6)) << "end of second line";
+ EXPECT_THAT(offsetToPosition(File, 17), Pos(1, 7)) << "second newline";
+ EXPECT_THAT(offsetToPosition(File, 18), Pos(2, 0)) << "start of last line";
+ EXPECT_THAT(offsetToPosition(File, 21), Pos(2, 3)) << "in last line";
+ EXPECT_THAT(offsetToPosition(File, 22), Pos(2, 4)) << "before astral char";
+ EXPECT_THAT(offsetToPosition(File, 24), Pos(2, 5)) << "in astral char";
+ EXPECT_THAT(offsetToPosition(File, 26), Pos(2, 5)) << "after astral char";
+ EXPECT_THAT(offsetToPosition(File, 28), Pos(2, 7)) << "end of last line";
+ EXPECT_THAT(offsetToPosition(File, 29), Pos(2, 8)) << "EOF";
+ EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 8)) << "out of bounds";
+
+ WithContextValue UTF8(kCurrentOffsetEncoding, OffsetEncoding::UTF8);
+ for (Line L : FileLines) {
+ for (unsigned I = 0; I <= L.Length; ++I)
+ EXPECT_THAT(offsetToPosition(File, L.Offset + I), Pos(L.Number, I));
+ }
+ EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 11)) << "out of bounds";
+}
+
+TEST(SourceCodeTests, IsRangeConsecutive) {
+ EXPECT_TRUE(isRangeConsecutive(range({2, 2}, {2, 3}), range({2, 3}, {2, 4})));
+ EXPECT_FALSE(
+ isRangeConsecutive(range({0, 2}, {0, 3}), range({2, 3}, {2, 4})));
+ EXPECT_FALSE(
+ isRangeConsecutive(range({2, 2}, {2, 3}), range({2, 4}, {2, 5})));
+}
+
+TEST(SourceCodeTests, SourceLocationInMainFile) {
+ Annotations Source(R"cpp(
+ ^in^t ^foo
+ ^bar
+ ^baz ^() {} {} {} {} { }^
+)cpp");
+
+ SourceManagerForFile Owner("foo.cpp", Source.code());
+ SourceManager &SM = Owner.get();
+
+ SourceLocation StartOfFile = SM.getLocForStartOfFile(SM.getMainFileID());
+ EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(0, 0)),
+ HasValue(StartOfFile));
+ // End of file.
+ EXPECT_THAT_EXPECTED(
+ sourceLocationInMainFile(SM, position(4, 0)),
+ HasValue(StartOfFile.getLocWithOffset(Source.code().size())));
+ // Column number is too large.
+ EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(0, 1)), Failed());
+ EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(0, 100)),
+ Failed());
+ EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(4, 1)), Failed());
+ // Line number is too large.
+ EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(5, 0)), Failed());
+ // Check all positions mentioned in the test return valid results.
+ for (auto P : Source.points()) {
+ size_t Offset = llvm::cantFail(positionToOffset(Source.code(), P));
+ EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, P),
+ HasValue(StartOfFile.getLocWithOffset(Offset)));
+ }
+}
+
+TEST(SourceCodeTests, CollectIdentifiers) {
+ auto Style = format::getLLVMStyle();
+ auto IDs = collectIdentifiers(R"cpp(
+ #include "a.h"
+ void foo() { int xyz; int abc = xyz; return foo(); }
+ )cpp",
+ Style);
+ EXPECT_EQ(IDs.size(), 7u);
+ EXPECT_EQ(IDs["include"], 1u);
+ EXPECT_EQ(IDs["void"], 1u);
+ EXPECT_EQ(IDs["int"], 2u);
+ EXPECT_EQ(IDs["xyz"], 2u);
+ EXPECT_EQ(IDs["abc"], 1u);
+ EXPECT_EQ(IDs["return"], 1u);
+ EXPECT_EQ(IDs["foo"], 2u);
+}
+
+TEST(SourceCodeTests, CollectWords) {
+ auto Words = collectWords(R"cpp(
+ #define FIZZ_BUZZ
+ // this is a comment
+ std::string getSomeText() { return "magic word"; }
+ )cpp");
+ std::set<std::string> ActualWords(Words.keys().begin(), Words.keys().end());
+ std::set<std::string> ExpectedWords = {"define", "fizz", "buzz", "this",
+ "comment", "string", "some", "text",
+ "return", "magic", "word"};
+ EXPECT_EQ(ActualWords, ExpectedWords);
+}
+
+TEST(SourceCodeTests, VisibleNamespaces) {
+ std::vector<std::pair<const char *, std::vector<std::string>>> Cases = {
+ {
+ R"cpp(
+ // Using directive resolved against enclosing namespaces.
+ using namespace foo;
+ namespace ns {
+ using namespace bar;
+ )cpp",
+ {"ns", "", "bar", "foo", "ns::bar"},
+ },
+ {
+ R"cpp(
+ // Don't include namespaces we've closed, ignore namespace aliases.
+ using namespace clang;
+ using std::swap;
+ namespace clang {
+ namespace clangd {}
+ namespace ll = ::llvm;
+ }
+ namespace clang {
+ )cpp",
+ {"clang", ""},
+ },
+ {
+ R"cpp(
+ // Using directives visible even if a namespace is reopened.
+ // Ignore anonymous namespaces.
+ namespace foo{ using namespace bar; }
+ namespace foo{ namespace {
+ )cpp",
+ {"foo", "", "bar", "foo::bar"},
+ },
+ {
+ R"cpp(
+ // Mismatched braces
+ namespace foo{}
+ }}}
+ namespace bar{
+ )cpp",
+ {"bar", ""},
+ },
+ {
+ R"cpp(
+ // Namespaces with multiple chunks.
+ namespace a::b {
+ using namespace c::d;
+ namespace e::f {
+ )cpp",
+ {
+ "a::b::e::f",
+ "",
+ "a",
+ "a::b",
+ "a::b::c::d",
+ "a::b::e",
+ "a::c::d",
+ "c::d",
+ },
+ },
+ };
+ for (const auto& Case : Cases) {
+ EXPECT_EQ(Case.second,
+ visibleNamespaces(Case.first, format::getLLVMStyle()))
+ << Case.first;
+ }
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/unittests/clangd/SymbolCollectorTests.cpp b/clangd/unittests/SymbolCollectorTests.cpp
index 6f76b175..d372b1d6 100644
--- a/unittests/clangd/SymbolCollectorTests.cpp
+++ b/clangd/unittests/SymbolCollectorTests.cpp
@@ -1,9 +1,8 @@
//===-- SymbolCollectorTests.cpp -------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -21,6 +20,8 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/VirtualFileSystem.h"
+#include "gmock/gmock-matchers.h"
+#include "gmock/gmock-more-matchers.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -31,16 +32,16 @@ namespace clang {
namespace clangd {
namespace {
-using testing::_;
-using testing::AllOf;
-using testing::Contains;
-using testing::Eq;
-using testing::Field;
-using testing::IsEmpty;
-using testing::Not;
-using testing::Pair;
-using testing::UnorderedElementsAre;
-using testing::UnorderedElementsAreArray;
+using ::testing::_;
+using ::testing::AllOf;
+using ::testing::Contains;
+using ::testing::Each;
+using ::testing::ElementsAre;
+using ::testing::Field;
+using ::testing::Not;
+using ::testing::Pair;
+using ::testing::UnorderedElementsAre;
+using ::testing::UnorderedElementsAreArray;
// GMock helpers for matching Symbol.
MATCHER_P(Labeled, Label, "") {
@@ -52,10 +53,14 @@ MATCHER_P(Snippet, S, "") {
return (arg.Name + arg.CompletionSnippetSuffix).str() == S;
}
MATCHER_P(QName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
+MATCHER_P(TemplateArgs, TemplArgs, "") {
+ return arg.TemplateSpecializationArgs == TemplArgs;
+}
MATCHER_P(DeclURI, P, "") {
return StringRef(arg.CanonicalDeclaration.FileURI) == P;
}
MATCHER_P(DefURI, P, "") { return StringRef(arg.Definition.FileURI) == P; }
+MATCHER(IncludeHeader, "") { return !arg.IncludeHeaders.empty(); }
MATCHER_P(IncludeHeader, P, "") {
return (arg.IncludeHeaders.size() == 1) &&
(arg.IncludeHeaders.begin()->IncludeHeader == P);
@@ -91,16 +96,16 @@ MATCHER(VisibleOutsideFile, "") {
return static_cast<bool>(arg.Flags & Symbol::VisibleOutsideFile);
}
MATCHER(RefRange, "") {
- const Ref &Pos = testing::get<0>(arg);
- const Range &Range = testing::get<1>(arg);
+ const Ref &Pos = ::testing::get<0>(arg);
+ const Range &Range = ::testing::get<1>(arg);
return std::make_tuple(Pos.Location.Start.line(), Pos.Location.Start.column(),
Pos.Location.End.line(), Pos.Location.End.column()) ==
std::make_tuple(Range.start.line, Range.start.character,
Range.end.line, Range.end.character);
}
-testing::Matcher<const std::vector<Ref> &>
+::testing::Matcher<const std::vector<Ref> &>
HaveRanges(const std::vector<Range> Ranges) {
- return testing::UnorderedPointwise(RefRange(), Ranges);
+ return ::testing::UnorderedPointwise(RefRange(), Ranges);
}
class ShouldCollectSymbolTest : public ::testing::Test {
@@ -116,8 +121,8 @@ public:
// build() must have been called.
bool shouldCollect(llvm::StringRef Name, bool Qualified = true) {
assert(AST.hasValue());
- const NamedDecl& ND = Qualified ? findDecl(*AST, Name)
- : findUnqualifiedDecl(*AST, Name);
+ const NamedDecl &ND =
+ Qualified ? findDecl(*AST, Name) : findUnqualifiedDecl(*AST, Name);
ASTContext& Ctx = AST->getASTContext();
const SourceManager& SM = Ctx.getSourceManager();
bool MainFile = SM.isWrittenInMainFile(SM.getExpansionLoc(ND.getBeginLoc()));
@@ -213,6 +218,12 @@ public:
return WrapperFrontendAction::CreateASTConsumer(CI, InFile);
}
+ bool BeginInvocation(CompilerInstance &CI) override {
+ // Make the compiler parse all comments.
+ CI.getLangOpts().CommentOpts.ParseAllComments = true;
+ return WrapperFrontendAction::BeginInvocation(CI);
+ }
+
private:
index::IndexingOptions IndexOpts;
CommentHandler *PragmaHandler;
@@ -241,6 +252,8 @@ public:
TestFileURI = URI::create(TestFileName).toString();
}
+ // Note that unlike TestTU, no automatic header guard is added.
+ // HeaderCode should start with #pragma once to be treated as modular.
bool runSymbolCollector(llvm::StringRef HeaderCode, llvm::StringRef MainCode,
const std::vector<std::string> &ExtraArgs = {}) {
llvm::IntrusiveRefCntPtr<FileManager> Files(
@@ -249,9 +262,8 @@ public:
auto Factory = llvm::make_unique<SymbolIndexActionFactory>(
CollectorOpts, PragmaHandler.get());
- std::vector<std::string> Args = {
- "symbol_collector", "-fsyntax-only", "-xc++",
- "-std=c++11", "-include", TestHeaderName};
+ std::vector<std::string> Args = {"symbol_collector", "-fsyntax-only",
+ "-xc++", "-include", TestHeaderName};
Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
// This allows to override the "-xc++" with something else, i.e.
// -xobjective-c++.
@@ -261,8 +273,8 @@ public:
Args, Factory->create(), Files.get(),
std::make_shared<PCHContainerOperations>());
- InMemoryFileSystem->addFile(TestHeaderName, 0,
- llvm::MemoryBuffer::getMemBuffer(HeaderCode));
+ InMemoryFileSystem->addFile(
+ TestHeaderName, 0, llvm::MemoryBuffer::getMemBuffer(HeaderCode));
InMemoryFileSystem->addFile(TestFileName, 0,
llvm::MemoryBuffer::getMemBuffer(MainCode));
Invocation.run();
@@ -326,9 +338,6 @@ TEST_F(SymbolCollectorTest, CollectSymbols) {
// Namespace alias
namespace baz = bar;
- // FIXME: using declaration is not supported as the IndexAction will ignore
- // implicit declarations (the implicit using shadow declaration) by default,
- // and there is no way to customize this behavior at the moment.
using bar::v2;
} // namespace foo
)";
@@ -355,6 +364,7 @@ TEST_F(SymbolCollectorTest, CollectSymbols) {
AllOf(QName("foo::int32_t"), ForCodeCompletion(true)),
AllOf(QName("foo::v1"), ForCodeCompletion(true)),
AllOf(QName("foo::bar::v2"), ForCodeCompletion(true)),
+ AllOf(QName("foo::v2"), ForCodeCompletion(true)),
AllOf(QName("foo::baz"), ForCodeCompletion(true))}));
}
@@ -389,17 +399,90 @@ TEST_F(SymbolCollectorTest, FileLocal) {
TEST_F(SymbolCollectorTest, Template) {
Annotations Header(R"(
- // Template is indexed, specialization and instantiation is not.
- template <class T> struct [[Tmpl]] {T $xdecl[[x]] = 0;};
- template <> struct Tmpl<int> {};
- extern template struct Tmpl<float>;
- template struct Tmpl<double>;
+ // Primary template and explicit specialization are indexed, instantiation
+ // is not.
+ template <class T, class U> struct [[Tmpl]] {T $xdecl[[x]] = 0;};
+ template <> struct $specdecl[[Tmpl]]<int, bool> {};
+ template <class U> struct $partspecdecl[[Tmpl]]<bool, U> {};
+ extern template struct Tmpl<float, bool>;
+ template struct Tmpl<double, bool>;
)");
runSymbolCollector(Header.code(), /*Main=*/"");
EXPECT_THAT(Symbols,
- UnorderedElementsAreArray(
- {AllOf(QName("Tmpl"), DeclRange(Header.range())),
- AllOf(QName("Tmpl::x"), DeclRange(Header.range("xdecl")))}));
+ UnorderedElementsAre(
+ AllOf(QName("Tmpl"), DeclRange(Header.range()),
+ ForCodeCompletion(true)),
+ AllOf(QName("Tmpl"), DeclRange(Header.range("specdecl")),
+ ForCodeCompletion(false)),
+ AllOf(QName("Tmpl"), DeclRange(Header.range("partspecdecl")),
+ ForCodeCompletion(false)),
+ AllOf(QName("Tmpl::x"), DeclRange(Header.range("xdecl")),
+ ForCodeCompletion(false))));
+}
+
+TEST_F(SymbolCollectorTest, TemplateArgs) {
+ Annotations Header(R"(
+ template <class X> class $barclasstemp[[Bar]] {};
+ template <class T, class U, template<typename> class Z, int Q>
+ struct [[Tmpl]] { T $xdecl[[x]] = 0; };
+
+ // template-template, non-type and type full spec
+ template <> struct $specdecl[[Tmpl]]<int, bool, Bar, 3> {};
+
+ // template-template, non-type and type partial spec
+ template <class U, int T> struct $partspecdecl[[Tmpl]]<bool, U, Bar, T> {};
+ // instantiation
+ extern template struct Tmpl<float, bool, Bar, 8>;
+ // instantiation
+ template struct Tmpl<double, bool, Bar, 2>;
+
+ template <typename ...> class $fooclasstemp[[Foo]] {};
+ // parameter-packs full spec
+ template<> class $parampack[[Foo]]<Bar<int>, int, double> {};
+ // parameter-packs partial spec
+ template<class T> class $parampackpartial[[Foo]]<T, T> {};
+
+ template <int ...> class $bazclasstemp[[Baz]] {};
+ // non-type parameter-packs full spec
+ template<> class $parampacknontype[[Baz]]<3, 5, 8> {};
+ // non-type parameter-packs partial spec
+ template<int T> class $parampacknontypepartial[[Baz]]<T, T> {};
+
+ template <template <class> class ...> class $fozclasstemp[[Foz]] {};
+ // template-template parameter-packs full spec
+ template<> class $parampacktempltempl[[Foz]]<Bar, Bar> {};
+ // template-template parameter-packs partial spec
+ template<template <class> class T>
+ class $parampacktempltemplpartial[[Foz]]<T, T> {};
+ )");
+ runSymbolCollector(Header.code(), /*Main=*/"");
+ EXPECT_THAT(
+ Symbols,
+ AllOf(
+ Contains(AllOf(QName("Tmpl"), TemplateArgs("<int, bool, Bar, 3>"),
+ DeclRange(Header.range("specdecl")),
+ ForCodeCompletion(false))),
+ Contains(AllOf(QName("Tmpl"), TemplateArgs("<bool, U, Bar, T>"),
+ DeclRange(Header.range("partspecdecl")),
+ ForCodeCompletion(false))),
+ Contains(AllOf(QName("Foo"), TemplateArgs("<Bar<int>, int, double>"),
+ DeclRange(Header.range("parampack")),
+ ForCodeCompletion(false))),
+ Contains(AllOf(QName("Foo"), TemplateArgs("<T, T>"),
+ DeclRange(Header.range("parampackpartial")),
+ ForCodeCompletion(false))),
+ Contains(AllOf(QName("Baz"), TemplateArgs("<3, 5, 8>"),
+ DeclRange(Header.range("parampacknontype")),
+ ForCodeCompletion(false))),
+ Contains(AllOf(QName("Baz"), TemplateArgs("<T, T>"),
+ DeclRange(Header.range("parampacknontypepartial")),
+ ForCodeCompletion(false))),
+ Contains(AllOf(QName("Foz"), TemplateArgs("<Bar, Bar>"),
+ DeclRange(Header.range("parampacktempltempl")),
+ ForCodeCompletion(false))),
+ Contains(AllOf(QName("Foz"), TemplateArgs("<T, T>"),
+ DeclRange(Header.range("parampacktempltemplpartial")),
+ ForCodeCompletion(false)))));
}
TEST_F(SymbolCollectorTest, ObjCSymbols) {
@@ -438,6 +521,23 @@ TEST_F(SymbolCollectorTest, ObjCSymbols) {
QName("MyProtocol"), QName("MyProtocol::someMethodName3:")));
}
+TEST_F(SymbolCollectorTest, ObjCPropertyImpl) {
+ const std::string Header = R"(
+ @interface Container
+ @property(nonatomic) int magic;
+ @end
+
+ @implementation Container
+ @end
+ )";
+ TestFileName = testPath("test.m");
+ runSymbolCollector(Header, /*Main=*/"", {"-xobjective-c++"});
+ EXPECT_THAT(Symbols, Contains(QName("Container")));
+ EXPECT_THAT(Symbols, Contains(QName("Container::magic")));
+ // FIXME: Results also contain Container::_magic on some platforms.
+ // Figure out why it's platform-dependent.
+}
+
TEST_F(SymbolCollectorTest, Locations) {
Annotations Header(R"cpp(
// Declared in header, defined in main.
@@ -555,19 +655,15 @@ TEST_F(SymbolCollectorTest, References) {
)";
CollectorOpts.CountReferences = true;
runSymbolCollector(Header, Main);
- EXPECT_THAT(Symbols,
- UnorderedElementsAreArray(
- {AllOf(QName("W"), RefCount(1)),
- AllOf(QName("X"), RefCount(1)),
- AllOf(QName("Y"), RefCount(0)),
- AllOf(QName("Z"), RefCount(0)),
- AllOf(QName("y"), RefCount(0)),
- AllOf(QName("z"), RefCount(0)),
- AllOf(QName("x"), RefCount(0)),
- AllOf(QName("w"), RefCount(0)),
- AllOf(QName("w2"), RefCount(0)),
- AllOf(QName("V"), RefCount(1)),
- AllOf(QName("v"), RefCount(0))}));
+ EXPECT_THAT(
+ Symbols,
+ UnorderedElementsAreArray(
+ {AllOf(QName("W"), RefCount(1)), AllOf(QName("X"), RefCount(1)),
+ AllOf(QName("Y"), RefCount(0)), AllOf(QName("Z"), RefCount(0)),
+ AllOf(QName("y"), RefCount(0)), AllOf(QName("z"), RefCount(0)),
+ AllOf(QName("x"), RefCount(0)), AllOf(QName("w"), RefCount(0)),
+ AllOf(QName("w2"), RefCount(0)), AllOf(QName("V"), RefCount(1)),
+ AllOf(QName("v"), RefCount(0))}));
}
TEST_F(SymbolCollectorTest, SymbolRelativeNoFallback) {
@@ -694,6 +790,31 @@ TEST_F(SymbolCollectorTest, SymbolsInMainFile) {
QName("main_f")));
}
+TEST_F(SymbolCollectorTest, Documentation) {
+ const std::string Header = R"(
+ // Doc Foo
+ class Foo {
+ // Doc f
+ int f();
+ };
+ )";
+ CollectorOpts.StoreAllDocumentation = false;
+ runSymbolCollector(Header, /* Main */ "");
+ EXPECT_THAT(Symbols,
+ UnorderedElementsAre(
+ AllOf(QName("Foo"), Doc("Doc Foo"), ForCodeCompletion(true)),
+ AllOf(QName("Foo::f"), Doc(""), ReturnType(""),
+ ForCodeCompletion(false))));
+
+ CollectorOpts.StoreAllDocumentation = true;
+ runSymbolCollector(Header, /* Main */ "");
+ EXPECT_THAT(Symbols,
+ UnorderedElementsAre(
+ AllOf(QName("Foo"), Doc("Doc Foo"), ForCodeCompletion(true)),
+ AllOf(QName("Foo::f"), Doc("Doc f"), ReturnType(""),
+ ForCodeCompletion(false))));
+}
+
TEST_F(SymbolCollectorTest, ClassMembers) {
const std::string Header = R"(
class Foo {
@@ -800,54 +921,22 @@ TEST_F(SymbolCollectorTest, Snippet) {
TEST_F(SymbolCollectorTest, IncludeHeaderSameAsFileURI) {
CollectorOpts.CollectIncludePath = true;
- runSymbolCollector("class Foo {};", /*Main=*/"");
+ runSymbolCollector("#pragma once\nclass Foo {};", /*Main=*/"");
EXPECT_THAT(Symbols, UnorderedElementsAre(
AllOf(QName("Foo"), DeclURI(TestHeaderURI))));
EXPECT_THAT(Symbols.begin()->IncludeHeaders,
UnorderedElementsAre(IncludeHeaderWithRef(TestHeaderURI, 1u)));
}
-#ifndef _WIN32
TEST_F(SymbolCollectorTest, CanonicalSTLHeader) {
CollectorOpts.CollectIncludePath = true;
CanonicalIncludes Includes;
addSystemHeadersMapping(&Includes);
CollectorOpts.Includes = &Includes;
- // bits/basic_string.h$ should be mapped to <string>
- TestHeaderName = "/nasty/bits/basic_string.h";
- TestFileName = "/nasty/bits/basic_string.cpp";
- TestHeaderURI = URI::create(TestHeaderName).toString();
- runSymbolCollector("class string {};", /*Main=*/"");
- EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("string"),
- DeclURI(TestHeaderURI),
- IncludeHeader("<string>"))));
-}
-#endif
-
-TEST_F(SymbolCollectorTest, STLiosfwd) {
- CollectorOpts.CollectIncludePath = true;
- CanonicalIncludes Includes;
- addSystemHeadersMapping(&Includes);
- CollectorOpts.Includes = &Includes;
- // Symbols from <iosfwd> should be mapped individually.
- TestHeaderName = testPath("iosfwd");
- TestFileName = testPath("iosfwd.cpp");
- std::string Header = R"(
- namespace std {
- class no_map {};
- class ios {};
- class ostream {};
- class filebuf {};
- } // namespace std
- )";
- runSymbolCollector(Header, /*Main=*/"");
+ runSymbolCollector("namespace std { class string {}; }", /*Main=*/"");
EXPECT_THAT(Symbols,
- UnorderedElementsAre(
- QName("std"),
- AllOf(QName("std::no_map"), IncludeHeader("<iosfwd>")),
- AllOf(QName("std::ios"), IncludeHeader("<ios>")),
- AllOf(QName("std::ostream"), IncludeHeader("<ostream>")),
- AllOf(QName("std::filebuf"), IncludeHeader("<fstream>"))));
+ Contains(AllOf(QName("std::string"), DeclURI(TestHeaderURI),
+ IncludeHeader("<string>"))));
}
TEST_F(SymbolCollectorTest, IWYUPragma) {
@@ -900,53 +989,85 @@ TEST_F(SymbolCollectorTest, SkipIncFileWhenCanonicalizeHeaders) {
TEST_F(SymbolCollectorTest, MainFileIsHeaderWhenSkipIncFile) {
CollectorOpts.CollectIncludePath = true;
- CanonicalIncludes Includes;
- CollectorOpts.Includes = &Includes;
- TestFileName = testPath("main.h");
+ // To make this case as hard as possible, we won't tell clang main is a
+ // header. No extension, no -x c++-header.
+ TestFileName = testPath("no_ext_main");
TestFileURI = URI::create(TestFileName).toString();
auto IncFile = testPath("test.inc");
auto IncURI = URI::create(IncFile).toString();
InMemoryFileSystem->addFile(IncFile, 0,
llvm::MemoryBuffer::getMemBuffer("class X {};"));
- runSymbolCollector("", /*Main=*/"#include \"test.inc\"",
+ runSymbolCollector("", R"cpp(
+ // Can't use #pragma once in a main file clang doesn't think is a header.
+ #ifndef MAIN_H_
+ #define MAIN_H_
+ #include "test.inc"
+ #endif
+ )cpp",
/*ExtraArgs=*/{"-I", testRoot()});
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
IncludeHeader(TestFileURI))));
}
-TEST_F(SymbolCollectorTest, MainFileIsHeaderWithoutExtensionWhenSkipIncFile) {
+TEST_F(SymbolCollectorTest, IncFileInNonHeader) {
CollectorOpts.CollectIncludePath = true;
- CanonicalIncludes Includes;
- CollectorOpts.Includes = &Includes;
- TestFileName = testPath("no_ext_main");
+ TestFileName = testPath("main.cc");
TestFileURI = URI::create(TestFileName).toString();
auto IncFile = testPath("test.inc");
auto IncURI = URI::create(IncFile).toString();
InMemoryFileSystem->addFile(IncFile, 0,
llvm::MemoryBuffer::getMemBuffer("class X {};"));
- runSymbolCollector("", /*Main=*/"#include \"test.inc\"",
+ runSymbolCollector("", R"cpp(
+ #include "test.inc"
+ )cpp",
/*ExtraArgs=*/{"-I", testRoot()});
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
- IncludeHeader(TestFileURI))));
+ Not(IncludeHeader()))));
}
-TEST_F(SymbolCollectorTest, FallbackToIncFileWhenIncludingFileIsCC) {
+// Features that depend on header-guards are fragile. Header guards are only
+// recognized when the file ends, so we have to defer checking for them.
+TEST_F(SymbolCollectorTest, HeaderGuardDetected) {
CollectorOpts.CollectIncludePath = true;
- CanonicalIncludes Includes;
- CollectorOpts.Includes = &Includes;
- auto IncFile = testPath("test.inc");
- auto IncURI = URI::create(IncFile).toString();
- InMemoryFileSystem->addFile(IncFile, 0,
- llvm::MemoryBuffer::getMemBuffer("class X {};"));
- runSymbolCollector("", /*Main=*/"#include \"test.inc\"",
- /*ExtraArgs=*/{"-I", testRoot()});
- EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
- IncludeHeader(IncURI))));
+ CollectorOpts.CollectMacro = true;
+ runSymbolCollector(R"cpp(
+ #ifndef HEADER_GUARD_
+ #define HEADER_GUARD_
+
+ // Symbols are seen before the header guard is complete.
+ #define MACRO
+ int decl();
+
+ #endif // Header guard is recognized here.
+ )cpp",
+ "");
+ EXPECT_THAT(Symbols, Not(Contains(QName("HEADER_GUARD_"))));
+ EXPECT_THAT(Symbols, Each(IncludeHeader()));
+}
+
+TEST_F(SymbolCollectorTest, NonModularHeader) {
+ auto TU = TestTU::withHeaderCode("int x();");
+ EXPECT_THAT(TU.headerSymbols(), ElementsAre(IncludeHeader()));
+
+ // Files missing include guards aren't eligible for insertion.
+ TU.ImplicitHeaderGuard = false;
+ EXPECT_THAT(TU.headerSymbols(), ElementsAre(Not(IncludeHeader())));
+
+ // We recognize some patterns of trying to prevent insertion.
+ TU = TestTU::withHeaderCode(R"cpp(
+#ifndef SECRET
+#error "This file isn't safe to include directly"
+#endif
+ int x();
+ )cpp");
+ TU.ExtraArgs.push_back("-DSECRET"); // *we're* able to include it.
+ EXPECT_THAT(TU.headerSymbols(), ElementsAre(Not(IncludeHeader())));
}
TEST_F(SymbolCollectorTest, AvoidUsingFwdDeclsAsCanonicalDecls) {
CollectorOpts.CollectIncludePath = true;
Annotations Header(R"(
+ #pragma once
// Forward declarations of TagDecls.
class C;
struct S;
@@ -980,7 +1101,8 @@ TEST_F(SymbolCollectorTest, AvoidUsingFwdDeclsAsCanonicalDecls) {
TEST_F(SymbolCollectorTest, ClassForwardDeclarationIsCanonical) {
CollectorOpts.CollectIncludePath = true;
- runSymbolCollector(/*Header=*/"class X;", /*Main=*/"class X {};");
+ runSymbolCollector(/*Header=*/"#pragma once\nclass X;",
+ /*Main=*/"class X {};");
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(
QName("X"), DeclURI(TestHeaderURI),
IncludeHeader(TestHeaderURI), DefURI(TestFileURI))));
@@ -1047,27 +1169,34 @@ TEST_F(SymbolCollectorTest, Origin) {
TEST_F(SymbolCollectorTest, CollectMacros) {
CollectorOpts.CollectIncludePath = true;
Annotations Header(R"(
+ #pragma once
#define X 1
#define $mac[[MAC]](x) int x
#define $used[[USED]](y) float y;
MAC(p);
)");
- const std::string Main = R"(
- #define MAIN 1 // not indexed
- USED(t);
- )";
+
+ Annotations Main(R"(
+ #define $main[[MAIN]] 1
+ USED(t);
+ )");
CollectorOpts.CountReferences = true;
CollectorOpts.CollectMacro = true;
- runSymbolCollector(Header.code(), Main);
- EXPECT_THAT(Symbols,
- UnorderedElementsAre(QName("p"), QName("t"),
- AllOf(QName("X"), DeclURI(TestHeaderURI),
- IncludeHeader(TestHeaderURI)),
- AllOf(Labeled("MAC(x)"), RefCount(0),
- DeclRange(Header.range("mac"))),
- AllOf(Labeled("USED(y)"), RefCount(1),
- DeclRange(Header.range("used")))));
+ runSymbolCollector(Header.code(), Main.code());
+ EXPECT_THAT(
+ Symbols,
+ UnorderedElementsAre(
+ QName("p"), QName("t"),
+ AllOf(QName("X"), DeclURI(TestHeaderURI),
+ IncludeHeader(TestHeaderURI)),
+ AllOf(Labeled("MAC(x)"), RefCount(0),
+
+ DeclRange(Header.range("mac")), VisibleOutsideFile()),
+ AllOf(Labeled("USED(y)"), RefCount(1),
+ DeclRange(Header.range("used")), VisibleOutsideFile()),
+ AllOf(Labeled("MAIN"), RefCount(0), DeclRange(Main.range("main")),
+ Not(VisibleOutsideFile()))));
}
TEST_F(SymbolCollectorTest, DeprecatedSymbols) {
@@ -1096,6 +1225,33 @@ TEST_F(SymbolCollectorTest, ImplementationDetail) {
AllOf(QName("Public"), Not(ImplementationDetail()))));
}
+TEST_F(SymbolCollectorTest, UsingDecl) {
+ const char *Header = R"(
+ void foo();
+ namespace std {
+ using ::foo;
+ })";
+ runSymbolCollector(Header, /**/ "");
+ EXPECT_THAT(Symbols, Contains(QName("std::foo")));
+}
+
+TEST_F(SymbolCollectorTest, CBuiltins) {
+ // In C, printf in stdio.h is a redecl of an implicit builtin.
+ const char *Header = R"(
+ extern int printf(const char*, ...);
+ )";
+ runSymbolCollector(Header, /**/ "", {"-xc"});
+ EXPECT_THAT(Symbols, Contains(QName("printf")));
+}
+
+TEST_F(SymbolCollectorTest, InvalidSourceLoc) {
+ const char *Header = R"(
+ void operator delete(void*)
+ __attribute__((__externally_visible__));)";
+ runSymbolCollector(Header, /**/ "");
+ EXPECT_THAT(Symbols, Contains(QName("operator delete")));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
diff --git a/unittests/clangd/SymbolInfoTests.cpp b/clangd/unittests/SymbolInfoTests.cpp
index cbd178e6..d8d40432 100644
--- a/unittests/clangd/SymbolInfoTests.cpp
+++ b/clangd/unittests/SymbolInfoTests.cpp
@@ -1,9 +1,8 @@
//===-- SymbolInfoTests.cpp -----------------------*- C++ -*--------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "Annotations.h"
@@ -25,7 +24,7 @@ namespace clang {
namespace clangd {
namespace {
-using testing::ElementsAreArray;
+using ::testing::ElementsAreArray;
auto CreateExpectedSymbolDetails = [](const std::string &name,
const std::string &container,
@@ -150,7 +149,13 @@ TEST(SymbolInfoTests, All) {
#define MACRO 5\nint i = MAC^RO;
)cpp",
{CreateExpectedSymbolDetails("MACRO", "",
- "c:TestTU.cpp@55@macro@MACRO")}},
+ "c:TestTU.cpp@38@macro@MACRO")}},
+ {
+ R"cpp( // Macro reference
+ #define MACRO 5\nint i = MACRO^;
+ )cpp",
+ {CreateExpectedSymbolDetails("MACRO", "",
+ "c:TestTU.cpp@38@macro@MACRO")}},
{
R"cpp( // Multiple symbols returned - using overloaded function name
void foo() {}
@@ -162,7 +167,8 @@ TEST(SymbolInfoTests, All) {
)cpp",
{CreateExpectedSymbolDetails("foo", "", "c:@F@foo#"),
CreateExpectedSymbolDetails("foo", "", "c:@F@foo#b#"),
- CreateExpectedSymbolDetails("foo", "", "c:@F@foo#I#")}},
+ CreateExpectedSymbolDetails("foo", "", "c:@F@foo#I#"),
+ CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@UD@foo")}},
{
R"cpp( // Multiple symbols returned - implicit conversion
struct foo {};
@@ -175,12 +181,8 @@ TEST(SymbolInfoTests, All) {
func_baz1(f^f);
}
)cpp",
- {
- CreateExpectedSymbolDetails(
- "ff", "func_baz2", "c:TestTU.cpp@218@F@func_baz2#@ff"),
- CreateExpectedSymbolDetails(
- "bar", "bar::", "c:@S@bar@F@bar#&1$@S@foo#"),
- }},
+ {CreateExpectedSymbolDetails(
+ "ff", "func_baz2", "c:TestTU.cpp@218@F@func_baz2#@ff")}},
{
R"cpp( // Type reference - declaration
struct foo;
@@ -208,14 +210,14 @@ TEST(SymbolInfoTests, All) {
T^T t;
};
)cpp",
- {/* not implemented */}},
+ {CreateExpectedSymbolDetails("TT", "bar::", "c:TestTU.cpp@65")}},
{
R"cpp( // Template parameter reference - type param
template<int NN> struct bar {
int a = N^N;
};
)cpp",
- {/* not implemented */}},
+ {CreateExpectedSymbolDetails("NN", "bar::", "c:TestTU.cpp@65")}},
{
R"cpp( // Class member reference - objec
struct foo {
@@ -297,6 +299,12 @@ TEST(SymbolInfoTests, All) {
)cpp",
{CreateExpectedSymbolDetails("bar", "foo::", "c:@E@foo@bar")}},
{
+ R"cpp( // Parameters in declarations
+ void foo(int ba^r);
+ )cpp",
+ {CreateExpectedSymbolDetails("bar", "foo",
+ "c:TestTU.cpp@50@F@foo#I#@bar")}},
+ {
R"cpp( // Type inferrence with auto keyword
struct foo {};
foo getfoo() { return foo{}; }
diff --git a/unittests/clangd/SyncAPI.cpp b/clangd/unittests/SyncAPI.cpp
index 83e6b761..102cecb5 100644
--- a/unittests/clangd/SyncAPI.cpp
+++ b/clangd/unittests/SyncAPI.cpp
@@ -1,9 +1,8 @@
//===--- SyncAPI.cpp - Sync version of ClangdServer's API --------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -85,10 +84,10 @@ llvm::Expected<SignatureHelp> runSignatureHelp(ClangdServer &Server,
return std::move(*Result);
}
-llvm::Expected<std::vector<Location>>
-runFindDefinitions(ClangdServer &Server, PathRef File, Position Pos) {
- llvm::Optional<llvm::Expected<std::vector<Location>>> Result;
- Server.findDefinitions(File, Pos, capture(Result));
+llvm::Expected<std::vector<LocatedSymbol>>
+runLocateSymbolAt(ClangdServer &Server, PathRef File, Position Pos) {
+ llvm::Optional<llvm::Expected<std::vector<LocatedSymbol>>> Result;
+ Server.locateSymbolAt(File, Pos, capture(Result));
return std::move(*Result);
}
@@ -99,10 +98,10 @@ runFindDocumentHighlights(ClangdServer &Server, PathRef File, Position Pos) {
return std::move(*Result);
}
-llvm::Expected<std::vector<tooling::Replacement>>
-runRename(ClangdServer &Server, PathRef File, Position Pos,
- llvm::StringRef NewName) {
- llvm::Optional<llvm::Expected<std::vector<tooling::Replacement>>> Result;
+llvm::Expected<std::vector<TextEdit>> runRename(ClangdServer &Server,
+ PathRef File, Position Pos,
+ llvm::StringRef NewName) {
+ llvm::Optional<llvm::Expected<std::vector<TextEdit>>> Result;
Server.rename(File, Pos, NewName, capture(Result));
return std::move(*Result);
}
diff --git a/unittests/clangd/SyncAPI.h b/clangd/unittests/SyncAPI.h
index f336e615..c1416524 100644
--- a/unittests/clangd/SyncAPI.h
+++ b/clangd/unittests/SyncAPI.h
@@ -1,9 +1,8 @@
//===--- SyncAPI.h - Sync version of ClangdServer's API ----------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -33,13 +32,13 @@ runCodeComplete(ClangdServer &Server, PathRef File, Position Pos,
llvm::Expected<SignatureHelp> runSignatureHelp(ClangdServer &Server,
PathRef File, Position Pos);
-llvm::Expected<std::vector<Location>>
-runFindDefinitions(ClangdServer &Server, PathRef File, Position Pos);
+llvm::Expected<std::vector<LocatedSymbol>>
+runLocateSymbolAt(ClangdServer &Server, PathRef File, Position Pos);
llvm::Expected<std::vector<DocumentHighlight>>
runFindDocumentHighlights(ClangdServer &Server, PathRef File, Position Pos);
-llvm::Expected<std::vector<tooling::Replacement>>
+llvm::Expected<std::vector<TextEdit>>
runRename(ClangdServer &Server, PathRef File, Position Pos, StringRef NewName);
std::string runDumpAST(ClangdServer &Server, PathRef File);
diff --git a/unittests/clangd/TUSchedulerTests.cpp b/clangd/unittests/TUSchedulerTests.cpp
index 27cc6375..a7d032cc 100644
--- a/unittests/clangd/TUSchedulerTests.cpp
+++ b/clangd/unittests/TUSchedulerTests.cpp
@@ -1,9 +1,8 @@
//===-- TUSchedulerTests.cpp ------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -22,12 +21,9 @@ namespace clang {
namespace clangd {
namespace {
-using ::testing::_;
-using ::testing::AllOf;
using ::testing::AnyOf;
using ::testing::Each;
using ::testing::ElementsAre;
-using ::testing::Pair;
using ::testing::Pointee;
using ::testing::UnorderedElementsAre;
@@ -38,8 +34,12 @@ MATCHER_P2(TUState, State, ActionName, "") {
class TUSchedulerTests : public ::testing::Test {
protected:
ParseInputs getInputs(PathRef File, std::string Contents) {
- return ParseInputs{*CDB.getCompileCommand(File),
- buildTestFS(Files, Timestamps), std::move(Contents)};
+ ParseInputs Inputs;
+ Inputs.CompileCommand = *CDB.getCompileCommand(File);
+ Inputs.FS = buildTestFS(Files, Timestamps);
+ Inputs.Contents = std::move(Contents);
+ Inputs.Opts = ParseOptions();
+ return Inputs;
}
void updateWithCallback(TUScheduler &S, PathRef File,
@@ -101,7 +101,7 @@ Key<llvm::unique_function<void(PathRef File, std::vector<Diag>)>>
TUSchedulerTests::DiagsCallbackKey;
TEST_F(TUSchedulerTests, MissingFiles) {
- TUScheduler S(getDefaultAsyncThreadsCount(),
+ TUScheduler S(CDB, getDefaultAsyncThreadsCount(),
/*StorePreamblesInMemory=*/true, /*ASTCallbacks=*/nullptr,
/*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
ASTRetentionPolicy());
@@ -152,7 +152,7 @@ TEST_F(TUSchedulerTests, WantDiagnostics) {
// thread until we've scheduled them all.
Notification Ready;
TUScheduler S(
- getDefaultAsyncThreadsCount(),
+ CDB, getDefaultAsyncThreadsCount(),
/*StorePreamblesInMemory=*/true, captureDiags(),
/*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
ASTRetentionPolicy());
@@ -182,7 +182,7 @@ TEST_F(TUSchedulerTests, WantDiagnostics) {
TEST_F(TUSchedulerTests, Debounce) {
std::atomic<int> CallbackCount(0);
{
- TUScheduler S(getDefaultAsyncThreadsCount(),
+ TUScheduler S(CDB, getDefaultAsyncThreadsCount(),
/*StorePreamblesInMemory=*/true, captureDiags(),
/*UpdateDebounce=*/std::chrono::seconds(1),
ASTRetentionPolicy());
@@ -218,7 +218,7 @@ TEST_F(TUSchedulerTests, PreambleConsistency) {
{
Notification InconsistentReadDone; // Must live longest.
TUScheduler S(
- getDefaultAsyncThreadsCount(), /*StorePreamblesInMemory=*/true,
+ CDB, getDefaultAsyncThreadsCount(), /*StorePreamblesInMemory=*/true,
/*ASTCallbacks=*/nullptr,
/*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
ASTRetentionPolicy());
@@ -275,7 +275,7 @@ TEST_F(TUSchedulerTests, Cancellation) {
{
Notification Proceed; // Ensure we schedule everything.
TUScheduler S(
- getDefaultAsyncThreadsCount(), /*StorePreamblesInMemory=*/true,
+ CDB, getDefaultAsyncThreadsCount(), /*StorePreamblesInMemory=*/true,
/*ASTCallbacks=*/captureDiags(),
/*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
ASTRetentionPolicy());
@@ -344,7 +344,7 @@ TEST_F(TUSchedulerTests, ManyUpdates) {
// Run TUScheduler and collect some stats.
{
- TUScheduler S(getDefaultAsyncThreadsCount(),
+ TUScheduler S(CDB, getDefaultAsyncThreadsCount(),
/*StorePreamblesInMemory=*/true, captureDiags(),
/*UpdateDebounce=*/std::chrono::milliseconds(50),
ASTRetentionPolicy());
@@ -435,10 +435,11 @@ TEST_F(TUSchedulerTests, EvictedAST) {
std::atomic<int> BuiltASTCounter(0);
ASTRetentionPolicy Policy;
Policy.MaxRetainedASTs = 2;
- TUScheduler S(
- /*AsyncThreadsCount=*/1, /*StorePreambleInMemory=*/true,
- /*ASTCallbacks=*/nullptr,
- /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(), Policy);
+ TUScheduler S(CDB,
+ /*AsyncThreadsCount=*/1, /*StorePreambleInMemory=*/true,
+ /*ASTCallbacks=*/nullptr,
+ /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
+ Policy);
llvm::StringLiteral SourceContents = R"cpp(
int* a;
@@ -485,11 +486,11 @@ TEST_F(TUSchedulerTests, EvictedAST) {
}
TEST_F(TUSchedulerTests, EmptyPreamble) {
- TUScheduler S(
- /*AsyncThreadsCount=*/4, /*StorePreambleInMemory=*/true,
- /*ASTCallbacks=*/nullptr,
- /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
- ASTRetentionPolicy());
+ TUScheduler S(CDB,
+ /*AsyncThreadsCount=*/4, /*StorePreambleInMemory=*/true,
+ /*ASTCallbacks=*/nullptr,
+ /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
+ ASTRetentionPolicy());
auto Foo = testPath("foo.cpp");
auto Header = testPath("foo.h");
@@ -530,11 +531,11 @@ TEST_F(TUSchedulerTests, EmptyPreamble) {
TEST_F(TUSchedulerTests, RunWaitsForPreamble) {
// Testing strategy: we update the file and schedule a few preamble reads at
// the same time. All reads should get the same non-null preamble.
- TUScheduler S(
- /*AsyncThreadsCount=*/4, /*StorePreambleInMemory=*/true,
- /*ASTCallbacks=*/nullptr,
- /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
- ASTRetentionPolicy());
+ TUScheduler S(CDB,
+ /*AsyncThreadsCount=*/4, /*StorePreambleInMemory=*/true,
+ /*ASTCallbacks=*/nullptr,
+ /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
+ ASTRetentionPolicy());
auto Foo = testPath("foo.cpp");
auto NonEmptyPreamble = R"cpp(
#define FOO 1
@@ -562,11 +563,11 @@ TEST_F(TUSchedulerTests, RunWaitsForPreamble) {
}
TEST_F(TUSchedulerTests, NoopOnEmptyChanges) {
- TUScheduler S(
- /*AsyncThreadsCount=*/getDefaultAsyncThreadsCount(),
- /*StorePreambleInMemory=*/true, captureDiags(),
- /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
- ASTRetentionPolicy());
+ TUScheduler S(CDB,
+ /*AsyncThreadsCount=*/getDefaultAsyncThreadsCount(),
+ /*StorePreambleInMemory=*/true, captureDiags(),
+ /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
+ ASTRetentionPolicy());
auto Source = testPath("foo.cpp");
auto Header = testPath("foo.h");
@@ -615,11 +616,11 @@ TEST_F(TUSchedulerTests, NoopOnEmptyChanges) {
}
TEST_F(TUSchedulerTests, NoChangeDiags) {
- TUScheduler S(
- /*AsyncThreadsCount=*/getDefaultAsyncThreadsCount(),
- /*StorePreambleInMemory=*/true, captureDiags(),
- /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
- ASTRetentionPolicy());
+ TUScheduler S(CDB,
+ /*AsyncThreadsCount=*/getDefaultAsyncThreadsCount(),
+ /*StorePreambleInMemory=*/true, captureDiags(),
+ /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
+ ASTRetentionPolicy());
auto FooCpp = testPath("foo.cpp");
auto Contents = "int a; int b;";
@@ -650,7 +651,7 @@ TEST_F(TUSchedulerTests, NoChangeDiags) {
}
TEST_F(TUSchedulerTests, Run) {
- TUScheduler S(/*AsyncThreadsCount=*/getDefaultAsyncThreadsCount(),
+ TUScheduler S(CDB, /*AsyncThreadsCount=*/getDefaultAsyncThreadsCount(),
/*StorePreambleInMemory=*/true, /*ASTCallbacks=*/nullptr,
/*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(),
ASTRetentionPolicy());
@@ -685,10 +686,10 @@ TEST_F(TUSchedulerTests, TUStatus) {
// We schedule the following tasks in the queue:
// [Update] [GoToDefinition]
Server.addDocument(testPath("foo.cpp"), Code.code(), WantDiagnostics::Yes);
- Server.findDefinitions(testPath("foo.cpp"), Code.point(),
- [](Expected<std::vector<Location>> Result) {
- ASSERT_TRUE((bool)Result);
- });
+ Server.locateSymbolAt(testPath("foo.cpp"), Code.point(),
+ [](Expected<std::vector<LocatedSymbol>> Result) {
+ ASSERT_TRUE((bool)Result);
+ });
ASSERT_TRUE(Server.blockUntilIdleForTest());
diff --git a/unittests/clangd/TestFS.cpp b/clangd/unittests/TestFS.cpp
index 082f15a1..c5b2613f 100644
--- a/unittests/clangd/TestFS.cpp
+++ b/clangd/unittests/TestFS.cpp
@@ -1,9 +1,8 @@
//===-- TestFS.cpp ----------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "TestFS.h"
diff --git a/unittests/clangd/TestFS.h b/clangd/unittests/TestFS.h
index 0226fc3d..eabdddf7 100644
--- a/unittests/clangd/TestFS.h
+++ b/clangd/unittests/TestFS.h
@@ -1,9 +1,8 @@
//===-- TestFS.h ------------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clangd/unittests/TestIndex.cpp b/clangd/unittests/TestIndex.cpp
new file mode 100644
index 00000000..11ac4239
--- /dev/null
+++ b/clangd/unittests/TestIndex.cpp
@@ -0,0 +1,118 @@
+//===-- TestIndex.cpp -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestIndex.h"
+#include "clang/Index/IndexSymbol.h"
+#include "llvm/Support/Regex.h"
+
+namespace clang {
+namespace clangd {
+
+Symbol symbol(llvm::StringRef QName) {
+ Symbol Sym;
+ Sym.ID = SymbolID(QName.str());
+ size_t Pos = QName.rfind("::");
+ if (Pos == llvm::StringRef::npos) {
+ Sym.Name = QName;
+ Sym.Scope = "";
+ } else {
+ Sym.Name = QName.substr(Pos + 2);
+ Sym.Scope = QName.substr(0, Pos + 2);
+ }
+ return Sym;
+}
+
+static std::string replace(llvm::StringRef Haystack, llvm::StringRef Needle,
+ llvm::StringRef Repl) {
+ llvm::SmallVector<llvm::StringRef, 8> Parts;
+ Haystack.split(Parts, Needle);
+ return llvm::join(Parts, Repl);
+}
+
+// Helpers to produce fake index symbols for memIndex() or completions().
+// USRFormat is a regex replacement string for the unqualified part of the USR.
+Symbol sym(llvm::StringRef QName, index::SymbolKind Kind,
+ llvm::StringRef USRFormat) {
+ Symbol Sym;
+ std::string USR = "c:"; // We synthesize a few simple cases of USRs by hand!
+ size_t Pos = QName.rfind("::");
+ if (Pos == llvm::StringRef::npos) {
+ Sym.Name = QName;
+ Sym.Scope = "";
+ } else {
+ Sym.Name = QName.substr(Pos + 2);
+ Sym.Scope = QName.substr(0, Pos + 2);
+ USR += "@N@" + replace(QName.substr(0, Pos), "::", "@N@"); // ns:: -> @N@ns
+ }
+ USR += llvm::Regex("^.*$").sub(USRFormat, Sym.Name); // e.g. func -> @F@func#
+ Sym.ID = SymbolID(USR);
+ Sym.SymInfo.Kind = Kind;
+ Sym.Flags |= Symbol::IndexedForCodeCompletion;
+ Sym.Origin = SymbolOrigin::Static;
+ return Sym;
+}
+
+Symbol func(llvm::StringRef Name) { // Assumes the function has no args.
+ return sym(Name, index::SymbolKind::Function, "@F@\\0#"); // no args
+}
+
+Symbol cls(llvm::StringRef Name) {
+ return sym(Name, index::SymbolKind::Class, "@S@\\0");
+}
+
+Symbol var(llvm::StringRef Name) {
+ return sym(Name, index::SymbolKind::Variable, "@\\0");
+}
+
+Symbol ns(llvm::StringRef Name) {
+ return sym(Name, index::SymbolKind::Namespace, "@N@\\0");
+}
+
+SymbolSlab generateSymbols(std::vector<std::string> QualifiedNames) {
+ SymbolSlab::Builder Slab;
+ for (llvm::StringRef QName : QualifiedNames)
+ Slab.insert(symbol(QName));
+ return std::move(Slab).build();
+}
+
+SymbolSlab generateNumSymbols(int Begin, int End) {
+ std::vector<std::string> Names;
+ for (int i = Begin; i <= End; i++)
+ Names.push_back(std::to_string(i));
+ return generateSymbols(Names);
+}
+
+std::string getQualifiedName(const Symbol &Sym) {
+ return (Sym.Scope + Sym.Name + Sym.TemplateSpecializationArgs).str();
+}
+
+std::vector<std::string> match(const SymbolIndex &I,
+ const FuzzyFindRequest &Req, bool *Incomplete) {
+ std::vector<std::string> Matches;
+ bool IsIncomplete = I.fuzzyFind(Req, [&](const Symbol &Sym) {
+ Matches.push_back(clang::clangd::getQualifiedName(Sym));
+ });
+ if (Incomplete)
+ *Incomplete = IsIncomplete;
+ return Matches;
+}
+
+// Returns qualified names of symbols with any of IDs in the index.
+std::vector<std::string> lookup(const SymbolIndex &I,
+ llvm::ArrayRef<SymbolID> IDs) {
+ LookupRequest Req;
+ Req.IDs.insert(IDs.begin(), IDs.end());
+ std::vector<std::string> Results;
+ I.lookup(Req, [&](const Symbol &Sym) {
+ Results.push_back(getQualifiedName(Sym));
+ });
+ return Results;
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/unittests/clangd/TestIndex.h b/clangd/unittests/TestIndex.h
index 01dcc086..01de089e 100644
--- a/unittests/clangd/TestIndex.h
+++ b/clangd/unittests/TestIndex.h
@@ -1,9 +1,8 @@
//===-- IndexHelpers.h ------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -19,6 +18,19 @@ namespace clangd {
// Creates Symbol instance and sets SymbolID to given QualifiedName.
Symbol symbol(llvm::StringRef QName);
+// Helpers to produce fake index symbols with proper SymbolID.
+// USRFormat is a regex replacement string for the unqualified part of the USR.
+Symbol sym(llvm::StringRef QName, index::SymbolKind Kind,
+ llvm::StringRef USRFormat);
+// Creats a function symbol assuming no function arg.
+Symbol func(llvm::StringRef Name);
+// Creates a class symbol.
+Symbol cls(llvm::StringRef Name);
+// Creates a variable symbol.
+Symbol var(llvm::StringRef Name);
+// Creates a namespace symbol.
+Symbol ns(llvm::StringRef Name);
+
// Create a slab of symbols with the given qualified names as IDs and names.
SymbolSlab generateSymbols(std::vector<std::string> QualifiedNames);
diff --git a/unittests/clangd/TestScheme.h b/clangd/unittests/TestScheme.h
index e69de29b..e69de29b 100644
--- a/unittests/clangd/TestScheme.h
+++ b/clangd/unittests/TestScheme.h
diff --git a/unittests/clangd/TestTU.cpp b/clangd/unittests/TestTU.cpp
index 6706c449..8f48eab5 100644
--- a/unittests/clangd/TestTU.cpp
+++ b/clangd/unittests/TestTU.cpp
@@ -1,9 +1,8 @@
//===--- TestTU.cpp - Scratch source files for testing --------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -13,7 +12,6 @@
#include "index/MemIndex.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/CompilerInvocation.h"
-#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Frontend/Utils.h"
namespace clang {
@@ -21,13 +19,25 @@ namespace clangd {
ParsedAST TestTU::build() const {
std::string FullFilename = testPath(Filename),
- FullHeaderName = testPath(HeaderFilename);
+ FullHeaderName = testPath(HeaderFilename),
+ ImportThunk = testPath("import_thunk.h");
+ // We want to implicitly include HeaderFilename without messing up offsets.
+ // -include achieves this, but sometimes we want #import (to simulate a header
+ // guard without messing up offsets). In this case, use an intermediate file.
+ std::string ThunkContents = "#import \"" + FullHeaderName + "\"\n";
+
+ llvm::StringMap<std::string> Files(AdditionalFiles);
+ Files[FullFilename] = Code;
+ Files[FullHeaderName] = HeaderCode;
+ Files[ImportThunk] = ThunkContents;
+
std::vector<const char *> Cmd = {"clang", FullFilename.c_str()};
// FIXME: this shouldn't need to be conditional, but it breaks a
// GoToDefinition test for some reason (getMacroArgExpandedLocation fails).
if (!HeaderCode.empty()) {
Cmd.push_back("-include");
- Cmd.push_back(FullHeaderName.c_str());
+ Cmd.push_back(ImplicitHeaderGuard ? ImportThunk.c_str()
+ : FullHeaderName.c_str());
}
Cmd.insert(Cmd.end(), ExtraArgs.begin(), ExtraArgs.end());
ParseInputs Inputs;
@@ -35,17 +45,21 @@ ParsedAST TestTU::build() const {
Inputs.CompileCommand.CommandLine = {Cmd.begin(), Cmd.end()};
Inputs.CompileCommand.Directory = testRoot();
Inputs.Contents = Code;
- Inputs.FS = buildTestFS({{FullFilename, Code}, {FullHeaderName, HeaderCode}});
- auto PCHs = std::make_shared<PCHContainerOperations>();
+ Inputs.FS = buildTestFS(Files);
+ Inputs.Opts = ParseOptions();
+ Inputs.Opts.ClangTidyOpts.Checks = ClangTidyChecks;
+ Inputs.Index = ExternalIndex;
+ if (Inputs.Index)
+ Inputs.Opts.SuggestMissingIncludes = true;
auto CI = buildCompilerInvocation(Inputs);
assert(CI && "Failed to build compilation invocation.");
auto Preamble =
buildPreamble(FullFilename, *CI,
/*OldPreamble=*/nullptr,
- /*OldCompileCommand=*/Inputs.CompileCommand, Inputs, PCHs,
+ /*OldCompileCommand=*/Inputs.CompileCommand, Inputs,
/*StoreInMemory=*/true, /*PreambleCallback=*/nullptr);
auto AST = buildAST(FullFilename, createInvocationFromCommandLine(Cmd),
- Inputs, Preamble, PCHs);
+ Inputs, Preamble);
if (!AST.hasValue()) {
ADD_FAILURE() << "Failed to build code:\n" << Code;
llvm_unreachable("Failed to build TestTU!");
@@ -55,13 +69,15 @@ ParsedAST TestTU::build() const {
SymbolSlab TestTU::headerSymbols() const {
auto AST = build();
- return indexHeaderSymbols(AST.getASTContext(), AST.getPreprocessorPtr());
+ return indexHeaderSymbols(AST.getASTContext(), AST.getPreprocessorPtr(),
+ AST.getCanonicalIncludes());
}
std::unique_ptr<SymbolIndex> TestTU::index() const {
auto AST = build();
auto Idx = llvm::make_unique<FileIndex>(/*UseDex=*/true);
- Idx->updatePreamble(Filename, AST.getASTContext(), AST.getPreprocessorPtr());
+ Idx->updatePreamble(Filename, AST.getASTContext(), AST.getPreprocessorPtr(),
+ AST.getCanonicalIncludes());
Idx->updateMain(Filename, AST);
return std::move(Idx);
}
diff --git a/unittests/clangd/TestTU.h b/clangd/unittests/TestTU.h
index ced612fa..6ac4c86a 100644
--- a/unittests/clangd/TestTU.h
+++ b/clangd/unittests/TestTU.h
@@ -1,9 +1,8 @@
//===--- TestTU.h - Scratch source files for testing -------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -19,8 +18,13 @@
#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTTU_H
#include "ClangdUnit.h"
+#include "Path.h"
#include "index/Index.h"
+#include "llvm/ADT/StringMap.h"
#include "gtest/gtest.h"
+#include <string>
+#include <utility>
+#include <vector>
namespace clang {
namespace clangd {
@@ -46,9 +50,19 @@ struct TestTU {
std::string HeaderCode;
std::string HeaderFilename = "TestTU.h";
+ // Name and contents of each file.
+ llvm::StringMap<std::string> AdditionalFiles;
+
// Extra arguments for the compiler invocation.
std::vector<const char *> ExtraArgs;
+ llvm::Optional<std::string> ClangTidyChecks;
+ // Index to use when building AST.
+ const SymbolIndex *ExternalIndex = nullptr;
+
+ // Simulate a header guard of the header (using an #import directive).
+ bool ImplicitHeaderGuard = true;
+
ParsedAST build() const;
SymbolSlab headerSymbols() const;
std::unique_ptr<SymbolIndex> index() const;
diff --git a/unittests/clangd/ThreadingTests.cpp b/clangd/unittests/ThreadingTests.cpp
index dd27dcce..18b9146e 100644
--- a/unittests/clangd/ThreadingTests.cpp
+++ b/clangd/unittests/ThreadingTests.cpp
@@ -1,9 +1,8 @@
//===-- ThreadingTests.cpp --------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clangd/TraceTests.cpp b/clangd/unittests/TraceTests.cpp
index 98115651..1871e6ac 100644
--- a/unittests/clangd/TraceTests.cpp
+++ b/clangd/unittests/TraceTests.cpp
@@ -1,9 +1,8 @@
//===-- TraceTests.cpp - Tracing unit tests ---------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/unittests/TweakTests.cpp b/clangd/unittests/TweakTests.cpp
new file mode 100644
index 00000000..baa60292
--- /dev/null
+++ b/clangd/unittests/TweakTests.cpp
@@ -0,0 +1,190 @@
+//===-- TweakTests.cpp ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Annotations.h"
+#include "SourceCode.h"
+#include "TestTU.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/Expr.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <cassert>
+
+using llvm::Failed;
+using llvm::HasValue;
+using llvm::Succeeded;
+
+namespace clang {
+namespace clangd {
+namespace {
+
+std::string markRange(llvm::StringRef Code, Range R) {
+ size_t Begin = llvm::cantFail(positionToOffset(Code, R.start));
+ size_t End = llvm::cantFail(positionToOffset(Code, R.end));
+ assert(Begin <= End);
+ if (Begin == End) // Mark a single point.
+ return (Code.substr(0, Begin) + "^" + Code.substr(Begin)).str();
+ // Mark a range.
+ return (Code.substr(0, Begin) + "[[" + Code.substr(Begin, End - Begin) +
+ "]]" + Code.substr(End))
+ .str();
+}
+
+void checkAvailable(StringRef ID, llvm::StringRef Input, bool Available) {
+ Annotations Code(Input);
+ ASSERT_TRUE(0 < Code.points().size() || 0 < Code.ranges().size())
+ << "no points of interest specified";
+ TestTU TU;
+ TU.Filename = "foo.cpp";
+ TU.Code = Code.code();
+
+ ParsedAST AST = TU.build();
+
+ auto CheckOver = [&](Range Selection) {
+ unsigned Begin = cantFail(positionToOffset(Code.code(), Selection.start));
+ unsigned End = cantFail(positionToOffset(Code.code(), Selection.end));
+ auto T = prepareTweak(ID, Tweak::Selection(AST, Begin, End));
+ if (Available)
+ EXPECT_THAT_EXPECTED(T, Succeeded())
+ << "code is " << markRange(Code.code(), Selection);
+ else
+ EXPECT_THAT_EXPECTED(T, Failed())
+ << "code is " << markRange(Code.code(), Selection);
+ };
+ for (auto P : Code.points())
+ CheckOver(Range{P, P});
+ for (auto R : Code.ranges())
+ CheckOver(R);
+}
+
+/// Checks action is available at every point and range marked in \p Input.
+void checkAvailable(StringRef ID, llvm::StringRef Input) {
+ return checkAvailable(ID, Input, /*Available=*/true);
+}
+
+/// Same as checkAvailable, but checks the action is not available.
+void checkNotAvailable(StringRef ID, llvm::StringRef Input) {
+ return checkAvailable(ID, Input, /*Available=*/false);
+}
+llvm::Expected<std::string> apply(StringRef ID, llvm::StringRef Input) {
+ Annotations Code(Input);
+ Range SelectionRng;
+ if (Code.points().size() != 0) {
+ assert(Code.ranges().size() == 0 &&
+ "both a cursor point and a selection range were specified");
+ SelectionRng = Range{Code.point(), Code.point()};
+ } else {
+ SelectionRng = Code.range();
+ }
+ TestTU TU;
+ TU.Filename = "foo.cpp";
+ TU.Code = Code.code();
+
+ ParsedAST AST = TU.build();
+ unsigned Begin = cantFail(positionToOffset(Code.code(), SelectionRng.start));
+ unsigned End = cantFail(positionToOffset(Code.code(), SelectionRng.end));
+ Tweak::Selection S(AST, Begin, End);
+
+ auto T = prepareTweak(ID, S);
+ if (!T)
+ return T.takeError();
+ auto Replacements = (*T)->apply(S);
+ if (!Replacements)
+ return Replacements.takeError();
+ return applyAllReplacements(Code.code(), *Replacements);
+}
+
+void checkTransform(llvm::StringRef ID, llvm::StringRef Input,
+ llvm::StringRef Output) {
+ EXPECT_THAT_EXPECTED(apply(ID, Input), HasValue(Output))
+ << "action id is" << ID;
+}
+
+TEST(TweakTest, SwapIfBranches) {
+ llvm::StringLiteral ID = "SwapIfBranches";
+
+ checkAvailable(ID, R"cpp(
+ void test() {
+ ^i^f^^(^t^r^u^e^) { return 100; } ^e^l^s^e^ { continue; }
+ }
+ )cpp");
+
+ checkNotAvailable(ID, R"cpp(
+ void test() {
+ if (true) {^return ^100;^ } else { ^continue^;^ }
+ }
+ )cpp");
+
+ llvm::StringLiteral Input = R"cpp(
+ void test() {
+ ^if (true) { return 100; } else { continue; }
+ }
+ )cpp";
+ llvm::StringLiteral Output = R"cpp(
+ void test() {
+ if (true) { continue; } else { return 100; }
+ }
+ )cpp";
+ checkTransform(ID, Input, Output);
+
+ Input = R"cpp(
+ void test() {
+ ^if () { return 100; } else { continue; }
+ }
+ )cpp";
+ Output = R"cpp(
+ void test() {
+ if () { continue; } else { return 100; }
+ }
+ )cpp";
+ checkTransform(ID, Input, Output);
+
+ // Available in subexpressions of the condition.
+ checkAvailable(ID, R"cpp(
+ void test() {
+ if(2 + [[2]] + 2) { return 2 + 2 + 2; } else { continue; }
+ }
+ )cpp");
+ // But not as part of the branches.
+ checkNotAvailable(ID, R"cpp(
+ void test() {
+ if(2 + 2 + 2) { return 2 + [[2]] + 2; } else { continue; }
+ }
+ )cpp");
+ // Range covers the "else" token, so available.
+ checkAvailable(ID, R"cpp(
+ void test() {
+ if(2 + 2 + 2) { return 2 + [[2 + 2; } else { continue;]] }
+ }
+ )cpp");
+ // Not available in compound statements in condition.
+ checkNotAvailable(ID, R"cpp(
+ void test() {
+ if([]{return [[true]];}()) { return 2 + 2 + 2; } else { continue; }
+ }
+ )cpp");
+ // Not available if both sides aren't braced.
+ checkNotAvailable(ID, R"cpp(
+ void test() {
+ ^if (1) return; else { return; }
+ }
+ )cpp");
+ // Only one if statement is supported!
+ checkNotAvailable(ID, R"cpp(
+ [[if(1){}else{}if(2){}else{}]]
+ )cpp");
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/clangd/unittests/TypeHierarchyTests.cpp b/clangd/unittests/TypeHierarchyTests.cpp
new file mode 100644
index 00000000..9fcb94a9
--- /dev/null
+++ b/clangd/unittests/TypeHierarchyTests.cpp
@@ -0,0 +1,455 @@
+//===-- TypeHierarchyTests.cpp ---------------------------*- C++ -*-------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "Annotations.h"
+#include "ClangdUnit.h"
+#include "Compiler.h"
+#include "Matchers.h"
+#include "SyncAPI.h"
+#include "TestFS.h"
+#include "TestTU.h"
+#include "XRefs.h"
+#include "index/FileIndex.h"
+#include "index/SymbolCollector.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Index/IndexingAction.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+using ::testing::AllOf;
+using ::testing::ElementsAre;
+using ::testing::Eq;
+using ::testing::Field;
+using ::testing::IsEmpty;
+using ::testing::Matcher;
+using ::testing::Pointee;
+using ::testing::UnorderedElementsAreArray;
+
+// GMock helpers for matching TypeHierarchyItem.
+MATCHER_P(WithName, N, "") { return arg.name == N; }
+MATCHER_P(WithKind, Kind, "") { return arg.kind == Kind; }
+MATCHER_P(SelectionRangeIs, R, "") { return arg.selectionRange == R; }
+template <class... ParentMatchers>
+::testing::Matcher<TypeHierarchyItem> Parents(ParentMatchers... ParentsM) {
+ return Field(&TypeHierarchyItem::parents, HasValue(ElementsAre(ParentsM...)));
+}
+
+TEST(FindRecordTypeAt, TypeOrVariable) {
+ Annotations Source(R"cpp(
+struct Ch^ild2 {
+ int c;
+};
+
+int main() {
+ Ch^ild2 ch^ild2;
+ ch^ild2.c = 1;
+}
+)cpp");
+
+ TestTU TU = TestTU::withCode(Source.code());
+ auto AST = TU.build();
+
+ ASSERT_TRUE(AST.getDiagnostics().empty());
+
+ for (Position Pt : Source.points()) {
+ const CXXRecordDecl *RD = findRecordTypeAt(AST, Pt);
+ EXPECT_EQ(&findDecl(AST, "Child2"), static_cast<const NamedDecl *>(RD));
+ }
+}
+
+TEST(FindRecordTypeAt, Method) {
+ Annotations Source(R"cpp(
+struct Child2 {
+ void met^hod ();
+ void met^hod (int x);
+};
+
+int main() {
+ Child2 child2;
+ child2.met^hod(5);
+}
+)cpp");
+
+ TestTU TU = TestTU::withCode(Source.code());
+ auto AST = TU.build();
+
+ ASSERT_TRUE(AST.getDiagnostics().empty());
+
+ for (Position Pt : Source.points()) {
+ const CXXRecordDecl *RD = findRecordTypeAt(AST, Pt);
+ EXPECT_EQ(&findDecl(AST, "Child2"), static_cast<const NamedDecl *>(RD));
+ }
+}
+
+TEST(FindRecordTypeAt, Field) {
+ Annotations Source(R"cpp(
+struct Child2 {
+ int fi^eld;
+};
+
+int main() {
+ Child2 child2;
+ child2.fi^eld = 5;
+}
+)cpp");
+
+ TestTU TU = TestTU::withCode(Source.code());
+ auto AST = TU.build();
+
+ ASSERT_TRUE(AST.getDiagnostics().empty());
+
+ for (Position Pt : Source.points()) {
+ const CXXRecordDecl *RD = findRecordTypeAt(AST, Pt);
+ // A field does not unambiguously specify a record type
+ // (possible associated reocrd types could be the field's type,
+ // or the type of the record that the field is a member of).
+ EXPECT_EQ(nullptr, RD);
+ }
+}
+
+TEST(TypeParents, SimpleInheritance) {
+ Annotations Source(R"cpp(
+struct Parent {
+ int a;
+};
+
+struct Child1 : Parent {
+ int b;
+};
+
+struct Child2 : Child1 {
+ int c;
+};
+)cpp");
+
+ TestTU TU = TestTU::withCode(Source.code());
+ auto AST = TU.build();
+
+ ASSERT_TRUE(AST.getDiagnostics().empty());
+
+ const CXXRecordDecl *Parent =
+ dyn_cast<CXXRecordDecl>(&findDecl(AST, "Parent"));
+ const CXXRecordDecl *Child1 =
+ dyn_cast<CXXRecordDecl>(&findDecl(AST, "Child1"));
+ const CXXRecordDecl *Child2 =
+ dyn_cast<CXXRecordDecl>(&findDecl(AST, "Child2"));
+
+ EXPECT_THAT(typeParents(Parent), ElementsAre());
+ EXPECT_THAT(typeParents(Child1), ElementsAre(Parent));
+ EXPECT_THAT(typeParents(Child2), ElementsAre(Child1));
+}
+
+TEST(TypeParents, MultipleInheritance) {
+ Annotations Source(R"cpp(
+struct Parent1 {
+ int a;
+};
+
+struct Parent2 {
+ int b;
+};
+
+struct Parent3 : Parent2 {
+ int c;
+};
+
+struct Child : Parent1, Parent3 {
+ int d;
+};
+)cpp");
+
+ TestTU TU = TestTU::withCode(Source.code());
+ auto AST = TU.build();
+
+ ASSERT_TRUE(AST.getDiagnostics().empty());
+
+ const CXXRecordDecl *Parent1 =
+ dyn_cast<CXXRecordDecl>(&findDecl(AST, "Parent1"));
+ const CXXRecordDecl *Parent2 =
+ dyn_cast<CXXRecordDecl>(&findDecl(AST, "Parent2"));
+ const CXXRecordDecl *Parent3 =
+ dyn_cast<CXXRecordDecl>(&findDecl(AST, "Parent3"));
+ const CXXRecordDecl *Child = dyn_cast<CXXRecordDecl>(&findDecl(AST, "Child"));
+
+ EXPECT_THAT(typeParents(Parent1), ElementsAre());
+ EXPECT_THAT(typeParents(Parent2), ElementsAre());
+ EXPECT_THAT(typeParents(Parent3), ElementsAre(Parent2));
+ EXPECT_THAT(typeParents(Child), ElementsAre(Parent1, Parent3));
+}
+
+TEST(TypeParents, ClassTemplate) {
+ Annotations Source(R"cpp(
+struct Parent {};
+
+template <typename T>
+struct Child : Parent {};
+)cpp");
+
+ TestTU TU = TestTU::withCode(Source.code());
+ auto AST = TU.build();
+
+ ASSERT_TRUE(AST.getDiagnostics().empty());
+
+ const CXXRecordDecl *Parent =
+ dyn_cast<CXXRecordDecl>(&findDecl(AST, "Parent"));
+ const CXXRecordDecl *Child =
+ dyn_cast<ClassTemplateDecl>(&findDecl(AST, "Child"))->getTemplatedDecl();
+
+ EXPECT_THAT(typeParents(Child), ElementsAre(Parent));
+}
+
+MATCHER_P(ImplicitSpecOf, ClassTemplate, "") {
+ const ClassTemplateSpecializationDecl *CTS =
+ dyn_cast<ClassTemplateSpecializationDecl>(arg);
+ return CTS &&
+ CTS->getSpecializedTemplate()->getTemplatedDecl() == ClassTemplate &&
+ CTS->getSpecializationKind() == TSK_ImplicitInstantiation;
+}
+
+// This is similar to findDecl(AST, QName), but supports using
+// a template-id as a query.
+const NamedDecl &findDeclWithTemplateArgs(ParsedAST &AST,
+ llvm::StringRef Query) {
+ return findDecl(AST, [&Query](const NamedDecl &ND) {
+ std::string QName;
+ llvm::raw_string_ostream OS(QName);
+ PrintingPolicy Policy(ND.getASTContext().getLangOpts());
+ // Use getNameForDiagnostic() which includes the template
+ // arguments in the printed name.
+ ND.getNameForDiagnostic(OS, Policy, /*Qualified=*/true);
+ OS.flush();
+ return QName == Query;
+ });
+}
+
+TEST(TypeParents, TemplateSpec1) {
+ Annotations Source(R"cpp(
+template <typename T>
+struct Parent {};
+
+template <>
+struct Parent<int> {};
+
+struct Child1 : Parent<float> {};
+
+struct Child2 : Parent<int> {};
+)cpp");
+
+ TestTU TU = TestTU::withCode(Source.code());
+ auto AST = TU.build();
+
+ ASSERT_TRUE(AST.getDiagnostics().empty());
+
+ const CXXRecordDecl *Parent =
+ dyn_cast<ClassTemplateDecl>(&findDecl(AST, "Parent"))->getTemplatedDecl();
+ const CXXRecordDecl *ParentSpec =
+ dyn_cast<CXXRecordDecl>(&findDeclWithTemplateArgs(AST, "Parent<int>"));
+ const CXXRecordDecl *Child1 =
+ dyn_cast<CXXRecordDecl>(&findDecl(AST, "Child1"));
+ const CXXRecordDecl *Child2 =
+ dyn_cast<CXXRecordDecl>(&findDecl(AST, "Child2"));
+
+ EXPECT_THAT(typeParents(Child1), ElementsAre(ImplicitSpecOf(Parent)));
+ EXPECT_THAT(typeParents(Child2), ElementsAre(ParentSpec));
+}
+
+TEST(TypeParents, TemplateSpec2) {
+ Annotations Source(R"cpp(
+struct Parent {};
+
+template <typename T>
+struct Child {};
+
+template <>
+struct Child<int> : Parent {};
+)cpp");
+
+ TestTU TU = TestTU::withCode(Source.code());
+ auto AST = TU.build();
+
+ ASSERT_TRUE(AST.getDiagnostics().empty());
+
+ const CXXRecordDecl *Parent =
+ dyn_cast<CXXRecordDecl>(&findDecl(AST, "Parent"));
+ const CXXRecordDecl *Child =
+ dyn_cast<ClassTemplateDecl>(&findDecl(AST, "Child"))->getTemplatedDecl();
+ const CXXRecordDecl *ChildSpec =
+ dyn_cast<CXXRecordDecl>(&findDeclWithTemplateArgs(AST, "Child<int>"));
+
+ EXPECT_THAT(typeParents(Child), ElementsAre());
+ EXPECT_THAT(typeParents(ChildSpec), ElementsAre(Parent));
+}
+
+TEST(TypeParents, DependentBase) {
+ Annotations Source(R"cpp(
+template <typename T>
+struct Parent {};
+
+template <typename T>
+struct Child1 : Parent<T> {};
+
+template <typename T>
+struct Child2 : Parent<T>::Type {};
+
+template <typename T>
+struct Child3 : T {};
+)cpp");
+
+ TestTU TU = TestTU::withCode(Source.code());
+ auto AST = TU.build();
+
+ ASSERT_TRUE(AST.getDiagnostics().empty());
+
+ const CXXRecordDecl *Parent =
+ dyn_cast<ClassTemplateDecl>(&findDecl(AST, "Parent"))->getTemplatedDecl();
+ const CXXRecordDecl *Child1 =
+ dyn_cast<ClassTemplateDecl>(&findDecl(AST, "Child1"))->getTemplatedDecl();
+ const CXXRecordDecl *Child2 =
+ dyn_cast<ClassTemplateDecl>(&findDecl(AST, "Child2"))->getTemplatedDecl();
+ const CXXRecordDecl *Child3 =
+ dyn_cast<ClassTemplateDecl>(&findDecl(AST, "Child3"))->getTemplatedDecl();
+
+ // For "Parent<T>", use the primary template as a best-effort guess.
+ EXPECT_THAT(typeParents(Child1), ElementsAre(Parent));
+ // For "Parent<T>::Type", there is nothing we can do.
+ EXPECT_THAT(typeParents(Child2), ElementsAre());
+ // Likewise for "T".
+ EXPECT_THAT(typeParents(Child3), ElementsAre());
+}
+
+// Parts of getTypeHierarchy() are tested in more detail by the
+// FindRecordTypeAt.* and TypeParents.* tests above. This test exercises the
+// entire operation.
+TEST(TypeHierarchy, Parents) {
+ Annotations Source(R"cpp(
+struct $Parent1Def[[Parent1]] {
+ int a;
+};
+
+struct $Parent2Def[[Parent2]] {
+ int b;
+};
+
+struct $Parent3Def[[Parent3]] : Parent2 {
+ int c;
+};
+
+struct Ch^ild : Parent1, Parent3 {
+ int d;
+};
+
+int main() {
+ Ch^ild ch^ild;
+
+ ch^ild.a = 1;
+}
+)cpp");
+
+ TestTU TU = TestTU::withCode(Source.code());
+ auto AST = TU.build();
+
+ for (Position Pt : Source.points()) {
+ // Set ResolveLevels to 0 because it's only used for Children;
+ // for Parents, getTypeHierarchy() always returns all levels.
+ llvm::Optional<TypeHierarchyItem> Result = getTypeHierarchy(
+ AST, Pt, /*ResolveLevels=*/0, TypeHierarchyDirection::Parents);
+ ASSERT_TRUE(bool(Result));
+ EXPECT_THAT(
+ *Result,
+ AllOf(
+ WithName("Child"), WithKind(SymbolKind::Struct),
+ Parents(AllOf(WithName("Parent1"), WithKind(SymbolKind::Struct),
+ SelectionRangeIs(Source.range("Parent1Def")),
+ Parents()),
+ AllOf(WithName("Parent3"), WithKind(SymbolKind::Struct),
+ SelectionRangeIs(Source.range("Parent3Def")),
+ Parents(AllOf(
+ WithName("Parent2"), WithKind(SymbolKind::Struct),
+ SelectionRangeIs(Source.range("Parent2Def")),
+ Parents()))))));
+ }
+}
+
+TEST(TypeHierarchy, RecursiveHierarchyUnbounded) {
+ Annotations Source(R"cpp(
+ template <int N>
+ struct $SDef[[S]] : S<N + 1> {};
+
+ S^<0> s;
+ )cpp");
+
+ TestTU TU = TestTU::withCode(Source.code());
+ auto AST = TU.build();
+
+ // The compiler should produce a diagnostic for hitting the
+ // template instantiation depth.
+ ASSERT_TRUE(!AST.getDiagnostics().empty());
+
+ // Make sure getTypeHierarchy() doesn't get into an infinite recursion.
+ // FIXME(nridge): It would be preferable if the type hierarchy gave us type
+ // names (e.g. "S<0>" for the child and "S<1>" for the parent) rather than
+ // template names (e.g. "S").
+ llvm::Optional<TypeHierarchyItem> Result = getTypeHierarchy(
+ AST, Source.points()[0], 0, TypeHierarchyDirection::Parents);
+ ASSERT_TRUE(bool(Result));
+ EXPECT_THAT(
+ *Result,
+ AllOf(WithName("S"), WithKind(SymbolKind::Struct),
+ Parents(AllOf(WithName("S"), WithKind(SymbolKind::Struct),
+ SelectionRangeIs(Source.range("SDef")), Parents()))));
+}
+
+TEST(TypeHierarchy, RecursiveHierarchyBounded) {
+ Annotations Source(R"cpp(
+ template <int N>
+ struct $SDef[[S]] : S<N - 1> {};
+
+ template <>
+ struct S<0>{};
+
+ S$SRefConcrete^<2> s;
+
+ template <int N>
+ struct Foo {
+ S$SRefDependent^<N> s;
+ };)cpp");
+
+ TestTU TU = TestTU::withCode(Source.code());
+ auto AST = TU.build();
+
+ ASSERT_TRUE(AST.getDiagnostics().empty());
+
+ // Make sure getTypeHierarchy() doesn't get into an infinite recursion
+ // for either a concrete starting point or a dependent starting point.
+ llvm::Optional<TypeHierarchyItem> Result = getTypeHierarchy(
+ AST, Source.point("SRefConcrete"), 0, TypeHierarchyDirection::Parents);
+ ASSERT_TRUE(bool(Result));
+ EXPECT_THAT(
+ *Result,
+ AllOf(WithName("S"), WithKind(SymbolKind::Struct),
+ Parents(AllOf(WithName("S"), WithKind(SymbolKind::Struct),
+ SelectionRangeIs(Source.range("SDef")), Parents()))));
+ Result = getTypeHierarchy(AST, Source.point("SRefDependent"), 0,
+ TypeHierarchyDirection::Parents);
+ ASSERT_TRUE(bool(Result));
+ EXPECT_THAT(
+ *Result,
+ AllOf(WithName("S"), WithKind(SymbolKind::Struct),
+ Parents(AllOf(WithName("S"), WithKind(SymbolKind::Struct),
+ SelectionRangeIs(Source.range("SDef")), Parents()))));
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/unittests/clangd/URITests.cpp b/clangd/unittests/URITests.cpp
index ae84d56e..52ca7b44 100644
--- a/unittests/clangd/URITests.cpp
+++ b/clangd/unittests/URITests.cpp
@@ -1,9 +1,8 @@
//===-- URITests.cpp ---------------------------------*- C++ -*-----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clangd/XRefsTests.cpp b/clangd/unittests/XRefsTests.cpp
index 88394b6c..77fa042c 100644
--- a/unittests/clangd/XRefsTests.cpp
+++ b/clangd/unittests/XRefsTests.cpp
@@ -1,9 +1,8 @@
//===-- XRefsTests.cpp ---------------------------*- C++ -*--------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "Annotations.h"
@@ -18,6 +17,7 @@
#include "index/SymbolCollector.h"
#include "clang/Index/IndexingAction.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/ScopedPrinter.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -25,11 +25,10 @@ namespace clang {
namespace clangd {
namespace {
-using testing::ElementsAre;
-using testing::Field;
-using testing::IsEmpty;
-using testing::Matcher;
-using testing::UnorderedElementsAreArray;
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
+using ::testing::Matcher;
+using ::testing::UnorderedElementsAreArray;
class IgnoreDiagnostics : public DiagnosticsConsumer {
void onDiagnosticsReady(PathRef File,
@@ -87,6 +86,10 @@ TEST(HighlightsTest, All) {
auto *X = &[[foo]];
}
)cpp",
+
+ R"cpp(// Function parameter in decl
+ void foo(int [[^bar]]);
+ )cpp",
};
for (const char *Test : Tests) {
Annotations T(Test);
@@ -96,9 +99,35 @@ TEST(HighlightsTest, All) {
}
}
+MATCHER_P3(Sym, Name, Decl, DefOrNone, "") {
+ llvm::Optional<Range> Def = DefOrNone;
+ if (Name != arg.Name) {
+ *result_listener << "Name is " << arg.Name;
+ return false;
+ }
+ if (Decl != arg.PreferredDeclaration.range) {
+ *result_listener << "Declaration is "
+ << llvm::to_string(arg.PreferredDeclaration);
+ return false;
+ }
+ if (Def && !arg.Definition) {
+ *result_listener << "Has no definition";
+ return false;
+ }
+ if (Def && arg.Definition->range != *Def) {
+ *result_listener << "Definition is " << llvm::to_string(arg.Definition);
+ return false;
+ }
+ return true;
+}
+::testing::Matcher<LocatedSymbol> Sym(std::string Name, Range Decl) {
+ return Sym(Name, Decl, llvm::None);
+}
+MATCHER_P(Sym, Name, "") { return arg.Name == Name; }
+
MATCHER_P(RangeIs, R, "") { return arg.range == R; }
-TEST(GoToDefinition, WithIndex) {
+TEST(LocateSymbol, WithIndex) {
Annotations SymbolHeader(R"cpp(
class $forward[[Forward]];
class $foo[[Foo]] {};
@@ -116,9 +145,9 @@ TEST(GoToDefinition, WithIndex) {
TU.Code = SymbolCpp.code();
TU.HeaderCode = SymbolHeader.code();
auto Index = TU.index();
- auto runFindDefinitionsWithIndex = [&Index](const Annotations &Main) {
+ auto LocateWithIndex = [&Index](const Annotations &Main) {
auto AST = TestTU::withCode(Main.code()).build();
- return clangd::findDefinitions(AST, Main.point(), Index.get());
+ return clangd::locateSymbolAt(AST, Main.point(), Index.get());
};
Annotations Test(R"cpp(// only declaration in AST.
@@ -127,9 +156,8 @@ TEST(GoToDefinition, WithIndex) {
^f1();
}
)cpp");
- EXPECT_THAT(runFindDefinitionsWithIndex(Test),
- testing::ElementsAreArray(
- {RangeIs(SymbolCpp.range("f1")), RangeIs(Test.range())}));
+ EXPECT_THAT(LocateWithIndex(Test),
+ ElementsAre(Sym("f1", Test.range(), SymbolCpp.range("f1"))));
Test = Annotations(R"cpp(// definition in AST.
void [[f1]]() {}
@@ -137,30 +165,63 @@ TEST(GoToDefinition, WithIndex) {
^f1();
}
)cpp");
- EXPECT_THAT(runFindDefinitionsWithIndex(Test),
- testing::ElementsAreArray(
- {RangeIs(Test.range()), RangeIs(SymbolHeader.range("f1"))}));
+ EXPECT_THAT(LocateWithIndex(Test),
+ ElementsAre(Sym("f1", SymbolHeader.range("f1"), Test.range())));
Test = Annotations(R"cpp(// forward declaration in AST.
class [[Foo]];
F^oo* create();
)cpp");
- EXPECT_THAT(runFindDefinitionsWithIndex(Test),
- testing::ElementsAreArray(
- {RangeIs(SymbolHeader.range("foo")), RangeIs(Test.range())}));
+ EXPECT_THAT(LocateWithIndex(Test),
+ ElementsAre(Sym("Foo", Test.range(), SymbolHeader.range("foo"))));
Test = Annotations(R"cpp(// defintion in AST.
class [[Forward]] {};
F^orward create();
)cpp");
- EXPECT_THAT(runFindDefinitionsWithIndex(Test),
- testing::ElementsAreArray({
- RangeIs(Test.range()),
- RangeIs(SymbolHeader.range("forward")),
- }));
+ EXPECT_THAT(
+ LocateWithIndex(Test),
+ ElementsAre(Sym("Forward", SymbolHeader.range("forward"), Test.range())));
+}
+
+TEST(LocateSymbol, WithIndexPreferredLocation) {
+ Annotations SymbolHeader(R"cpp(
+ class $p[[Proto]] {};
+ void $f[[func]]() {};
+ )cpp");
+ TestTU TU;
+ TU.HeaderCode = SymbolHeader.code();
+ TU.HeaderFilename = "x.proto"; // Prefer locations in codegen files.
+ auto Index = TU.index();
+
+ Annotations Test(R"cpp(// only declaration in AST.
+ // Shift to make range different.
+ class Proto;
+ void func() {}
+ P$p^roto* create() {
+ fu$f^nc();
+ return nullptr;
+ }
+ )cpp");
+
+ auto AST = TestTU::withCode(Test.code()).build();
+ {
+ auto Locs = clangd::locateSymbolAt(AST, Test.point("p"), Index.get());
+ auto CodeGenLoc = SymbolHeader.range("p");
+ EXPECT_THAT(Locs, ElementsAre(Sym("Proto", CodeGenLoc, CodeGenLoc)));
+ }
+ {
+ auto Locs = clangd::locateSymbolAt(AST, Test.point("f"), Index.get());
+ auto CodeGenLoc = SymbolHeader.range("f");
+ EXPECT_THAT(Locs, ElementsAre(Sym("func", CodeGenLoc, CodeGenLoc)));
+ }
}
-TEST(GoToDefinition, All) {
+TEST(LocateSymbol, All) {
+ // Ranges in tests:
+ // $decl is the declaration location (if absent, no symbol is located)
+ // $def is the definition location (if absent, symbol has no definition)
+ // unnamed range becomes both $decl and $def.
const char *Tests[] = {
R"cpp(// Local variable
int main() {
@@ -187,7 +248,7 @@ TEST(GoToDefinition, All) {
)cpp",
R"cpp(// Function declaration via call
- int [[foo]](int);
+ int $decl[[foo]](int);
int main() {
return ^foo(42);
}
@@ -223,7 +284,7 @@ TEST(GoToDefinition, All) {
)cpp",
R"cpp(// Method call
- struct Foo { int [[x]](); };
+ struct Foo { int $decl[[x]](); };
int main() {
Foo bar;
bar.^x();
@@ -231,20 +292,24 @@ TEST(GoToDefinition, All) {
)cpp",
R"cpp(// Typedef
- typedef int [[Foo]];
+ typedef int $decl[[Foo]];
int main() {
^Foo bar;
}
)cpp",
- /* FIXME: clangIndex doesn't handle template type parameters
R"cpp(// Template type parameter
- template <[[typename T]]>
+ template <typename [[T]]>
void foo() { ^T t; }
- )cpp", */
+ )cpp",
+
+ R"cpp(// Template template type parameter
+ template <template<typename> class [[T]]>
+ void foo() { ^T<int> t; }
+ )cpp",
R"cpp(// Namespace
- namespace [[ns]] {
+ namespace $decl[[ns]] {
struct Foo { static void bar(); }
} // namespace ns
int main() { ^ns::Foo::bar(); }
@@ -302,61 +367,137 @@ TEST(GoToDefinition, All) {
FF();
void f() { T^est a; }
)cpp",
+
+ R"cpp(// explicit template specialization
+ template <typename T>
+ struct Foo { void bar() {} };
+
+ template <>
+ struct [[Foo]]<int> { void bar() {} };
+
+ void foo() {
+ Foo<char> abc;
+ Fo^o<int> b;
+ }
+ )cpp",
+
+ R"cpp(// implicit template specialization
+ template <typename T>
+ struct [[Foo]] { void bar() {} };
+ template <>
+ struct Foo<int> { void bar() {} };
+ void foo() {
+ Fo^o<char> abc;
+ Foo<int> b;
+ }
+ )cpp",
+
+ R"cpp(// partial template specialization
+ template <typename T>
+ struct Foo { void bar() {} };
+ template <typename T>
+ struct [[Foo]]<T*> { void bar() {} };
+ ^Foo<int*> x;
+ )cpp",
+
+ R"cpp(// function template specializations
+ template <class T>
+ void foo(T) {}
+ template <>
+ void [[foo]](int) {}
+ void bar() {
+ fo^o(10);
+ }
+ )cpp",
+
+ R"cpp(// variable template decls
+ template <class T>
+ T var = T();
+
+ template <>
+ double [[var]]<int> = 10;
+
+ double y = va^r<int>;
+ )cpp",
+
+ R"cpp(// No implicit constructors
+ class X {
+ X(X&& x) = default;
+ };
+ X [[makeX]]() {}
+ void foo() {
+ auto x = m^akeX();
+ }
+ )cpp",
};
for (const char *Test : Tests) {
Annotations T(Test);
+ llvm::Optional<Range> WantDecl;
+ llvm::Optional<Range> WantDef;
+ if (!T.ranges().empty())
+ WantDecl = WantDef = T.range();
+ if (!T.ranges("decl").empty())
+ WantDecl = T.range("decl");
+ if (!T.ranges("def").empty())
+ WantDef = T.range("def");
+
auto AST = TestTU::withCode(T.code()).build();
- std::vector<Matcher<Location>> ExpectedLocations;
- for (const auto &R : T.ranges())
- ExpectedLocations.push_back(RangeIs(R));
- EXPECT_THAT(findDefinitions(AST, T.point()),
- ElementsAreArray(ExpectedLocations))
- << Test;
+ auto Results = locateSymbolAt(AST, T.point());
+
+ if (!WantDecl) {
+ EXPECT_THAT(Results, IsEmpty()) << Test;
+ } else {
+ ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
+ EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
+ llvm::Optional<Range> GotDef;
+ if (Results[0].Definition)
+ GotDef = Results[0].Definition->range;
+ EXPECT_EQ(WantDef, GotDef) << Test;
+ }
}
}
-TEST(GoToDefinition, Rank) {
+TEST(LocateSymbol, Ambiguous) {
auto T = Annotations(R"cpp(
- struct $foo1[[Foo]] {
- $foo2[[Foo]]();
- $foo3[[Foo]](Foo&&);
- $foo4[[Foo]](const char*);
+ struct Foo {
+ Foo();
+ Foo(Foo&&);
+ Foo(const char*);
};
- Foo $f[[f]]();
+ Foo f();
- void $g[[g]](Foo foo);
+ void g(Foo foo);
void call() {
- const char* $str[[str]] = "123";
+ const char* str = "123";
Foo a = $1^str;
Foo b = Foo($2^str);
Foo c = $3^f();
$4^g($5^f());
g($6^str);
+ Foo ab$7^c;
+ Foo ab$8^cd("asdf");
+ Foo foox = Fo$9^o("asdf");
}
)cpp");
auto AST = TestTU::withCode(T.code()).build();
- EXPECT_THAT(findDefinitions(AST, T.point("1")),
- ElementsAre(RangeIs(T.range("str")), RangeIs(T.range("foo4"))));
- EXPECT_THAT(findDefinitions(AST, T.point("2")),
- ElementsAre(RangeIs(T.range("str"))));
- EXPECT_THAT(findDefinitions(AST, T.point("3")),
- ElementsAre(RangeIs(T.range("f")), RangeIs(T.range("foo3"))));
- EXPECT_THAT(findDefinitions(AST, T.point("4")),
- ElementsAre(RangeIs(T.range("g"))));
- EXPECT_THAT(findDefinitions(AST, T.point("5")),
- ElementsAre(RangeIs(T.range("f")), RangeIs(T.range("foo3"))));
-
- auto DefinitionAtPoint6 = findDefinitions(AST, T.point("6"));
- EXPECT_EQ(3ul, DefinitionAtPoint6.size());
- EXPECT_THAT(DefinitionAtPoint6, HasSubsequence(RangeIs(T.range("str")),
- RangeIs(T.range("foo4"))));
- EXPECT_THAT(DefinitionAtPoint6, HasSubsequence(RangeIs(T.range("str")),
- RangeIs(T.range("foo3"))));
+ // Ordered assertions are deliberate: we expect a predictable order.
+ EXPECT_THAT(locateSymbolAt(AST, T.point("1")), ElementsAre(Sym("str")));
+ EXPECT_THAT(locateSymbolAt(AST, T.point("2")), ElementsAre(Sym("str")));
+ EXPECT_THAT(locateSymbolAt(AST, T.point("3")), ElementsAre(Sym("f")));
+ EXPECT_THAT(locateSymbolAt(AST, T.point("4")), ElementsAre(Sym("g")));
+ EXPECT_THAT(locateSymbolAt(AST, T.point("5")), ElementsAre(Sym("f")));
+ EXPECT_THAT(locateSymbolAt(AST, T.point("6")), ElementsAre(Sym("str")));
+ EXPECT_THAT(locateSymbolAt(AST, T.point("7")), ElementsAre(Sym("abc")));
+ EXPECT_THAT(locateSymbolAt(AST, T.point("8")),
+ ElementsAre(Sym("Foo"), Sym("abcd")));
+ EXPECT_THAT(locateSymbolAt(AST, T.point("9")),
+ // First one is class definition, second is the constructor.
+ ElementsAre(Sym("Foo"), Sym("Foo")));
}
-TEST(GoToDefinition, RelPathsInCompileCommand) {
+TEST(LocateSymbol, RelPathsInCompileCommand) {
// The source is in "/clangd-test/src".
// We build in "/clangd-test/build".
@@ -398,24 +539,23 @@ int [[bar_not_preamble]];
// Go to a definition in main source file.
auto Locations =
- runFindDefinitions(Server, FooCpp, SourceAnnotations.point("p1"));
+ runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p1"));
EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
- EXPECT_THAT(*Locations,
- ElementsAre(FileRange(FooCpp, SourceAnnotations.range())));
+ EXPECT_THAT(*Locations, ElementsAre(Sym("foo", SourceAnnotations.range())));
// Go to a definition in header_in_preamble.h.
- Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("p2"));
+ Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p2"));
EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
- EXPECT_THAT(*Locations,
- ElementsAre(FileRange(HeaderInPreambleH,
- HeaderInPreambleAnnotations.range())));
+ EXPECT_THAT(
+ *Locations,
+ ElementsAre(Sym("bar_preamble", HeaderInPreambleAnnotations.range())));
// Go to a definition in header_not_in_preamble.h.
- Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("p3"));
+ Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p3"));
EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
EXPECT_THAT(*Locations,
- ElementsAre(FileRange(HeaderNotInPreambleH,
- HeaderNotInPreambleAnnotations.range())));
+ ElementsAre(Sym("bar_not_preamble",
+ HeaderNotInPreambleAnnotations.range())));
}
TEST(Hover, All) {
@@ -616,7 +756,25 @@ TEST(Hover, All) {
#define MACRO 2
#undef macro
)cpp",
- "#define MACRO",
+ "#define MACRO 1",
+ },
+ {
+ R"cpp(// Macro
+ #define MACRO 0
+ #define MACRO2 ^MACRO
+ )cpp",
+ "#define MACRO 0",
+ },
+ {
+ R"cpp(// Macro
+ #define MACRO {\
+ return 0;\
+ }
+ int main() ^MACRO
+ )cpp",
+ R"cpp(#define MACRO {\
+ return 0;\
+ })cpp",
},
{
R"cpp(// Forward class declaration
@@ -1062,46 +1220,51 @@ TEST(GoToInclude, All) {
Server.addDocument(FooCpp, SourceAnnotations.code());
// Test include in preamble.
- auto Locations =
- runFindDefinitions(Server, FooCpp, SourceAnnotations.point());
- ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
- EXPECT_THAT(*Locations,
- ElementsAre(FileRange(FooH, HeaderAnnotations.range())));
+ auto Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point());
+ ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
+ EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
// Test include in preamble, last char.
- Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("2"));
- ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
- EXPECT_THAT(*Locations,
- ElementsAre(FileRange(FooH, HeaderAnnotations.range())));
+ Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("2"));
+ ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
+ EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
- Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("3"));
- ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
- EXPECT_THAT(*Locations,
- ElementsAre(FileRange(FooH, HeaderAnnotations.range())));
+ Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("3"));
+ ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
+ EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
// Test include outside of preamble.
- Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("6"));
- ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
- EXPECT_THAT(*Locations,
- ElementsAre(FileRange(FooH, HeaderAnnotations.range())));
+ Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("6"));
+ ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
+ EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
// Test a few positions that do not result in Locations.
- Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("4"));
- ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
+ Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("4"));
+ ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
EXPECT_THAT(*Locations, IsEmpty());
- Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("5"));
- ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
- EXPECT_THAT(*Locations,
- ElementsAre(FileRange(FooH, HeaderAnnotations.range())));
-
- Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("7"));
- ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
- EXPECT_THAT(*Locations,
- ElementsAre(FileRange(FooH, HeaderAnnotations.range())));
+ Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("5"));
+ ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
+ EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
+
+ Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("7"));
+ ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
+ EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
+
+ // Objective C #import directive.
+ Annotations ObjC(R"objc(
+ #import "^foo.h"
+ )objc");
+ auto FooM = testPath("foo.m");
+ FS.Files[FooM] = ObjC.code();
+
+ Server.addDocument(FooM, ObjC.code());
+ Locations = runLocateSymbolAt(Server, FooM, ObjC.point());
+ ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
+ EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
}
-TEST(GoToDefinition, WithPreamble) {
+TEST(LocateSymbol, WithPreamble) {
// Test stragety: AST should always use the latest preamble instead of last
// good preamble.
MockFSProvider FS;
@@ -1121,18 +1284,18 @@ TEST(GoToDefinition, WithPreamble) {
FS.Files[FooH] = FooHeader.code();
runAddDocument(Server, FooCpp, FooWithHeader.code());
- // GoToDefinition goes to a #include file: the result comes from the preamble.
+ // LocateSymbol goes to a #include file: the result comes from the preamble.
EXPECT_THAT(
- cantFail(runFindDefinitions(Server, FooCpp, FooWithHeader.point())),
- ElementsAre(FileRange(FooH, FooHeader.range())));
+ cantFail(runLocateSymbolAt(Server, FooCpp, FooWithHeader.point())),
+ ElementsAre(Sym("foo.h", FooHeader.range())));
// Only preamble is built, and no AST is built in this request.
Server.addDocument(FooCpp, FooWithoutHeader.code(), WantDiagnostics::No);
// We build AST here, and it should use the latest preamble rather than the
// stale one.
EXPECT_THAT(
- cantFail(runFindDefinitions(Server, FooCpp, FooWithoutHeader.point())),
- ElementsAre(FileRange(FooCpp, FooWithoutHeader.range())));
+ cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
+ ElementsAre(Sym("foo", FooWithoutHeader.range())));
// Reset test environment.
runAddDocument(Server, FooCpp, FooWithHeader.code());
@@ -1140,8 +1303,8 @@ TEST(GoToDefinition, WithPreamble) {
Server.addDocument(FooCpp, FooWithoutHeader.code(), WantDiagnostics::Yes);
// Use the AST being built in above request.
EXPECT_THAT(
- cantFail(runFindDefinitions(Server, FooCpp, FooWithoutHeader.point())),
- ElementsAre(FileRange(FooCpp, FooWithoutHeader.range())));
+ cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
+ ElementsAre(Sym("foo", FooWithoutHeader.range())));
}
TEST(FindReferences, WithinAST) {
@@ -1199,6 +1362,15 @@ TEST(FindReferences, WithinAST) {
}
)cpp",
+ R"cpp(// Constructor
+ struct Foo {
+ [[F^oo]](int);
+ };
+ void foo() {
+ Foo f = [[Foo]](42);
+ }
+ )cpp",
+
R"cpp(// Typedef
typedef int [[Foo]];
int main() {
diff --git a/clangd/unittests/lit.cfg.py b/clangd/unittests/lit.cfg.py
new file mode 100644
index 00000000..754835e6
--- /dev/null
+++ b/clangd/unittests/lit.cfg.py
@@ -0,0 +1,21 @@
+import lit.formats
+config.name = "Clangd Unit Tests"
+config.test_format = lit.formats.GoogleTest('.', 'Tests')
+config.test_source_root = config.clangd_binary_dir + "/unittests"
+config.test_exec_root = config.clangd_binary_dir + "/unittests"
+
+# Point the dynamic loader at dynamic libraries in 'lib'.
+# FIXME: it seems every project has a copy of this logic. Move it somewhere.
+import platform
+if platform.system() == 'Darwin':
+ shlibpath_var = 'DYLD_LIBRARY_PATH'
+elif platform.system() == 'Windows':
+ shlibpath_var = 'PATH'
+else:
+ shlibpath_var = 'LD_LIBRARY_PATH'
+config.environment[shlibpath_var] = os.path.pathsep.join((
+ "@SHLIBDIR@", "@LLVM_LIBS_DIR@",
+ config.environment.get(shlibpath_var,'')))
+
+
+
diff --git a/clangd/unittests/lit.site.cfg.py.in b/clangd/unittests/lit.site.cfg.py.in
new file mode 100644
index 00000000..3fdf084a
--- /dev/null
+++ b/clangd/unittests/lit.site.cfg.py.in
@@ -0,0 +1,11 @@
+@LIT_SITE_CFG_IN_HEADER@
+# This is a shim to run the gtest unittests in ../unittests using lit.
+
+config.llvm_libs_dir = "@LLVM_LIBS_DIR@"
+config.shlibdir = "@SHLIBDIR@"
+
+config.clangd_source_dir = "@CMAKE_CURRENT_SOURCE_DIR@/.."
+config.clangd_binary_dir = "@CMAKE_CURRENT_BINARY_DIR@/.."
+
+# Delegate logic to lit.cfg.py.
+lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg.py")
diff --git a/unittests/clangd/xpc/CMakeLists.txt b/clangd/unittests/xpc/CMakeLists.txt
index 229ad5af..21a1667b 100644
--- a/unittests/clangd/xpc/CMakeLists.txt
+++ b/clangd/unittests/xpc/CMakeLists.txt
@@ -8,7 +8,8 @@ include_directories(
${CLANGD_SOURCE_DIR}
)
-add_extra_unittest(ClangdXpcTests
+add_custom_target(ClangdXpcUnitTests)
+add_unittest(ClangdXpcUnitTests ClangdXpcTests
ConversionTests.cpp
)
diff --git a/unittests/clangd/xpc/ConversionTests.cpp b/clangd/unittests/xpc/ConversionTests.cpp
index 7acdc61f..5d0efd83 100644
--- a/unittests/clangd/xpc/ConversionTests.cpp
+++ b/clangd/unittests/xpc/ConversionTests.cpp
@@ -1,9 +1,8 @@
//===-- ConversionTests.cpp --------------------------*- C++ -*-----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/xpc/CMakeLists.txt b/clangd/xpc/CMakeLists.txt
index 788a66f5..f05767c8 100644
--- a/clangd/xpc/CMakeLists.txt
+++ b/clangd/xpc/CMakeLists.txt
@@ -20,10 +20,10 @@ set(LLVM_OPTIONAL_SOURCES Conversion.cpp XPCTransport.cpp)
add_clang_library(clangdXpcJsonConversions
Conversion.cpp
+ LINK_LIBS clangDaemon
)
add_clang_library(clangdXpcTransport
XPCTransport.cpp
- DEPENDS clangdXpcJsonConversions
- LINK_LIBS clangdXpcJsonConversions
+ LINK_LIBS clangDaemon clangdXpcJsonConversions
)
diff --git a/clangd/xpc/Conversion.cpp b/clangd/xpc/Conversion.cpp
index 45bb11af..3e8d36b7 100644
--- a/clangd/xpc/Conversion.cpp
+++ b/clangd/xpc/Conversion.cpp
@@ -1,9 +1,8 @@
//===--- Conversion.cpp - LSP data (de-)serialization through XPC - C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/xpc/Conversion.h b/clangd/xpc/Conversion.h
index 936f51be..fccc095b 100644
--- a/clangd/xpc/Conversion.h
+++ b/clangd/xpc/Conversion.h
@@ -1,9 +1,8 @@
//===--- Conversion.h - LSP data (de-)serialization through XPC -*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/xpc/XPCTransport.cpp b/clangd/xpc/XPCTransport.cpp
index 496d8e47..f7df8a91 100644
--- a/clangd/xpc/XPCTransport.cpp
+++ b/clangd/xpc/XPCTransport.cpp
@@ -1,9 +1,8 @@
//===--- XPCTransport.cpp - sending and receiving LSP messages over XPC ---===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "Conversion.h"
diff --git a/clangd/xpc/framework/CMakeLists.txt b/clangd/xpc/framework/CMakeLists.txt
index a20340fb..7e1ce876 100644
--- a/clangd/xpc/framework/CMakeLists.txt
+++ b/clangd/xpc/framework/CMakeLists.txt
@@ -1,6 +1,7 @@
set(SOURCES
- ClangdXPC.cpp)
+ ClangdXPC.cpp
+)
add_clang_library(ClangdXPCLib SHARED
${SOURCES}
DEPENDS
diff --git a/clangd/xpc/framework/ClangdXPC.cpp b/clangd/xpc/framework/ClangdXPC.cpp
index 6c68f5cd..3b86164e 100644
--- a/clangd/xpc/framework/ClangdXPC.cpp
+++ b/clangd/xpc/framework/ClangdXPC.cpp
@@ -1,3 +1,10 @@
+//===-- ClangdXPC.cpp --------------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
/// Returns the bundle identifier of the Clangd XPC service.
extern "C" const char *clangd_xpc_get_bundle_identifier() {
diff --git a/clangd/xpc/test-client/ClangdXPCTestClient.cpp b/clangd/xpc/test-client/ClangdXPCTestClient.cpp
index da204a69..1cddd06d 100644
--- a/clangd/xpc/test-client/ClangdXPCTestClient.cpp
+++ b/clangd/xpc/test-client/ClangdXPCTestClient.cpp
@@ -1,3 +1,11 @@
+//===-- ClangdXPCTestClient.cpp ----------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
#include "xpc/Conversion.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallString.h"
@@ -41,8 +49,10 @@ int main(int argc, char *argv[]) {
// Open the ClangdXPC dylib in the framework.
std::string LibPath = getLibraryPath();
void *dlHandle = dlopen(LibPath.c_str(), RTLD_LOCAL | RTLD_FIRST);
- if (!dlHandle)
+ if (!dlHandle) {
+ llvm::errs() << "Failed to load framework from \'" << LibPath << "\'\n";
return 1;
+ }
// Lookup the XPC service bundle name, and launch it.
clangd_xpc_get_bundle_identifier_t clangd_xpc_get_bundle_identifier =
diff --git a/docs/README.txt b/docs/README.txt
index 4b607775..cebbf63b 100644
--- a/docs/README.txt
+++ b/docs/README.txt
@@ -1,11 +1,10 @@
--------------------------------------------------------------
-Documentation for the tools of clang-tools-extra repo project
--------------------------------------------------------------
+----------------------------------
+Documentation in clang-tools-extra
+----------------------------------
-Sphinx and doxygen documentation is generated by executing make.
+To generate documentation in HTML format from files in clang-tools-extra/docs,
+build the docs-clang-tools-html target.
-Sphinx html files can be generated separately using make html.
+To generate documentation from the source code using Doxygen, build the
+doxygen-clang-tools target.
-Doxygen html files can also be generated using make doxygen.
-
-The generated documentation will be placed in _build/html.
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index 8731dc73..bb18c6ed 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -1,5 +1,5 @@
===================================================
-Extra Clang Tools 8.0.0 (In-Progress) Release Notes
+Extra Clang Tools 9.0.0 (In-Progress) Release Notes
===================================================
.. contents::
@@ -10,7 +10,7 @@ Written by the `LLVM Team <https://llvm.org/>`_
.. warning::
- These are in-progress notes for the upcoming Extra Clang Tools 8 release.
+ These are in-progress notes for the upcoming Extra Clang Tools 9 release.
Release notes for previous releases can be found on
`the Download Page <https://releases.llvm.org/download.html>`_.
@@ -18,7 +18,7 @@ Introduction
============
This document contains the release notes for the Extra Clang Tools, part of the
-Clang release 8.0.0. Here we describe the status of the Extra Clang Tools in
+Clang release 9.0.0. Here we describe the status of the Extra Clang Tools in
some detail, including major improvements from the previous release and new
feature work. All LLVM releases may be downloaded from the `LLVM releases web
site <https://llvm.org/releases/>`_.
@@ -32,7 +32,7 @@ main Clang web page, this document applies to the *next* release, not
the current one. To see the release notes for a specific release, please
see the `releases page <https://llvm.org/releases/>`_.
-What's New in Extra Clang Tools 8.0.0?
+What's New in Extra Clang Tools 9.0.0?
======================================
Some of the major new features and improvements to Extra Clang Tools are listed
@@ -57,47 +57,7 @@ The improvements are...
Improvements to clang-query
---------------------------
-- A new command line parameter ``--preload`` was added to
- run commands from a file and then start the interactive interpreter.
-
-- The command ``q`` can was added as an alias for ``quit`` to exit the
- ``clang-query`` interpreter.
-
-- It is now possible to bind to named values (the result of ``let``
- expressions). For example:
-
- .. code-block:: none
-
- let fn functionDecl()
- match fn.bind("foo")
-
-- It is now possible to write comments in ``clang-query`` code. This
- is primarily useful when using script-mode. Comments are all content
- following the ``#`` character on a line:
-
- .. code-block:: none
-
- # This is a comment
- match fn.bind("foo") # This is a trailing comment
-
-- The new ``set print-matcher true`` command now causes ``clang-query`` to
- print the evaluated matcher together with the resulting bindings.
-
-- A new output mode ``detailed-ast`` was added to ``clang-query``. The
- existing ``dump`` output mode is now a deprecated alias
- for ``detailed-ast``
-
-- Output modes can now be enabled or disabled non-exclusively. For example,
-
- .. code-block:: none
-
- # Enable detailed-ast without disabling other output, such as diag
- enable output detailed-ast
- m functionDecl()
-
- # Disable detailed-ast only
- disable output detailed-ast
- m functionDecl()
+- ...
Improvements to clang-rename
----------------------------
@@ -107,204 +67,105 @@ The improvements are...
Improvements to clang-tidy
--------------------------
-- New :doc:`abseil-duration-comparison
- <clang-tidy/checks/abseil-duration-comparison>` check.
-
- Checks for comparisons which should be done in the ``absl::Duration`` domain
- instead of the float of integer domains.
-
-- New :doc:`abseil-duration-division
- <clang-tidy/checks/abseil-duration-division>` check.
-
- Checks for uses of ``absl::Duration`` division that is done in a
- floating-point context, and recommends the use of a function that
- returns a floating-point value.
-
-- New :doc:`abseil-duration-factory-float
- <clang-tidy/checks/abseil-duration-factory-float>` check.
-
- Checks for cases where the floating-point overloads of various
- ``absl::Duration`` factory functions are called when the more-efficient
- integer versions could be used instead.
-
-- New :doc:`abseil-duration-factory-scale
- <clang-tidy/checks/abseil-duration-factory-scale>` check.
-
- Checks for cases where arguments to ``absl::Duration`` factory functions are
- scaled internally and could be changed to a different factory function.
-
-- New :doc:`abseil-duration-subtraction
- <clang-tidy/checks/abseil-duration-subtraction>` check.
-
- Checks for cases where subtraction should be performed in the
- ``absl::Duration`` domain.
+- New OpenMP module.
-- New :doc:`abseil-faster-strsplit-delimiter
- <clang-tidy/checks/abseil-faster-strsplit-delimiter>` check.
+ For checks specific to `OpenMP <https://www.openmp.org/>`_ API.
- Finds instances of ``absl::StrSplit()`` or ``absl::MaxSplits()`` where the
- delimiter is a single character string literal and replaces with a character.
+- New :doc:`abseil-duration-addition
+ <clang-tidy/checks/abseil-duration-addition>` check.
-- New :doc:`abseil-no-internal-dependencies
- <clang-tidy/checks/abseil-no-internal-dependencies>` check.
+ Checks for cases where addition should be performed in the ``absl::Time``
+ domain.
- Gives a warning if code using Abseil depends on internal details.
+- New :doc:`abseil-duration-conversion-cast
+ <clang-tidy/checks/abseil-duration-conversion-cast>` check.
-- New :doc:`abseil-no-namespace
- <clang-tidy/checks/abseil-no-namespace>` check.
+ Checks for casts of ``absl::Duration`` conversion functions, and recommends
+ the right conversion function instead.
- Ensures code does not open ``namespace absl`` as that violates Abseil's
- compatibility guidelines.
+- New :doc:`abseil-duration-unnecessary-conversion
+ <clang-tidy/checks/abseil-duration-unnecessary-conversion>` check.
-- New :doc:`abseil-redundant-strcat-calls
- <clang-tidy/checks/abseil-redundant-strcat-calls>` check.
+ Finds and fixes cases where ``absl::Duration`` values are being converted to
+ numeric types and back again.
- Suggests removal of unnecessary calls to ``absl::StrCat`` when the result is
- being passed to another ``absl::StrCat`` or ``absl::StrAppend``.
+- New :doc:`abseil-time-comparison
+ <clang-tidy/checks/abseil-time-comparison>` check.
-- New :doc:`abseil-str-cat-append
- <clang-tidy/checks/abseil-str-cat-append>` check.
+ Prefer comparisons in the ``absl::Time`` domain instead of the integer
+ domain.
- Flags uses of ``absl::StrCat()`` to append to a ``std::string``. Suggests
- ``absl::StrAppend()`` should be used instead.
+- New :doc:`abseil-time-subtraction
+ <clang-tidy/checks/abseil-time-subtraction>` check.
-- New :doc:`abseil-upgrade-duration-conversions
- <clang-tidy/checks/abseil-upgrade-duration-conversions>` check.
+ Finds and fixes ``absl::Time`` subtraction expressions to do subtraction
+ in the Time domain instead of the numeric domain.
- Finds calls to ``absl::Duration`` arithmetic operators and factories whose
- argument needs an explicit cast to continue compiling after upcoming API
- changes.
+- New :doc:`google-readability-avoid-underscore-in-googletest-name
+ <clang-tidy/checks/google-readability-avoid-underscore-in-googletest-name>`
+ check.
-- New :doc:`bugprone-too-small-loop-variable
- <clang-tidy/checks/bugprone-too-small-loop-variable>` check.
+ Checks whether there are underscores in googletest test and test case names in
+ test macros, which is prohibited by the Googletest FAQ.
- Detects those ``for`` loops that have a loop variable with a "too small" type
- which means this type can't represent all values which are part of the
- iteration range.
+- New :doc:`objc-super-self <clang-tidy/checks/objc-super-self>` check.
-- New :doc:`cppcoreguidelines-macro-usage
- <clang-tidy/checks/cppcoreguidelines-macro-usage>` check.
+ Finds invocations of ``-self`` on super instances in initializers of
+ subclasses of ``NSObject`` and recommends calling a superclass initializer
+ instead.
- Finds macro usage that is considered problematic because better language
- constructs exist for the task.
+- New alias :doc:`cppcoreguidelines-explicit-virtual-functions
+ <clang-tidy/checks/cppcoreguidelines-explicit-virtual-functions>` to
+ :doc:`modernize-use-override
+ <clang-tidy/checks/modernize-use-override>` was added.
-- New :doc:`google-objc-function-naming
- <clang-tidy/checks/google-objc-function-naming>` check.
+- The :doc:`bugprone-argument-comment
+ <clang-tidy/checks/bugprone-argument-comment>` now supports
+ `CommentBoolLiterals`, `CommentIntegerLiterals`, `CommentFloatLiterals`,
+ `CommentUserDefiniedLiterals`, `CommentStringLiterals`,
+ `CommentCharacterLiterals` & `CommentNullPtrs` options.
- Checks that function names in function declarations comply with the naming
- conventions described in the Google Objective-C Style Guide.
+- The :doc:`bugprone-too-small-loop-variable
+ <clang-tidy/checks/bugprone-too-small-loop-variable>` now supports
+ `MagnitudeBitsUpperLimit` option. The default value was set to 16,
+ which greatly reduces warnings related to loops which are unlikely to
+ cause an actual functional bug.
-- New :doc:`misc-non-private-member-variables-in-classes
- <clang-tidy/checks/misc-non-private-member-variables-in-classes>` check.
+- The :doc:`google-runtime-int <clang-tidy/checks/google-runtime-int>`
+ check has been disabled in Objective-C++.
- Finds classes that not only contain the data (non-static member variables),
- but also have logic (non-static member functions), and diagnoses all member
- variables that have any other scope other than ``private``.
+- The `Acronyms` and `IncludeDefaultAcronyms` options for the
+ :doc:`objc-property-declaration <clang-tidy/checks/objc-property-declaration>`
+ check have been removed.
-- New :doc:`modernize-avoid-c-arrays
- <clang-tidy/checks/modernize-avoid-c-arrays>` check.
+- The :doc:`modernize-use-override
+ <clang-tidy/checks/modernize-use-override>` now supports `OverrideSpelling`
+ and `FinalSpelling` options.
- Finds C-style array types and recommend to use ``std::array<>`` /
- ``std::vector<>``.
+- New :doc:`llvm-prefer-isa-or-dyn-cast-in-conditionals
+ <clang-tidy/checks/llvm-prefer-isa-or-dyn-cast-in-conditionals>` check.
-- New :doc:`modernize-concat-nested-namespaces
- <clang-tidy/checks/modernize-concat-nested-namespaces>` check.
+ Looks at conditionals and finds and replaces cases of ``cast<>``,
+ which will assert rather than return a null pointer, and
+ ``dyn_cast<>`` where the return value is not captured. Additionally,
+ finds and replaces cases that match the pattern ``var &&
+ isa<X>(var)``, where ``var`` is evaluated twice.
- Checks for uses of nested namespaces in the form of
- ``namespace a { namespace b { ... }}`` and offers change to
- syntax introduced in C++17 standard: ``namespace a::b { ... }``.
+- New :doc:`openmp-exception-escape
+ <clang-tidy/checks/openmp-exception-escape>` check.
-- New :doc:`modernize-deprecated-ios-base-aliases
- <clang-tidy/checks/modernize-deprecated-ios-base-aliases>` check.
+ Analyzes OpenMP Structured Blocks and checks that no exception escapes
+ out of the Structured Block it was thrown in.
- Detects usage of the deprecated member types of ``std::ios_base`` and replaces
- those that have a non-deprecated equivalent.
+- New :doc:`openmp-use-default-none
+ <clang-tidy/checks/openmp-use-default-none>` check.
-- New :doc:`modernize-use-nodiscard
- <clang-tidy/checks/modernize-use-nodiscard>` check.
+ Finds OpenMP directives that are allowed to contain a ``default`` clause,
+ but either don't specify it or the clause is specified but with the kind
+ other than ``none``, and suggests to use the ``default(none)`` clause.
- Adds ``[[nodiscard]]`` attributes (introduced in C++17) to member functions
- to highlight at compile time which return values should not be ignored.
-
-- New :doc:`readability-isolate-decl
- <clang-tidy/checks/readability-isolate-declaration>` check.
-
- Detects local variable declarations declaring more than one variable and
- tries to refactor the code to one statement per declaration.
-
-- New :doc:`readability-const-return-type
- <clang-tidy/checks/readability-const-return-type>` check.
-
- Checks for functions with a ``const``-qualified return type and recommends
- removal of the ``const`` keyword.
-
-- New :doc:`readability-magic-numbers
- <clang-tidy/checks/readability-magic-numbers>` check.
-
- Detects usage of magic numbers, numbers that are used as literals instead of
- introduced via constants or symbols.
-
-- New :doc:`readability-redundant-preprocessor
- <clang-tidy/checks/readability-redundant-preprocessor>` check.
-
- Finds potentially redundant preprocessor directives.
-
-- New :doc:`readability-uppercase-literal-suffix
- <clang-tidy/checks/readability-uppercase-literal-suffix>` check.
-
- Detects when the integral literal or floating point literal has non-uppercase
- suffix, and suggests to make the suffix uppercase. The list of destination
- suffixes can be optionally provided.
-
-- New alias :doc:`cert-dcl16-c
- <clang-tidy/checks/cert-dcl16-c>` to :doc:`readability-uppercase-literal-suffix
- <clang-tidy/checks/readability-uppercase-literal-suffix>`
- added.
-
-- New alias :doc:`cppcoreguidelines-avoid-c-arrays
- <clang-tidy/checks/cppcoreguidelines-avoid-c-arrays>`
- to :doc:`modernize-avoid-c-arrays
- <clang-tidy/checks/modernize-avoid-c-arrays>` added.
-
-- New alias :doc:`cppcoreguidelines-non-private-member-variables-in-classes
- <clang-tidy/checks/cppcoreguidelines-non-private-member-variables-in-classes>`
- to :doc:`misc-non-private-member-variables-in-classes
- <clang-tidy/checks/misc-non-private-member-variables-in-classes>`
- added.
-
-- New alias :doc:`hicpp-avoid-c-arrays
- <clang-tidy/checks/hicpp-avoid-c-arrays>`
- to :doc:`modernize-avoid-c-arrays
- <clang-tidy/checks/modernize-avoid-c-arrays>` added.
-
-- New alias :doc:`hicpp-uppercase-literal-suffix
- <clang-tidy/checks/hicpp-uppercase-literal-suffix>` to
- :doc:`readability-uppercase-literal-suffix
- <clang-tidy/checks/readability-uppercase-literal-suffix>`
- added.
-
-- The :doc:`cppcoreguidelines-narrowing-conversions
- <clang-tidy/checks/cppcoreguidelines-narrowing-conversions>` check now
- detects more narrowing conversions:
- - integer to narrower signed integer (this is compiler implementation defined),
- - integer - floating point narrowing conversions,
- - floating point - integer narrowing conversions,
- - constants with narrowing conversions (even in ternary operator).
-
-- The :doc:`objc-property-declaration
- <clang-tidy/checks/objc-property-declaration>` check now ignores the
- `Acronyms` and `IncludeDefaultAcronyms` options.
-
-- The :doc:`readability-redundant-smartptr-get
- <clang-tidy/checks/readability-redundant-smartptr-get>` check does not warn
- about calls inside macros anymore by default.
-
-- The :doc:`readability-uppercase-literal-suffix
- <clang-tidy/checks/readability-uppercase-literal-suffix>` check does not warn
- about literal suffixes inside macros anymore by default.
-
-Improvements to include-fixer
------------------------------
+Improvements to clang-include-fixer
+-----------------------------------
The improvements are...
@@ -312,3 +173,9 @@ Improvements to modularize
--------------------------
The improvements are...
+
+Improvements to pp-trace
+------------------------
+
+- Added a new option `-callbacks` to filter preprocessor callbacks. It replaces
+ the `-ignore` option.
diff --git a/docs/_static/clang-tools-extra-styles.css b/docs/_static/clang-tools-extra-styles.css
new file mode 100644
index 00000000..1a6cd710
--- /dev/null
+++ b/docs/_static/clang-tools-extra-styles.css
@@ -0,0 +1,23 @@
+details {
+ background-color: rgba(50, 150, 220, 0.08);
+ margin-bottom: 0.5em;
+ padding: 0 1em;
+ overflow-y: hidden; /* Suppress margin-collapsing */
+}
+details[open] {
+ border-bottom: 1px solid rgba(0, 0, 128, 0.2);
+ margin-bottom: 1em;
+}
+details summary {
+ font-weight: bold;
+ background-color: rgba(50, 150, 220, 0.1);
+ border-color: rgba(0, 0, 128, 0.2);
+ border-width: 1px;
+ border-style: solid none;
+ padding: 0.2em;
+ margin: 0 -1em;
+}
+details summary:hover {
+ background-color: rgba(50, 150, 220, 0.2);
+ cursor: pointer;
+}
diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html
new file mode 100644
index 00000000..b4f5b4e1
--- /dev/null
+++ b/docs/_templates/layout.html
@@ -0,0 +1,3 @@
+{% extends "!layout.html" %}
+
+{% set css_files = css_files + ['_static/clang-tools-extra-styles.css'] %}
diff --git a/docs/clang-doc.rst b/docs/clang-doc.rst
index f891b71a..96120687 100644
--- a/docs/clang-doc.rst
+++ b/docs/clang-doc.rst
@@ -20,10 +20,10 @@ Use
=====
:program:`clang-doc` is a `LibTooling
-<http://clang.llvm.org/docs/LibTooling.html>`_-based tool, and so requires a
+<https://clang.llvm.org/docs/LibTooling.html>`_-based tool, and so requires a
compile command database for your project (for an example of how to do this
see `How To Setup Tooling For LLVM
-<http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html>`_).
+<https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html>`_).
The tool can be used on a single file or multiple files as defined in
the compile commands database:
diff --git a/docs/include-fixer.rst b/docs/clang-include-fixer.rst
index fcd2998b..783f45ef 100644
--- a/docs/include-fixer.rst
+++ b/docs/clang-include-fixer.rst
@@ -32,7 +32,7 @@ them up if called with a source file from that tree. Note that by default
``compile_commands.json`` as generated by CMake does not include header files,
so only implementation files can be handled by tools.
-.. _How To Setup Tooling For LLVM: http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
+.. _How To Setup Tooling For LLVM: https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
Creating a Symbol Index From a Compilation Database
---------------------------------------------------
@@ -49,7 +49,7 @@ database for LLVM, any project built by CMake should follow similar steps.
$ ninja clang-include-fixer // build clang-include-fixer tool.
$ ls compile_commands.json # Make sure compile_commands.json exists.
compile_commands.json
- $ path/to/llvm/source/tools/clang/tools/extra/include-fixer/find-all-symbols/tool/run-find-all-symbols.py
+ $ path/to/llvm/source/tools/clang/tools/extra/clang-include-fixer/find-all-symbols/tool/run-find-all-symbols.py
... wait as clang indexes the code base ...
$ ln -s $PWD/find_all_symbols_db.yaml path/to/llvm/source/ # Link database into the source tree.
$ ln -s $PWD/compile_commands.json path/to/llvm/source/ # Also link compilation database if it's not there already.
@@ -64,7 +64,7 @@ following key binding to your ``.vimrc``:
.. code-block:: console
- noremap <leader>cf :pyf path/to/llvm/source/tools/clang/tools/extra/include-fixer/tool/clang-include-fixer.py<cr>
+ noremap <leader>cf :pyf path/to/llvm/source/tools/clang/tools/extra/clang-include-fixer/tool/clang-include-fixer.py<cr>
This enables `clang-include-fixer` for NORMAL and VISUAL mode. Change
`<leader>cf` to another binding if you need clang-include-fixer on a different
@@ -118,7 +118,7 @@ in your ``.emacs``:
.. code-block:: console
- (add-to-list 'load-path "path/to/llvm/source/tools/clang/tools/extra/include-fixer/tool/"
+ (add-to-list 'load-path "path/to/llvm/source/tools/clang/tools/extra/clang-include-fixer/tool/"
(require 'clang-include-fixer)
Within Emacs the tool can be invoked with the command
diff --git a/docs/clang-rename.rst b/docs/clang-rename.rst
index f6227795..2796141f 100644
--- a/docs/clang-rename.rst
+++ b/docs/clang-rename.rst
@@ -24,10 +24,10 @@ Using Clang-Rename
==================
:program:`clang-rename` is a `LibTooling
-<http://clang.llvm.org/docs/LibTooling.html>`_-based tool, and it's easier to
+<https://clang.llvm.org/docs/LibTooling.html>`_-based tool, and it's easier to
work with if you set up a compile command database for your project (for an
example of how to do this see `How To Setup Tooling For LLVM
-<http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html>`_). You can also
+<https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html>`_). You can also
specify compilation options on the command line after `--`:
.. code-block:: console
@@ -139,8 +139,8 @@ Vim Integration
You can call :program:`clang-rename` directly from Vim! To set up
:program:`clang-rename` integration for Vim see
-`clang-rename/tool/clang-rename.py
-<http://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/clang-rename/tool/clang-rename.py>`_.
+`clang/tools/clang-rename/clang-rename.py
+<https://github.com/llvm/llvm-project/blob/master/clang/tools/clang-rename/clang-rename.py>`_.
Please note that **you have to save all buffers, in which the replacement will
happen before running the tool**.
@@ -157,7 +157,7 @@ Emacs Integration
You can also use :program:`clang-rename` while using Emacs! To set up
:program:`clang-rename` integration for Emacs see
`clang-rename/tool/clang-rename.el
-<http://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/clang-rename/tool/clang-rename.el>`_.
+<https://github.com/llvm/llvm-project/blob/master/clang/tools/clang-rename/clang-rename.el>`_.
Once installed, you can point your cursor to symbols you want to rename, press
`M-X`, type `clang-rename` and new desired name.
diff --git a/docs/clang-tidy.rst b/docs/clang-tidy.rst
index bcd2bf1e..b9a18069 100644
--- a/docs/clang-tidy.rst
+++ b/docs/clang-tidy.rst
@@ -3,4 +3,4 @@
.. meta::
:http-equiv=refresh: 0;URL='clang-tidy/'
-clang-tidy documentation has moved here: http://clang.llvm.org/extra/clang-tidy/
+clang-tidy documentation has moved here: https://clang.llvm.org/extra/clang-tidy/
diff --git a/docs/clang-tidy/Contributing.rst b/docs/clang-tidy/Contributing.rst
new file mode 100644
index 00000000..09ff1f65
--- /dev/null
+++ b/docs/clang-tidy/Contributing.rst
@@ -0,0 +1,513 @@
+================
+Getting Involved
+================
+
+:program:`clang-tidy` has several own checks and can run Clang static analyzer
+checks, but its power is in the ability to easily write custom checks.
+
+Checks are organized in modules, which can be linked into :program:`clang-tidy`
+with minimal or no code changes in :program:`clang-tidy`.
+
+Checks can plug into the analysis on the preprocessor level using `PPCallbacks`_
+or on the AST level using `AST Matchers`_. When an error is found, checks can
+report them in a way similar to how Clang diagnostics work. A fix-it hint can be
+attached to a diagnostic message.
+
+The interface provided by :program:`clang-tidy` makes it easy to write useful
+and precise checks in just a few lines of code. If you have an idea for a good
+check, the rest of this document explains how to do this.
+
+There are a few tools particularly useful when developing clang-tidy checks:
+ * ``add_new_check.py`` is a script to automate the process of adding a new
+ check, it will create the check, update the CMake file and create a test;
+ * ``rename_check.py`` does what the script name suggests, renames an existing
+ check;
+ * :program:`clang-query` is invaluable for interactive prototyping of AST
+ matchers and exploration of the Clang AST;
+ * `clang-check`_ with the ``-ast-dump`` (and optionally ``-ast-dump-filter``)
+ provides a convenient way to dump AST of a C++ program.
+
+If CMake is configured with ``CLANG_ENABLE_STATIC_ANALYZER``,
+:program:`clang-tidy` will not be built with support for the
+``clang-analyzer-*`` checks or the ``mpi-*`` checks.
+
+
+.. _AST Matchers: https://clang.llvm.org/docs/LibASTMatchers.html
+.. _PPCallbacks: https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html
+.. _clang-check: https://clang.llvm.org/docs/ClangCheck.html
+
+
+Choosing the Right Place for your Check
+---------------------------------------
+
+If you have an idea of a check, you should decide whether it should be
+implemented as a:
+
++ *Clang diagnostic*: if the check is generic enough, targets code patterns that
+ most probably are bugs (rather than style or readability issues), can be
+ implemented effectively and with extremely low false positive rate, it may
+ make a good Clang diagnostic.
+
++ *Clang static analyzer check*: if the check requires some sort of control flow
+ analysis, it should probably be implemented as a static analyzer check.
+
++ *clang-tidy check* is a good choice for linter-style checks, checks that are
+ related to a certain coding style, checks that address code readability, etc.
+
+
+Preparing your Workspace
+------------------------
+
+If you are new to LLVM development, you should read the `Getting Started with
+the LLVM System`_, `Using Clang Tools`_ and `How To Setup Clang Tooling For
+LLVM`_ documents to check out and build LLVM, Clang and Clang Extra Tools with
+CMake.
+
+Once you are done, change to the ``llvm/tools/clang/tools/extra`` directory, and
+let's start!
+
+.. _Getting Started with the LLVM System: https://llvm.org/docs/GettingStarted.html
+.. _Using Clang Tools: https://clang.llvm.org/docs/ClangTools.html
+.. _How To Setup Clang Tooling For LLVM: https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
+
+
+The Directory Structure
+-----------------------
+
+:program:`clang-tidy` source code resides in the
+``llvm/tools/clang/tools/extra`` directory and is structured as follows:
+
+::
+
+ clang-tidy/ # Clang-tidy core.
+ |-- ClangTidy.h # Interfaces for users.
+ |-- ClangTidyCheck.h # Interfaces for checks.
+ |-- ClangTidyModule.h # Interface for clang-tidy modules.
+ |-- ClangTidyModuleRegistry.h # Interface for registering of modules.
+ ...
+ |-- google/ # Google clang-tidy module.
+ |-+
+ |-- GoogleTidyModule.cpp
+ |-- GoogleTidyModule.h
+ ...
+ |-- llvm/ # LLVM clang-tidy module.
+ |-+
+ |-- LLVMTidyModule.cpp
+ |-- LLVMTidyModule.h
+ ...
+ |-- objc/ # Objective-C clang-tidy module.
+ |-+
+ |-- ObjCTidyModule.cpp
+ |-- ObjCTidyModule.h
+ ...
+ |-- tool/ # Sources of the clang-tidy binary.
+ ...
+ test/clang-tidy/ # Integration tests.
+ ...
+ unittests/clang-tidy/ # Unit tests.
+ |-- ClangTidyTest.h
+ |-- GoogleModuleTest.cpp
+ |-- LLVMModuleTest.cpp
+ |-- ObjCModuleTest.cpp
+ ...
+
+
+Writing a clang-tidy Check
+--------------------------
+
+So you have an idea of a useful check for :program:`clang-tidy`.
+
+First, if you're not familiar with LLVM development, read through the `Getting
+Started with LLVM`_ document for instructions on setting up your workflow and
+the `LLVM Coding Standards`_ document to familiarize yourself with the coding
+style used in the project. For code reviews we mostly use `LLVM Phabricator`_.
+
+.. _Getting Started with LLVM: https://llvm.org/docs/GettingStarted.html
+.. _LLVM Coding Standards: https://llvm.org/docs/CodingStandards.html
+.. _LLVM Phabricator: https://llvm.org/docs/Phabricator.html
+
+Next, you need to decide which module the check belongs to. Modules
+are located in subdirectories of `clang-tidy/
+<https://github.com/llvm/llvm-project/tree/master/clang-tools-extra/clang-tidy/>`_
+and contain checks targeting a certain aspect of code quality (performance,
+readability, etc.), certain coding style or standard (Google, LLVM, CERT, etc.)
+or a widely used API (e.g. MPI). Their names are same as user-facing check
+groups names described :ref:`above <checks-groups-table>`.
+
+After choosing the module and the name for the check, run the
+``clang-tidy/add_new_check.py`` script to create the skeleton of the check and
+plug it to :program:`clang-tidy`. It's the recommended way of adding new checks.
+
+If we want to create a `readability-awesome-function-names`, we would run:
+
+.. code-block:: console
+
+ $ clang-tidy/add_new_check.py readability awesome-function-names
+
+
+The ``add_new_check.py`` script will:
+ * create the class for your check inside the specified module's directory and
+ register it in the module and in the build system;
+ * create a lit test file in the ``test/clang-tidy/`` directory;
+ * create a documentation file and include it into the
+ ``docs/clang-tidy/checks/list.rst``.
+
+Let's see in more detail at the check class definition:
+
+.. code-block:: c++
+
+ ...
+
+ #include "../ClangTidyCheck.h"
+
+ namespace clang {
+ namespace tidy {
+ namespace readability {
+
+ ...
+ class AwesomeFunctionNamesCheck : public ClangTidyCheck {
+ public:
+ AwesomeFunctionNamesCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ };
+
+ } // namespace readability
+ } // namespace tidy
+ } // namespace clang
+
+ ...
+
+Constructor of the check receives the ``Name`` and ``Context`` parameters, and
+must forward them to the ``ClangTidyCheck`` constructor.
+
+In our case the check needs to operate on the AST level and it overrides the
+``registerMatchers`` and ``check`` methods. If we wanted to analyze code on the
+preprocessor level, we'd need instead to override the ``registerPPCallbacks``
+method.
+
+In the ``registerMatchers`` method we create an AST Matcher (see `AST Matchers`_
+for more information) that will find the pattern in the AST that we want to
+inspect. The results of the matching are passed to the ``check`` method, which
+can further inspect them and report diagnostics.
+
+.. code-block:: c++
+
+ using namespace ast_matchers;
+
+ void AwesomeFunctionNamesCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(functionDecl().bind("x"), this);
+ }
+
+ void AwesomeFunctionNamesCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>("x");
+ if (MatchedDecl->getName().startswith("awesome_"))
+ return;
+ diag(MatchedDecl->getLocation(), "function %0 is insufficiently awesome")
+ << MatchedDecl
+ << FixItHint::CreateInsertion(MatchedDecl->getLocation(), "awesome_");
+ }
+
+(If you want to see an example of a useful check, look at
+`clang-tidy/google/ExplicitConstructorCheck.h
+<https://github.com/llvm/llvm-project/blob/master/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h>`_
+and `clang-tidy/google/ExplicitConstructorCheck.cpp
+<https://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/clang-tidy/google/ExplicitConstructorCheck.cpp>`_).
+
+
+Registering your Check
+----------------------
+
+(The ``add_new_check.py`` takes care of registering the check in an existing
+module. If you want to create a new module or know the details, read on.)
+
+The check should be registered in the corresponding module with a distinct name:
+
+.. code-block:: c++
+
+ class MyModule : public ClangTidyModule {
+ public:
+ void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+ CheckFactories.registerCheck<ExplicitConstructorCheck>(
+ "my-explicit-constructor");
+ }
+ };
+
+Now we need to register the module in the ``ClangTidyModuleRegistry`` using a
+statically initialized variable:
+
+.. code-block:: c++
+
+ static ClangTidyModuleRegistry::Add<MyModule> X("my-module",
+ "Adds my lint checks.");
+
+
+When using LLVM build system, we need to use the following hack to ensure the
+module is linked into the :program:`clang-tidy` binary:
+
+Add this near the ``ClangTidyModuleRegistry::Add<MyModule>`` variable:
+
+.. code-block:: c++
+
+ // This anchor is used to force the linker to link in the generated object file
+ // and thus register the MyModule.
+ volatile int MyModuleAnchorSource = 0;
+
+And this to the main translation unit of the :program:`clang-tidy` binary (or
+the binary you link the ``clang-tidy`` library in)
+``clang-tidy/tool/ClangTidyMain.cpp``:
+
+.. code-block:: c++
+
+ // This anchor is used to force the linker to link the MyModule.
+ extern volatile int MyModuleAnchorSource;
+ static int MyModuleAnchorDestination = MyModuleAnchorSource;
+
+
+Configuring Checks
+------------------
+
+If a check needs configuration options, it can access check-specific options
+using the ``Options.get<Type>("SomeOption", DefaultValue)`` call in the check
+constructor. In this case the check should also override the
+``ClangTidyCheck::storeOptions`` method to make the options provided by the
+check discoverable. This method lets :program:`clang-tidy` know which options
+the check implements and what the current values are (e.g. for the
+``-dump-config`` command line option).
+
+.. code-block:: c++
+
+ class MyCheck : public ClangTidyCheck {
+ const unsigned SomeOption1;
+ const std::string SomeOption2;
+
+ public:
+ MyCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ SomeOption(Options.get("SomeOption1", -1U)),
+ SomeOption(Options.get("SomeOption2", "some default")) {}
+
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override {
+ Options.store(Opts, "SomeOption1", SomeOption1);
+ Options.store(Opts, "SomeOption2", SomeOption2);
+ }
+ ...
+
+Assuming the check is registered with the name "my-check", the option can then
+be set in a ``.clang-tidy`` file in the following way:
+
+.. code-block:: yaml
+
+ CheckOptions:
+ - key: my-check.SomeOption1
+ value: 123
+ - key: my-check.SomeOption2
+ value: 'some other value'
+
+If you need to specify check options on a command line, you can use the inline
+YAML format:
+
+.. code-block:: console
+
+ $ clang-tidy -config="{CheckOptions: [{key: a, value: b}, {key: x, value: y}]}" ...
+
+
+Testing Checks
+--------------
+
+To run tests for :program:`clang-tidy` use the command:
+
+.. code-block:: console
+
+ $ ninja check-clang-tools
+
+:program:`clang-tidy` checks can be tested using either unit tests or
+`lit`_ tests. Unit tests may be more convenient to test complex replacements
+with strict checks. `Lit`_ tests allow using partial text matching and regular
+expressions which makes them more suitable for writing compact tests for
+diagnostic messages.
+
+The ``check_clang_tidy.py`` script provides an easy way to test both
+diagnostic messages and fix-its. It filters out ``CHECK`` lines from the test
+file, runs :program:`clang-tidy` and verifies messages and fixes with two
+separate `FileCheck`_ invocations: once with FileCheck's directive
+prefix set to ``CHECK-MESSAGES``, validating the diagnostic messages,
+and once with the directive prefix set to ``CHECK-FIXES``, running
+against the fixed code (i.e., the code after generated fix-its are
+applied). In particular, ``CHECK-FIXES:`` can be used to check
+that code was not modified by fix-its, by checking that it is present
+unchanged in the fixed code. The full set of `FileCheck`_ directives
+is available (e.g., ``CHECK-MESSAGES-SAME:``, ``CHECK-MESSAGES-NOT:``), though
+typically the basic ``CHECK`` forms (``CHECK-MESSAGES`` and ``CHECK-FIXES``)
+are sufficient for clang-tidy tests. Note that the `FileCheck`_
+documentation mostly assumes the default prefix (``CHECK``), and hence
+describes the directive as ``CHECK:``, ``CHECK-SAME:``, ``CHECK-NOT:``, etc.
+Replace ``CHECK`` by either ``CHECK-FIXES`` or ``CHECK-MESSAGES`` for
+clang-tidy tests.
+
+An additional check enabled by ``check_clang_tidy.py`` ensures that
+if `CHECK-MESSAGES:` is used in a file then every warning or error
+must have an associated CHECK in that file. Or, you can use ``CHECK-NOTES:``
+instead, if you want to **also** ensure that all the notes are checked.
+
+To use the ``check_clang_tidy.py`` script, put a .cpp file with the
+appropriate ``RUN`` line in the ``test/clang-tidy`` directory. Use
+``CHECK-MESSAGES:`` and ``CHECK-FIXES:`` lines to write checks against
+diagnostic messages and fixed code.
+
+It's advised to make the checks as specific as possible to avoid checks matching
+to incorrect parts of the input. Use ``[[@LINE+X]]``/``[[@LINE-X]]``
+substitutions and distinct function and variable names in the test code.
+
+Here's an example of a test using the ``check_clang_tidy.py`` script (the full
+source code is at `test/clang-tidy/google-readability-casting.cpp`_):
+
+.. code-block:: c++
+
+ // RUN: %check_clang_tidy %s google-readability-casting %t
+
+ void f(int a) {
+ int b = (int)a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant cast to the same type [google-readability-casting]
+ // CHECK-FIXES: int b = a;
+ }
+
+To check more than one scenario in the same test file use
+``-check-suffix=SUFFIX-NAME`` on ``check_clang_tidy.py`` command line or
+``-check-suffixes=SUFFIX-NAME-1,SUFFIX-NAME-2,...``.
+With ``-check-suffix[es]=SUFFIX-NAME`` you need to replace your ``CHECK-*``
+directives with ``CHECK-MESSAGES-SUFFIX-NAME`` and ``CHECK-FIXES-SUFFIX-NAME``.
+
+Here's an example:
+
+.. code-block:: c++
+
+ // RUN: %check_clang_tidy -check-suffix=USING-A %s misc-unused-using-decls %t -- -- -DUSING_A
+ // RUN: %check_clang_tidy -check-suffix=USING-B %s misc-unused-using-decls %t -- -- -DUSING_B
+ // RUN: %check_clang_tidy %s misc-unused-using-decls %t
+ ...
+ // CHECK-MESSAGES-USING-A: :[[@LINE-8]]:10: warning: using decl 'A' {{.*}}
+ // CHECK-MESSAGES-USING-B: :[[@LINE-7]]:10: warning: using decl 'B' {{.*}}
+ // CHECK-MESSAGES: :[[@LINE-6]]:10: warning: using decl 'C' {{.*}}
+ // CHECK-FIXES-USING-A-NOT: using a::A;$
+ // CHECK-FIXES-USING-B-NOT: using a::B;$
+ // CHECK-FIXES-NOT: using a::C;$
+
+
+There are many dark corners in the C++ language, and it may be difficult to make
+your check work perfectly in all cases, especially if it issues fix-it hints. The
+most frequent pitfalls are macros and templates:
+
+1. code written in a macro body/template definition may have a different meaning
+ depending on the macro expansion/template instantiation;
+2. multiple macro expansions/template instantiations may result in the same code
+ being inspected by the check multiple times (possibly, with different
+ meanings, see 1), and the same warning (or a slightly different one) may be
+ issued by the check multiple times; :program:`clang-tidy` will deduplicate
+ _identical_ warnings, but if the warnings are slightly different, all of them
+ will be shown to the user (and used for applying fixes, if any);
+3. making replacements to a macro body/template definition may be fine for some
+ macro expansions/template instantiations, but easily break some other
+ expansions/instantiations.
+
+.. _lit: https://llvm.org/docs/CommandGuide/lit.html
+.. _FileCheck: https://llvm.org/docs/CommandGuide/FileCheck.html
+.. _test/clang-tidy/google-readability-casting.cpp: https://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/test/clang-tidy/google-readability-casting.cpp
+
+
+Running clang-tidy on LLVM
+--------------------------
+
+To test a check it's best to try it out on a larger code base. LLVM and Clang
+are the natural targets as you already have the source code around. The most
+convenient way to run :program:`clang-tidy` is with a compile command database;
+CMake can automatically generate one, for a description of how to enable it see
+`How To Setup Clang Tooling For LLVM`_. Once ``compile_commands.json`` is in
+place and a working version of :program:`clang-tidy` is in ``PATH`` the entire
+code base can be analyzed with ``clang-tidy/tool/run-clang-tidy.py``. The script
+executes :program:`clang-tidy` with the default set of checks on every
+translation unit in the compile command database and displays the resulting
+warnings and errors. The script provides multiple configuration flags.
+
+.. _How To Setup Clang Tooling For LLVM: https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
+
+
+* The default set of checks can be overridden using the ``-checks`` argument,
+ taking the identical format as :program:`clang-tidy` does. For example
+ ``-checks=-*,modernize-use-override`` will run the ``modernize-use-override``
+ check only.
+
+* To restrict the files examined you can provide one or more regex arguments
+ that the file names are matched against.
+ ``run-clang-tidy.py clang-tidy/.*Check\.cpp`` will only analyze clang-tidy
+ checks. It may also be necessary to restrict the header files warnings are
+ displayed from using the ``-header-filter`` flag. It has the same behavior
+ as the corresponding :program:`clang-tidy` flag.
+
+* To apply suggested fixes ``-fix`` can be passed as an argument. This gathers
+ all changes in a temporary directory and applies them. Passing ``-format``
+ will run clang-format over changed lines.
+
+
+On checks profiling
+-------------------
+
+:program:`clang-tidy` can collect per-check profiling info, and output it
+for each processed source file (translation unit).
+
+To enable profiling info collection, use the ``-enable-check-profile`` argument.
+The timings will be output to ``stderr`` as a table. Example output:
+
+.. code-block:: console
+
+ $ clang-tidy -enable-check-profile -checks=-*,readability-function-size source.cpp
+ ===-------------------------------------------------------------------------===
+ clang-tidy checks profiling
+ ===-------------------------------------------------------------------------===
+ Total Execution Time: 1.0282 seconds (1.0258 wall clock)
+
+ ---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Name ---
+ 0.9136 (100.0%) 0.1146 (100.0%) 1.0282 (100.0%) 1.0258 (100.0%) readability-function-size
+ 0.9136 (100.0%) 0.1146 (100.0%) 1.0282 (100.0%) 1.0258 (100.0%) Total
+
+It can also store that data as JSON files for further processing. Example output:
+
+.. code-block:: console
+
+ $ clang-tidy -enable-check-profile -store-check-profile=. -checks=-*,readability-function-size source.cpp
+ $ # Note that there won't be timings table printed to the console.
+ $ ls /tmp/out/
+ 20180516161318717446360-source.cpp.json
+ $ cat 20180516161318717446360-source.cpp.json
+ {
+ "file": "/path/to/source.cpp",
+ "timestamp": "2018-05-16 16:13:18.717446360",
+ "profile": {
+ "time.clang-tidy.readability-function-size.wall": 1.0421266555786133e+00,
+ "time.clang-tidy.readability-function-size.user": 9.2088400000005421e-01,
+ "time.clang-tidy.readability-function-size.sys": 1.2418899999999974e-01
+ }
+ }
+
+There is only one argument that controls profile storage:
+
+* ``-store-check-profile=<prefix>``
+
+ By default reports are printed in tabulated format to stderr. When this option
+ is passed, these per-TU profiles are instead stored as JSON.
+ If the prefix is not an absolute path, it is considered to be relative to the
+ directory from where you have run :program:`clang-tidy`. All ``.`` and ``..``
+ patterns in the path are collapsed, and symlinks are resolved.
+
+ Example:
+ Let's suppose you have a source file named ``example.cpp``, located in the
+ ``/source`` directory. Only the input filename is used, not the full path
+ to the source file. Additionally, it is prefixed with the current timestamp.
+
+ * If you specify ``-store-check-profile=/tmp``, then the profile will be saved
+ to ``/tmp/<ISO8601-like timestamp>-example.cpp.json``
+
+ * If you run :program:`clang-tidy` from within ``/foo`` directory, and specify
+ ``-store-check-profile=.``, then the profile will still be saved to
+ ``/foo/<ISO8601-like timestamp>-example.cpp.json``
diff --git a/docs/clang-tidy/Integrations.rst b/docs/clang-tidy/Integrations.rst
new file mode 100644
index 00000000..ba08bf7f
--- /dev/null
+++ b/docs/clang-tidy/Integrations.rst
@@ -0,0 +1,117 @@
+==================================
+Clang-tidy IDE/Editor Integrations
+==================================
+
+.. _Clangd: https://clang.llvm.org/extra/clangd.html
+
+Apart from being a standalone tool, :program:`clang-tidy` is integrated into
+various IDEs, code analyzers, and editors. Besides, it is currently being
+integrated into Clangd_. The following table shows the most
+well-known :program:`clang-tidy` integrations in detail.
+
++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+
+| | Feature |
++======================================+========================+=================================+==========================+=========================================+==========================+
+| **Tool** | On-the-fly inspection | Check list configuration (GUI) | Options to checks (GUI) | Configuration via ``.clang-tidy`` files | Custom clang-tidy binary |
++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+
+|A.L.E. for Vim | \+\ | \-\ | \-\ | \-\ | \+\ |
++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+
+|Clang Power Tools for Visual Studio | \-\ | \+\ | \-\ | \+\ | \-\ |
++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+
+|Clangd | \+\ | \-\ | \-\ | \-\ | \-\ |
++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+
+|CLion IDE | \+\ | \+\ | \+\ | \+\ | \+\ |
++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+
+|CodeChecker | \-\ | \-\ | \-\ | \-\ | \+\ |
++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+
+|CPPCheck | \-\ | \-\ | \-\ | \-\ | \-\ |
++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+
+|CPPDepend | \-\ | \-\ | \-\ | \-\ | \-\ |
++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+
+|Flycheck for Emacs | \+\ | \-\ | \-\ | \+\ | \+\ |
++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+
+|KDevelop IDE | \-\ | \+\ | \+\ | \+\ | \+\ |
++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+
+|Qt Creator IDE | \+\ | \+\ | \-\ | \-\ | \+\ |
++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+
+|ReSharper C++ for Visual Studio | \+\ | \+\ | \-\ | \+\ | \-\ |
++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+
+|Syntastic for Vim | \+\ | \-\ | \-\ | \-\ | \+\ |
++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+
+|Visual Assist for Visual Studio | \+\ | \+\ | \-\ | \-\ | \-\ |
++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+
+
+**IDEs**
+
+.. _CLion: https://www.jetbrains.com/clion/
+.. _integrates clang-tidy: https://www.jetbrains.com/help/clion/clang-tidy-checks-support.html
+
+CLion_ 2017.2 and later `integrates clang-tidy`_ as an extension to the
+built-in code analyzer. Starting from 2018.2 EAP, CLion allows using
+:program:`clang-tidy` via Clangd. Inspections and applicable quick-fixes are
+performed on the fly, and checks can be configured in standard command line
+format. In this integration, you can switch to the :program:`clang-tidy`
+binary different from the bundled one, pass the configuration in
+``.clang-tidy`` files instead of using the IDE settings, and configure
+options for particular checks.
+
+.. _KDevelop: https://www.kdevelop.org/
+.. _kdev-clang-tidy: https://github.com/KDE/kdev-clang-tidy/
+
+KDevelop_ with the kdev-clang-tidy_ plugin, starting from version 5.1, performs
+static analysis using :program:`clang-tidy`. The plugin launches the
+:program:`clang-tidy` binary from the specified location and parses its
+output to provide a list of issues.
+
+.. _QtCreator: https://www.qt.io/
+.. _Clang Code Model: https://doc.qt.io/qtcreator/creator-clang-codemodel.html
+
+QtCreator_ 4.6 integrates :program:`clang-tidy` warnings into the editor
+diagnostics under the `Clang Code Model`_. To employ :program:`clang-tidy`
+inspection in QtCreator, you need to create a copy of one of the presets and
+choose the checks to be performed in the Clang Code Model Warnings menu.
+
+.. _MS Visual Studio: https://visualstudio.microsoft.com/
+.. _ReSharper C++: https://www.jetbrains.com/help/resharper/Clang_Tidy_Integration.html
+.. _Visual Assist: https://docs.wholetomato.com/default.asp?W761
+.. _Clang Power Tools: https://marketplace.visualstudio.com/items?itemName=caphyon.ClangPowerTools
+.. _clang-tidy-vs: https://github.com/llvm/llvm-project/tree/master/clang-tools-extra/clang-tidy-vs
+
+`MS Visual Studio`_ has a native clang-tidy-vs_ plugin and also can integrate
+:program:`clang-tidy` by means of three other tools. The `ReSharper C++`_
+extension, version 2017.3 and later, provides seamless :program:`clang-tidy`
+integration: checks and quick-fixes run alongside native inspections. Apart
+from that, ReSharper C++ incorporates :program:`clang-tidy` as a separate
+step of its code clean-up process. `Visual Assist`_ build 2210 includes a
+subset of :program:`clang-tidy` checklist to inspect the code as you edit.
+Another way to bring :program:`clang-tidy` functionality to Visual Studio is
+the `Clang Power Tools`_ plugin, which includes most of the
+:program:`clang-tidy` checks and runs them during compilation or as a separate
+step of code analysis.
+
+**Editors**
+
+.. _Flycheck: https://github.com/ch1bo/flycheck-clang-tidy
+.. _Syntastic: https://github.com/vim-syntastic/syntastic
+.. _A.L.E.: https://github.com/w0rp/ale
+.. _Emacs24: https://www.gnu.org/s/emacs/
+.. _Vim: https://www.vim.org/
+
+Emacs24_, when expanded with the Flycheck_ plugin, incorporates the
+:program:`clang-tidy` inspection into the syntax analyzer. For Vim_, you can
+use Syntastic_, which includes :program:`clang-tidy`, or `A.L.E.`_,
+a lint engine that applies :program:`clang-tidy` along with other linters.
+
+**Analyzers**
+
+.. _CPPDepend: https://www.cppdepend.com/cppdependv2018
+.. _CPPCheck: https://sourceforge.net/p/cppcheck/news/
+.. _CodeChecker: https://github.com/Ericsson/codechecker
+.. _plugin: https://github.com/Ericsson/CodeCheckerEclipsePlugin
+
+:program:`clang-tidy` is integrated in CPPDepend_ starting from version 2018.1
+and CPPCheck_ 1.82. CPPCheck integration lets you import Visual Studio
+solutions and run the :program:`clang-tidy` inspection on them. The
+CodeChecker_ application of version 5.3 or later, which also comes as a plugin_
+for Eclipse, supports :program:`clang-tidy` as a static analysis instrument and
+allows to use a custom :program:`clang-tidy` binary.
diff --git a/docs/clang-tidy/checks/abseil-duration-addition.rst b/docs/clang-tidy/checks/abseil-duration-addition.rst
new file mode 100644
index 00000000..2f3d805e
--- /dev/null
+++ b/docs/clang-tidy/checks/abseil-duration-addition.rst
@@ -0,0 +1,21 @@
+.. title:: clang-tidy - abseil-duration-addition
+
+abseil-duration-addition
+========================
+
+Check for cases where addition should be performed in the ``absl::Time`` domain.
+When adding two values, and one is known to be an ``absl::Time``, we can infer
+that the other should be interpreted as an ``absl::Duration`` of a similar
+scale, and make that inference explicit.
+
+Examples:
+
+.. code-block:: c++
+
+ // Original - Addition in the integer domain
+ int x;
+ absl::Time t;
+ int result = absl::ToUnixSeconds(t) + x;
+
+ // Suggestion - Addition in the absl::Time domain
+ int result = absl::TounixSeconds(t + absl::Seconds(x));
diff --git a/docs/clang-tidy/checks/abseil-duration-conversion-cast.rst b/docs/clang-tidy/checks/abseil-duration-conversion-cast.rst
new file mode 100644
index 00000000..3c1a152b
--- /dev/null
+++ b/docs/clang-tidy/checks/abseil-duration-conversion-cast.rst
@@ -0,0 +1,31 @@
+.. title:: clang-tidy - abseil-duration-conversion-cast
+
+abseil-duration-conversion-cast
+===============================
+
+Checks for casts of ``absl::Duration`` conversion functions, and recommends
+the right conversion function instead.
+
+Examples:
+
+.. code-block:: c++
+
+ // Original - Cast from a double to an integer
+ absl::Duration d;
+ int i = static_cast<int>(absl::ToDoubleSeconds(d));
+
+ // Suggested - Use the integer conversion function directly.
+ int i = absl::ToInt64Seconds(d);
+
+
+ // Original - Cast from a double to an integer
+ absl::Duration d;
+ double x = static_cast<double>(absl::ToInt64Seconds(d));
+
+ // Suggested - Use the integer conversion function directly.
+ double x = absl::ToDoubleSeconds(d);
+
+
+Note: In the second example, the suggested fix could yield a different result,
+as the conversion to integer could truncate. In practice, this is very rare,
+and you should use ``absl::Trunc`` to perform this operation explicitly instead.
diff --git a/docs/clang-tidy/checks/abseil-duration-subtraction.rst b/docs/clang-tidy/checks/abseil-duration-subtraction.rst
index 884eeb2c..b570931b 100644
--- a/docs/clang-tidy/checks/abseil-duration-subtraction.rst
+++ b/docs/clang-tidy/checks/abseil-duration-subtraction.rst
@@ -21,7 +21,6 @@ Examples:
// Suggestion - Subtraction in the absl::Duration domain instead
double result = absl::ToDoubleSeconds(d - absl::Seconds(x));
-
// Original - Subtraction of two Durations in the double domain
absl::Duration d1, d2;
double result = absl::ToDoubleSeconds(d1) - absl::ToDoubleSeconds(d2);
@@ -29,6 +28,7 @@ Examples:
// Suggestion - Subtraction in the absl::Duration domain instead
double result = absl::ToDoubleSeconds(d1 - d2);
+
Note: As with other ``clang-tidy`` checks, it is possible that multiple fixes
may overlap (as in the case of nested expressions), so not all occurences can
be transformed in one run. In particular, this may occur for nested subtraction
diff --git a/docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst b/docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
new file mode 100644
index 00000000..2f978f4d
--- /dev/null
+++ b/docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
@@ -0,0 +1,46 @@
+.. title:: clang-tidy - abseil-duration-unnecessary-conversion
+
+abseil-duration-unnecessary-conversion
+======================================
+
+Finds and fixes cases where ``absl::Duration`` values are being converted to
+numeric types and back again.
+
+Floating-point examples:
+
+.. code-block:: c++
+
+ // Original - Conversion to double and back again
+ absl::Duration d1;
+ absl::Duration d2 = absl::Seconds(absl::ToDoubleSeconds(d1));
+
+ // Suggestion - Remove unnecessary conversions
+ absl::Duration d2 = d1;
+
+ // Original - Division to convert to double and back again
+ absl::Duration d2 = absl::Seconds(absl::FDivDuration(d1, absl::Seconds(1)));
+
+ // Suggestion - Remove division and conversion
+ absl::Duration d2 = d1;
+
+Integer examples:
+
+.. code-block:: c++
+
+ // Original - Conversion to integer and back again
+ absl::Duration d1;
+ absl::Duration d2 = absl::Hours(absl::ToInt64Hours(d1));
+
+ // Suggestion - Remove unnecessary conversions
+ absl::Duration d2 = d1;
+
+ // Original - Integer division followed by conversion
+ absl::Duration d2 = absl::Seconds(d1 / absl::Seconds(1));
+
+ // Suggestion - Remove division and conversion
+ absl::Duration d2 = d1;
+
+Note: Converting to an integer and back to an ``absl::Duration`` might be a
+truncating operation if the value is not aligned to the scale of conversion.
+In the rare case where this is the intended result, callers should use
+``absl::Trunc`` to truncate explicitly.
diff --git a/docs/clang-tidy/checks/abseil-time-comparison.rst b/docs/clang-tidy/checks/abseil-time-comparison.rst
new file mode 100644
index 00000000..9342e4cf
--- /dev/null
+++ b/docs/clang-tidy/checks/abseil-time-comparison.rst
@@ -0,0 +1,23 @@
+.. title:: clang-tidy - abseil-time-comparison
+
+abseil-time-comparison
+======================
+
+Prefer comparisons in the ``absl::Time`` domain instead of the integer domain.
+
+N.B.: In cases where an ``absl::Time`` is being converted to an integer,
+alignment may occur. If the comparison depends on this alignment, doing the
+comparison in the ``absl::Time`` domain may yield a different result. In
+practice this is very rare, and still indicates a bug which should be fixed.
+
+Examples:
+
+.. code-block:: c++
+
+ // Original - Comparison in the integer domain
+ int x;
+ absl::Time t;
+ if (x < absl::ToUnixSeconds(t)) ...
+
+ // Suggested - Compare in the absl::Time domain instead
+ if (absl::FromUnixSeconds(x) < t) ...
diff --git a/docs/clang-tidy/checks/abseil-time-subtraction.rst b/docs/clang-tidy/checks/abseil-time-subtraction.rst
new file mode 100644
index 00000000..196c0736
--- /dev/null
+++ b/docs/clang-tidy/checks/abseil-time-subtraction.rst
@@ -0,0 +1,39 @@
+.. title:: clang-tidy - abseil-time-subtraction
+
+abseil-time-subtraction
+=======================
+
+Finds and fixes ``absl::Time`` subtraction expressions to do subtraction
+in the Time domain instead of the numeric domain.
+
+There are two cases of Time subtraction in which deduce additional type
+information:
+
+- When the result is an ``absl::Duration`` and the first argument is an
+ ``absl::Time``.
+- When the second argument is a ``absl::Time``.
+
+In the first case, we must know the result of the operation, since without that
+the second operand could be either an ``absl::Time`` or an ``absl::Duration``.
+In the second case, the first operand *must* be an ``absl::Time``, because
+subtracting an ``absl::Time`` from an ``absl::Duration`` is not defined.
+
+Examples:
+
+.. code-block:: c++
+
+ int x;
+ absl::Time t;
+
+ // Original - absl::Duration result and first operand is a absl::Time.
+ absl::Duration d = absl::Seconds(absl::ToUnixSeconds(t) - x);
+
+ // Suggestion - Perform subtraction in the Time domain instead.
+ absl::Duration d = t - absl::FromUnixSeconds(x);
+
+
+ // Original - Second operand is an absl::Time.
+ int i = x - absl::ToUnixSeconds(t);
+
+ // Suggestion - Perform subtraction in the Time domain instead.
+ int i = absl::ToInt64Seconds(absl::FromUnixSeconds(x) - t);
diff --git a/docs/clang-tidy/checks/bugprone-argument-comment.rst b/docs/clang-tidy/checks/bugprone-argument-comment.rst
index 5f7e5f0d..afc12186 100644
--- a/docs/clang-tidy/checks/bugprone-argument-comment.rst
+++ b/docs/clang-tidy/checks/bugprone-argument-comment.rst
@@ -27,3 +27,158 @@ Options
When zero (default value), the check will ignore leading and trailing
underscores and case when comparing names -- otherwise they are taken into
account.
+
+.. option:: CommentBoolLiterals
+
+ When true, the check will add argument comments in the format
+ ``/*ParameterName=*/`` right before the boolean literal argument.
+
+Before:
+
+.. code-block:: c++
+
+ void foo(bool TurnKey, bool PressButton);
+
+ foo(true, false);
+
+After:
+
+.. code-block:: c++
+
+ void foo(bool TurnKey, bool PressButton);
+
+ foo(/*TurnKey=*/true, /*PressButton=*/false);
+
+.. option:: CommentIntegerLiterals
+
+ When true, the check will add argument comments in the format
+ ``/*ParameterName=*/`` right before the integer literal argument.
+
+Before:
+
+.. code-block:: c++
+
+ void foo(int MeaningOfLife);
+
+ foo(42);
+
+After:
+
+.. code-block:: c++
+
+ void foo(int MeaningOfLife);
+
+ foo(/*MeaningOfLife=*/42);
+
+.. option:: CommentFloatLiterals
+
+ When true, the check will add argument comments in the format
+ ``/*ParameterName=*/`` right before the float/double literal argument.
+
+Before:
+
+.. code-block:: c++
+
+ void foo(float Pi);
+
+ foo(3.14159);
+
+After:
+
+.. code-block:: c++
+
+ void foo(float Pi);
+
+ foo(/*Pi=*/3.14159);
+
+.. option:: CommentStringLiterals
+
+ When true, the check will add argument comments in the format
+ ``/*ParameterName=*/`` right before the string literal argument.
+
+Before:
+
+.. code-block:: c++
+
+ void foo(const char *String);
+ void foo(const wchar_t *WideString);
+
+ foo("Hello World");
+ foo(L"Hello World");
+
+After:
+
+.. code-block:: c++
+
+ void foo(const char *String);
+ void foo(const wchar_t *WideString);
+
+ foo(/*String=*/"Hello World");
+ foo(/*WideString=*/L"Hello World");
+
+.. option:: CommentCharacterLiterals
+
+ When true, the check will add argument comments in the format
+ ``/*ParameterName=*/`` right before the character literal argument.
+
+Before:
+
+.. code-block:: c++
+
+ void foo(char *Character);
+
+ foo('A');
+
+After:
+
+.. code-block:: c++
+
+ void foo(char *Character);
+
+ foo(/*Character=*/'A');
+
+.. option:: CommentUserDefinedLiterals
+
+ When true, the check will add argument comments in the format
+ ``/*ParameterName=*/`` right before the user defined literal argument.
+
+Before:
+
+.. code-block:: c++
+
+ void foo(double Distance);
+
+ double operator"" _km(long double);
+
+ foo(402.0_km);
+
+After:
+
+.. code-block:: c++
+
+ void foo(double Distance);
+
+ double operator"" _km(long double);
+
+ foo(/*Distance=*/402.0_km);
+
+.. option:: CommentNullPtrs
+
+ When true, the check will add argument comments in the format
+ ``/*ParameterName=*/`` right before the nullptr literal argument.
+
+Before:
+
+.. code-block:: c++
+
+ void foo(A* Value);
+
+ foo(nullptr);
+
+After:
+
+.. code-block:: c++
+
+ void foo(A* Value);
+
+ foo(/*Value=*/nullptr);
diff --git a/docs/clang-tidy/checks/bugprone-parent-virtual-call.rst b/docs/clang-tidy/checks/bugprone-parent-virtual-call.rst
index e1021b18..c3521272 100755..100644
--- a/docs/clang-tidy/checks/bugprone-parent-virtual-call.rst
+++ b/docs/clang-tidy/checks/bugprone-parent-virtual-call.rst
@@ -8,15 +8,15 @@ to overridden parent's virtual methods.
.. code-block:: c++
- class A {
+ struct A {
int virtual foo() {...}
};
- class B: public A {
+ struct B: public A {
int foo() override {...}
};
- class C: public B {
+ struct C: public B {
int foo() override { A::foo(); }
// ^^^^^^^^
// warning: qualified name A::foo refers to a member overridden in subclass; did you mean 'B'? [bugprone-parent-virtual-call]
diff --git a/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst b/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
index 7688a3a5..702541d8 100644
--- a/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
+++ b/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
@@ -27,3 +27,20 @@ In a real use case size means a container's size which depends on the user input
This algorithm works for small amount of objects, but will lead to freeze for a
a larger user input.
+
+.. option:: MagnitudeBitsUpperLimit
+
+ Upper limit for the magnitude bits of the loop variable. If it's set the check
+ filters out those catches in which the loop variable's type has more magnitude
+ bits as the specified upper limit. The default value is 16.
+ For example, if the user sets this option to 31 (bits), then a 32-bit ``unsigend int``
+ is ignored by the check, however a 32-bit ``int`` is not (A 32-bit ``signed int``
+ has 31 magnitude bits).
+
+.. code-block:: c++
+
+ int main() {
+ long size = 294967296l;
+ for (unsigned i = 0; i < size; ++i) {} // no warning with MagnitudeBitsUpperLimit = 31 on a system where unsigned is 32-bit
+ for (int i = 0; i < size; ++i) {} // warning with MagnitudeBitsUpperLimit = 31 on a system where int is 32-bit
+ }
diff --git a/docs/clang-tidy/checks/cppcoreguidelines-explicit-virtual-functions.rst b/docs/clang-tidy/checks/cppcoreguidelines-explicit-virtual-functions.rst
new file mode 100644
index 00000000..87a8fe2d
--- /dev/null
+++ b/docs/clang-tidy/checks/cppcoreguidelines-explicit-virtual-functions.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cppcoreguidelines-explicit-virtual-functions
+.. meta::
+ :http-equiv=refresh: 5;URL=modernize-use-override.html
+
+cppcoreguidelines-explicit-virtual-functions
+============================================
+
+The cppcoreguidelines-explicit-virtual-functions check is an alias, please see
+`modernize-use-override <modernize-use-override.html>`_
+for more information.
diff --git a/docs/clang-tidy/checks/cppcoreguidelines-owning-memory.rst b/docs/clang-tidy/checks/cppcoreguidelines-owning-memory.rst
index 3f6f8c4b..cd190163 100644
--- a/docs/clang-tidy/checks/cppcoreguidelines-owning-memory.rst
+++ b/docs/clang-tidy/checks/cppcoreguidelines-owning-memory.rst
@@ -50,7 +50,7 @@ to be deleted.
int* NonOwner = new int(42); // First warning here, since new must land in an owner
delete NonOwner; // Second warning here, since only owners are allowed to be deleted
- // Example Good, Ownership correclty stated
+ // Example Good, Ownership correctly stated
gsl::owner<int*> Owner = new int(42); // Good
delete Owner; // Good as well, statically enforced, that only owners get deleted
diff --git a/docs/clang-tidy/checks/google-objc-avoid-throwing-exception.rst b/docs/clang-tidy/checks/google-objc-avoid-throwing-exception.rst
index 39b02174..884e9719 100644
--- a/docs/clang-tidy/checks/google-objc-avoid-throwing-exception.rst
+++ b/docs/clang-tidy/checks/google-objc-avoid-throwing-exception.rst
@@ -36,4 +36,4 @@ Instead, returning an error via ``NSError **`` is preferred:
}
The corresponding style guide rule:
-http://google.github.io/styleguide/objcguide.html#avoid-throwing-exceptions
+https://google.github.io/styleguide/objcguide.html#avoid-throwing-exceptions
diff --git a/docs/clang-tidy/checks/google-objc-global-variable-declaration.rst b/docs/clang-tidy/checks/google-objc-global-variable-declaration.rst
index d4703706..e4b41fbc 100644
--- a/docs/clang-tidy/checks/google-objc-global-variable-declaration.rst
+++ b/docs/clang-tidy/checks/google-objc-global-variable-declaration.rst
@@ -7,7 +7,7 @@ Finds global variable declarations in Objective-C files that do not follow the
pattern of variable names in Google's Objective-C Style Guide.
The corresponding style guide rule:
-http://google.github.io/styleguide/objcguide.html#variable-names
+https://google.github.io/styleguide/objcguide.html#variable-names
All the global variables should follow the pattern of `g[A-Z].*` (variables) or
`k[A-Z].*` (constants). The check will suggest a variable name that follows the
diff --git a/docs/clang-tidy/checks/google-readability-avoid-underscore-in-googletest-name.rst b/docs/clang-tidy/checks/google-readability-avoid-underscore-in-googletest-name.rst
new file mode 100644
index 00000000..75b1a9ab
--- /dev/null
+++ b/docs/clang-tidy/checks/google-readability-avoid-underscore-in-googletest-name.rst
@@ -0,0 +1,34 @@
+.. title:: clang-tidy - google-readability-avoid-underscore-in-googletest-name
+
+google-readability-avoid-underscore-in-googletest-name
+======================================================
+
+Checks whether there are underscores in googletest test and test case names in
+test macros:
+
+- ``TEST``
+- ``TEST_F``
+- ``TEST_P``
+- ``TYPED_TEST``
+- ``TYPED_TEST_P``
+
+The ``FRIEND_TEST`` macro is not included.
+
+For example:
+
+.. code-block:: c++
+
+ TEST(TestCaseName, Illegal_TestName) {}
+ TEST(Illegal_TestCaseName, TestName) {}
+
+would trigger the check. `Underscores are not allowed`_ in test names nor test
+case names.
+
+The ``DISABLED_`` prefix, which may be used to `disable individual tests`_, is
+ignored when checking test names, but the rest of the rest of the test name is
+still checked.
+
+This check does not propose any fixes.
+
+.. _Underscores are not allowed: https://github.com/google/googletest/blob/master/googletest/docs/faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore
+.. _disable individual tests: https://github.com/google/googletest/blob/master/googletest/docs/faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore
diff --git a/docs/clang-tidy/checks/list.rst b/docs/clang-tidy/checks/list.rst
index 080e747b..fc28cf61 100644
--- a/docs/clang-tidy/checks/list.rst
+++ b/docs/clang-tidy/checks/list.rst
@@ -4,17 +4,22 @@ Clang-Tidy Checks
=================
.. toctree::
+ abseil-duration-addition
abseil-duration-comparison
+ abseil-duration-conversion-cast
abseil-duration-division
abseil-duration-factory-float
abseil-duration-factory-scale
abseil-duration-subtraction
+ abseil-duration-unnecessary-conversion
abseil-faster-strsplit-delimiter
abseil-no-internal-dependencies
abseil-no-namespace
abseil-redundant-strcat-calls
abseil-str-cat-append
abseil-string-find-startswith
+ abseil-time-comparison
+ abseil-time-subtraction
abseil-upgrade-duration-conversions
android-cloexec-accept
android-cloexec-accept4
@@ -95,6 +100,7 @@ Clang-Tidy Checks
cppcoreguidelines-avoid-goto
cppcoreguidelines-avoid-magic-numbers (redirects to readability-magic-numbers) <cppcoreguidelines-avoid-magic-numbers>
cppcoreguidelines-c-copy-assignment-signature (redirects to misc-unconventional-assign-operator) <cppcoreguidelines-c-copy-assignment-signature>
+ cppcoreguidelines-explicit-virtual-functions (redirects to modernize-use-override) <cppcoreguidelines-explicit-virtual-functions>
cppcoreguidelines-interfaces-global-init
cppcoreguidelines-macro-usage
cppcoreguidelines-narrowing-conversions
@@ -130,6 +136,7 @@ Clang-Tidy Checks
google-objc-avoid-throwing-exception
google-objc-function-naming
google-objc-global-variable-declaration
+ google-readability-avoid-underscore-in-googletest-name
google-readability-braces-around-statements (redirects to readability-braces-around-statements) <google-readability-braces-around-statements>
google-readability-casting
google-readability-function-size (redirects to readability-function-size) <google-readability-function-size>
@@ -171,6 +178,7 @@ Clang-Tidy Checks
llvm-header-guard
llvm-include-order
llvm-namespace-comment
+ llvm-prefer-isa-or-dyn-cast-in-conditionals
llvm-twine-local
misc-definitions-in-headers
misc-misplaced-const
@@ -220,6 +228,9 @@ Clang-Tidy Checks
objc-avoid-spinlock
objc-forbidden-subclassing
objc-property-declaration
+ objc-super-self
+ openmp-exception-escape
+ openmp-use-default-none
performance-faster-string-find
performance-for-range-copy
performance-implicit-conversion-in-loop
diff --git a/docs/clang-tidy/checks/llvm-include-order.rst b/docs/clang-tidy/checks/llvm-include-order.rst
index dba98376..8a215b8e 100644
--- a/docs/clang-tidy/checks/llvm-include-order.rst
+++ b/docs/clang-tidy/checks/llvm-include-order.rst
@@ -6,4 +6,4 @@ llvm-include-order
Checks the correct order of ``#includes``.
-See http://llvm.org/docs/CodingStandards.html#include-style
+See https://llvm.org/docs/CodingStandards.html#include-style
diff --git a/docs/clang-tidy/checks/llvm-namespace-comment.rst b/docs/clang-tidy/checks/llvm-namespace-comment.rst
index f6bc5985..be90260b 100644
--- a/docs/clang-tidy/checks/llvm-namespace-comment.rst
+++ b/docs/clang-tidy/checks/llvm-namespace-comment.rst
@@ -8,7 +8,7 @@ check.
Checks that long namespaces have a closing comment.
-http://llvm.org/docs/CodingStandards.html#namespace-indentation
+https://llvm.org/docs/CodingStandards.html#namespace-indentation
https://google.github.io/styleguide/cppguide.html#Namespaces
diff --git a/docs/clang-tidy/checks/llvm-prefer-isa-or-dyn-cast-in-conditionals.rst b/docs/clang-tidy/checks/llvm-prefer-isa-or-dyn-cast-in-conditionals.rst
new file mode 100644
index 00000000..70ff0f27
--- /dev/null
+++ b/docs/clang-tidy/checks/llvm-prefer-isa-or-dyn-cast-in-conditionals.rst
@@ -0,0 +1,34 @@
+.. title:: clang-tidy - llvm-prefer-isa-or-dyn-cast-in-conditionals
+
+llvm-prefer-isa-or-dyn-cast-in-conditionals
+===========================================
+
+Looks at conditionals and finds and replaces cases of ``cast<>``,
+which will assert rather than return a null pointer, and
+``dyn_cast<>`` where the return value is not captured. Additionally,
+finds and replaces cases that match the pattern ``var &&
+isa<X>(var)``, where ``var`` is evaluated twice.
+
+.. code-block:: c++
+
+ // Finds these:
+ if (auto x = cast<X>(y)) {}
+ // is replaced by:
+ if (auto x = dyn_cast<X>(y)) {}
+
+ if (cast<X>(y)) {}
+ // is replaced by:
+ if (isa<X>(y)) {}
+
+ if (dyn_cast<X>(y)) {}
+ // is replaced by:
+ if (isa<X>(y)) {}
+
+ if (var && isa<T>(var)) {}
+ // is replaced by:
+ if (isa_and_nonnull<T>(var.foo())) {}
+
+ // Other cases are ignored, e.g.:
+ if (auto f = cast<Z>(y)->foo()) {}
+ if (cast<Z>(y)->foo()) {}
+ if (X.cast(y)) {}
diff --git a/docs/clang-tidy/checks/misc-non-private-member-variables-in-classes.rst b/docs/clang-tidy/checks/misc-non-private-member-variables-in-classes.rst
index db88c9b1..57990622 100644
--- a/docs/clang-tidy/checks/misc-non-private-member-variables-in-classes.rst
+++ b/docs/clang-tidy/checks/misc-non-private-member-variables-in-classes.rst
@@ -6,11 +6,11 @@ misc-non-private-member-variables-in-classes
`cppcoreguidelines-non-private-member-variables-in-classes` redirects here
as an alias for this check.
-Finds classes that contain non-static data members in addition to non-static
-member functions and diagnose all data members declared with a non-``public``
-access specifier. The data members should be declared as ``private`` and
-accessed through member functions instead of exposed to derived classes or
-class consumers.
+Finds classes that contain non-static data members in addition to user-declared
+non-static member functions and diagnose all data members declared with a
+non-``public`` access specifier. The data members should be declared as
+``private`` and accessed through member functions instead of exposed to derived
+classes or class consumers.
Options
-------
diff --git a/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst b/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst
index 1a6d6b3f..91287d86 100644
--- a/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst
+++ b/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst
@@ -3,8 +3,8 @@
misc-throw-by-value-catch-by-reference
======================================
-"cert-err09-cpp" redirects here as an alias for this check.
-"cert-err61-cpp" redirects here as an alias for this check.
+`cert-err09-cpp` redirects here as an alias for this check.
+`cert-err61-cpp` redirects here as an alias for this check.
Finds violations of the rule "Throw by value, catch by reference" presented for
example in "C++ Coding Standards" by H. Sutter and A. Alexandrescu.
diff --git a/docs/clang-tidy/checks/modernize-avoid-c-arrays.rst b/docs/clang-tidy/checks/modernize-avoid-c-arrays.rst
index 8f856a52..d7bc7474 100644
--- a/docs/clang-tidy/checks/modernize-avoid-c-arrays.rst
+++ b/docs/clang-tidy/checks/modernize-avoid-c-arrays.rst
@@ -54,3 +54,7 @@ such headers between C code, and C++ code.
}
}
+
+Similarly, the ``main()`` function is ignored. Its second and third parameters
+can be either ``char* argv[]`` or ``char** argv``, but can not be
+``std::array<>``.
diff --git a/docs/clang-tidy/checks/modernize-pass-by-value.rst b/docs/clang-tidy/checks/modernize-pass-by-value.rst
index f49648d4..e538135a 100644
--- a/docs/clang-tidy/checks/modernize-pass-by-value.rst
+++ b/docs/clang-tidy/checks/modernize-pass-by-value.rst
@@ -144,7 +144,7 @@ Example:
+ C(std::string S) : S(std::move(S)) {}
};
-.. _Clang Compiler User’s Manual - Microsoft extensions: http://clang.llvm.org/docs/UsersManual.html#microsoft-extensions
+.. _Clang Compiler User’s Manual - Microsoft extensions: https://clang.llvm.org/docs/UsersManual.html#microsoft-extensions
.. seealso::
diff --git a/docs/clang-tidy/checks/modernize-use-emplace.rst b/docs/clang-tidy/checks/modernize-use-emplace.rst
index 533125e9..447a110f 100644
--- a/docs/clang-tidy/checks/modernize-use-emplace.rst
+++ b/docs/clang-tidy/checks/modernize-use-emplace.rst
@@ -10,7 +10,7 @@ results in less verbose and potentially more efficient code.
Right now the check doesn't support ``push_front`` and ``insert``.
It also doesn't support ``insert`` functions for associative containers
because replacing ``insert`` with ``emplace`` may result in
-`speed regression <http://htmlpreview.github.io/?https://github.com/HowardHinnant/papers/blob/master/insert_vs_emplace.html>`_, but it might get support with some addition flag in the future.
+`speed regression <https://htmlpreview.github.io/?https://github.com/HowardHinnant/papers/blob/master/insert_vs_emplace.html>`_, but it might get support with some addition flag in the future.
By default only ``std::vector``, ``std::deque``, ``std::list`` are considered.
This list can be modified using the :option:`ContainersWithPushBack` option.
diff --git a/docs/clang-tidy/checks/modernize-use-override.rst b/docs/clang-tidy/checks/modernize-use-override.rst
index f2c778aa..4273c6e5 100644
--- a/docs/clang-tidy/checks/modernize-use-override.rst
+++ b/docs/clang-tidy/checks/modernize-use-override.rst
@@ -3,5 +3,42 @@
modernize-use-override
======================
+Adds ``override`` (introduced in C++11) to overridden virtual functions and
+removes ``virtual`` from those functions as it is not required.
-Use C++11's ``override`` and remove ``virtual`` where applicable.
+``virtual`` on non base class implementations was used to help indiciate to the
+user that a function was virtual. C++ compilers did not use the presence of
+this to signify an overriden function.
+
+In C++ 11 ``override`` and ``final`` keywords were introduced to allow
+overridden functions to be marked appropriately. Their presence allows
+compilers to verify that an overridden function correctly overrides a base
+class implementation.
+
+This can be useful as compilers can generate a compile time error when:
+
+ - The base class implementation function signature changes.
+ - The user has not created the override with the correct signature.
+
+Options
+-------
+
+.. option:: IgnoreDestructors
+
+ If set to non-zero, this check will not diagnose destructors. Default is `0`.
+
+.. option:: OverrideSpelling
+
+ Specifies a macro to use instead of ``override``. This is useful when
+ maintaining source code that also needs to compile with a pre-C++11
+ compiler.
+
+.. option:: FinalSpelling
+
+ Specifies a macro to use instead of ``final``. This is useful when
+ maintaining source code that also needs to compile with a pre-C++11
+ compiler.
+
+.. note::
+
+ For more information on the use of ``override`` see https://en.cppreference.com/w/cpp/language/override
diff --git a/docs/clang-tidy/checks/objc-property-declaration.rst b/docs/clang-tidy/checks/objc-property-declaration.rst
index 49df5102..60b9c82e 100644
--- a/docs/clang-tidy/checks/objc-property-declaration.rst
+++ b/docs/clang-tidy/checks/objc-property-declaration.rst
@@ -40,15 +40,3 @@ lowercase letters followed by a '_' to avoid naming conflict. For example:
@property(nonatomic, assign) int abc_lowerCamelCase;
The corresponding style rule: https://developer.apple.com/library/content/qa/qa1908/_index.html
-
-
-Options
--------
-
-.. option:: Acronyms
-
- This option is deprecated and ignored.
-
-.. option:: IncludeDefaultAcronyms
-
- This option is deprecated and ignored.
diff --git a/docs/clang-tidy/checks/objc-super-self.rst b/docs/clang-tidy/checks/objc-super-self.rst
new file mode 100644
index 00000000..ed0bb295
--- /dev/null
+++ b/docs/clang-tidy/checks/objc-super-self.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - objc-super-self
+
+objc-super-self
+===============
+
+Finds invocations of ``-self`` on super instances in initializers of subclasses
+of ``NSObject`` and recommends calling a superclass initializer instead.
+
+Invoking ``-self`` on super instances in initializers is a common programmer
+error when the programmer's original intent is to call a superclass
+initializer. Failing to call a superclass initializer breaks initializer
+chaining and can result in invalid object initialization.
+
diff --git a/docs/clang-tidy/checks/openmp-exception-escape.rst b/docs/clang-tidy/checks/openmp-exception-escape.rst
new file mode 100644
index 00000000..d85e4fd5
--- /dev/null
+++ b/docs/clang-tidy/checks/openmp-exception-escape.rst
@@ -0,0 +1,25 @@
+.. title:: clang-tidy - openmp-exception-escape
+
+openmp-exception-escape
+=======================
+
+Analyzes OpenMP Structured Blocks and checks that no exception escapes
+out of the Structured Block it was thrown in.
+
+As per the OpenMP specification, a structured block is an executable statement,
+possibly compound, with a single entry at the top and a single exit at the
+bottom. Which means, ``throw`` may not be used to to 'exit' out of the
+structured block. If an exception is not caught in the same structured block
+it was thrown in, the behaviour is undefined.
+
+FIXME: this check does not model SEH, ``setjmp``/``longjmp``.
+
+WARNING! This check may be expensive on large source files.
+
+Options
+-------
+
+.. option:: IgnoredExceptions
+
+ Comma-separated list containing type names which are not counted as thrown
+ exceptions in the check. Default value is an empty string.
diff --git a/docs/clang-tidy/checks/openmp-use-default-none.rst b/docs/clang-tidy/checks/openmp-use-default-none.rst
new file mode 100644
index 00000000..4223a10b
--- /dev/null
+++ b/docs/clang-tidy/checks/openmp-use-default-none.rst
@@ -0,0 +1,53 @@
+.. title:: clang-tidy - openmp-use-default-none
+
+openmp-use-default-none
+=======================
+
+Finds OpenMP directives that are allowed to contain a ``default`` clause,
+but either don't specify it or the clause is specified but with the kind
+other than ``none``, and suggests to use the ``default(none)`` clause.
+
+Using ``default(none)`` clause forces developers to explicitly specify data
+sharing attributes for the variables referenced in the construct,
+thus making it obvious which variables are referenced, and what is their
+data sharing attribute, thus increasing readability and possibly making errors
+easier to spot.
+
+Example
+-------
+
+.. code-block:: c++
+
+ // ``for`` directive can not have ``default`` clause, no diagnostics.
+ void n0(const int a) {
+ #pragma omp for
+ for (int b = 0; b < a; b++)
+ ;
+ }
+
+ // ``parallel`` directive.
+
+ // ``parallel`` directive can have ``default`` clause, but said clause is not
+ // specified, diagnosed.
+ void p0_0() {
+ #pragma omp parallel
+ ;
+ // WARNING: OpenMP directive ``parallel`` does not specify ``default``
+ // clause. Consider specifying ``default(none)`` clause.
+ }
+
+ // ``parallel`` directive can have ``default`` clause, and said clause is
+ // specified, with ``none`` kind, all good.
+ void p0_1() {
+ #pragma omp parallel default(none)
+ ;
+ }
+
+ // ``parallel`` directive can have ``default`` clause, and said clause is
+ // specified, but with ``shared`` kind, which is not ``none``, diagnose.
+ void p0_2() {
+ #pragma omp parallel default(shared)
+ ;
+ // WARNING: OpenMP directive ``parallel`` specifies ``default(shared)``
+ // clause. Consider using ``default(none)`` clause instead.
+ }
diff --git a/docs/clang-tidy/checks/portability-simd-intrinsics.rst b/docs/clang-tidy/checks/portability-simd-intrinsics.rst
index 2cd9d9f7..fedd47a1 100644
--- a/docs/clang-tidy/checks/portability-simd-intrinsics.rst
+++ b/docs/clang-tidy/checks/portability-simd-intrinsics.rst
@@ -46,4 +46,4 @@ Options
The namespace used to suggest `P0214`_ alternatives. If not specified, `std::`
for `-std=c++2a` and `std::experimental::` for `-std=c++11`.
-.. _P0214: http://wg21.link/p0214
+.. _P0214: https://wg21.link/p0214
diff --git a/docs/clang-tidy/checks/readability-else-after-return.rst b/docs/clang-tidy/checks/readability-else-after-return.rst
index 949b5bb4..c178a6a6 100644
--- a/docs/clang-tidy/checks/readability-else-after-return.rst
+++ b/docs/clang-tidy/checks/readability-else-after-return.rst
@@ -3,7 +3,7 @@
readability-else-after-return
=============================
-`LLVM Coding Standards <http://llvm.org/docs/CodingStandards.html>`_ advises to
+`LLVM Coding Standards <https://llvm.org/docs/CodingStandards.html>`_ advises to
reduce indentation where possible and where it makes understanding code easier.
Early exit is one of the suggested enforcements of that. Please do not use
``else`` or ``else if`` after something that interrupts control flow - like
@@ -61,4 +61,4 @@ Would be transformed into:
This check helps to enforce this `LLVM Coding Standards recommendation
-<http://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return>`_.
+<https://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return>`_.
diff --git a/docs/clang-tidy/checks/readability-magic-numbers.rst b/docs/clang-tidy/checks/readability-magic-numbers.rst
index 946672ed..9968809e 100644
--- a/docs/clang-tidy/checks/readability-magic-numbers.rst
+++ b/docs/clang-tidy/checks/readability-magic-numbers.rst
@@ -9,7 +9,7 @@ code and not introduced via constants or symbols.
Many coding guidelines advise replacing the magic values with symbolic
constants to improve readability. Here are a few references:
- * `Rule ES.45: Avoid “magic constants”; use symbolic constants in C++ Core Guidelines <http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-magic>`_
+ * `Rule ES.45: Avoid “magic constants”; use symbolic constants in C++ Core Guidelines <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-magic>`_
* `Rule 5.1.1 Use symbolic names instead of literal values in code in High Integrity C++ <http://www.codingstandard.com/rule/5-1-1-use-symbolic-names-instead-of-literal-values-in-code/>`_
* Item 17 in "C++ Coding Standards: 101 Rules, Guidelines and Best
Practices" by Herb Sutter and Andrei Alexandrescu
diff --git a/docs/clang-tidy/index.rst b/docs/clang-tidy/index.rst
index 20b18b4b..1b5af60d 100644
--- a/docs/clang-tidy/index.rst
+++ b/docs/clang-tidy/index.rst
@@ -10,6 +10,8 @@ See also:
:maxdepth: 1
The list of clang-tidy checks <checks/list>
+ Clang-tidy IDE/Editor Integrations <Integrations>
+ Getting Involved <Contributing>
:program:`clang-tidy` is a clang-based C++ "linter" tool. Its purpose is to
provide an extensible framework for diagnosing and fixing typical programming
@@ -71,6 +73,7 @@ Name prefix Description
means "C++11") language constructs.
``mpi-`` Checks related to MPI (Message Passing Interface).
``objc-`` Checks related to Objective-C coding conventions.
+``openmp-`` Checks related to OpenMP API.
``performance-`` Checks that target performance-related issues.
``portability-`` Checks that target portability-related issues that don't
relate to any particular coding style.
@@ -223,7 +226,7 @@ An overview of all the command-line options:
CMake option to get this output). When no build path is specified,
a search for compile_commands.json will be attempted through all
parent paths of the first input file . See:
- http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html for an
+ https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html for an
example of setting up Clang Tooling on a source tree.
<source0> ... specify the paths of source files. These paths are
@@ -258,30 +261,51 @@ An overview of all the command-line options:
Suppressing Undesired Diagnostics
=================================
-:program:`clang-tidy` diagnostics are intended to call out code that does
-not adhere to a coding standard, or is otherwise problematic in some way.
-However, if it is known that the code is correct, the check-specific ways
-to silence the diagnostics could be used, if they are available (e.g.
-bugprone-use-after-move can be silenced by re-initializing the variable after it
-has been moved out, bugprone-string-integer-assignment can be suppressed by
-explicitly casting the integer to char, readability-implicit-bool-conversion can
-also be suppressed by using explicit casts, etc.). If they are not available or
-if changing the semantics of the code is not desired, the ``NOLINT`` or
-``NOLINTNEXTLINE`` comments can be used instead. For example:
+:program:`clang-tidy` diagnostics are intended to call out code that does not
+adhere to a coding standard, or is otherwise problematic in some way. However,
+if the code is known to be correct, it may be useful to silence the warning.
+Some clang-tidy checks provide a check-specific way to silence the diagnostics,
+e.g. `bugprone-use-after-move <checks/bugprone-use-after-move.html>`_ can be
+silenced by re-initializing the variable after it has been moved out,
+`bugprone-string-integer-assignment
+<checks/bugprone-string-integer-assignment.html>`_ can be suppressed by
+explicitly casting the integer to ``char``,
+`readability-implicit-bool-conversion
+<checks/readability-implicit-bool-conversion.html>`_ can also be suppressed by
+using explicit casts, etc.
+
+If a specific suppression mechanism is not available for a certain warning, or
+its use is not desired for some reason, :program:`clang-tidy` has a generic
+mechanism to suppress diagnostics using ``NOLINT`` or ``NOLINTNEXTLINE``
+comments.
+
+The ``NOLINT`` comment instructs :program:`clang-tidy` to ignore warnings on the
+*same line* (it doesn't apply to a function, a block of code or any other
+language construct, it applies to the line of code it is on). If introducing the
+comment in the same line would change the formatting in undesired way, the
+``NOLINTNEXTLINE`` comment allows to suppress clang-tidy warnings on the *next
+line*.
+
+Both comments can be followed by an optional list of check names in parentheses
+(see below for the formal syntax).
+
+For example:
.. code-block:: c++
- class Foo
- {
- // Silent all the diagnostics for the line
+ class Foo {
+ // Suppress all the diagnostics for the line
Foo(int param); // NOLINT
- // Silent only the specified checks for the line
+ // Consider explaining the motivation to suppress the warning.
+ Foo(char param); // NOLINT: Allow implicit conversion from `char`, because <some valid reason>.
+
+ // Silence only the specified checks for the line
Foo(double param); // NOLINT(google-explicit-constructor, google-runtime-int)
- // Silent only the specified diagnostics for the next line
+ // Silence only the specified diagnostics for the next line
// NOLINTNEXTLINE(google-explicit-constructor, google-runtime-int)
- Foo(bool param);
+ Foo(bool param);
};
The formal syntax of ``NOLINT``/``NOLINTNEXTLINE`` is the following:
@@ -305,516 +329,8 @@ The formal syntax of ``NOLINT``/``NOLINTNEXTLINE`` is the following:
Note that whitespaces between ``NOLINT``/``NOLINTNEXTLINE`` and the opening
parenthesis are not allowed (in this case the comment will be treated just as
-``NOLINT``/``NOLINTNEXTLINE``), whereas in check names list (inside
-the parenthesis) whitespaces can be used and will be ignored.
-
-.. _LibTooling: http://clang.llvm.org/docs/LibTooling.html
-.. _How To Setup Tooling For LLVM: http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
-
-
-Getting Involved
-================
-
-:program:`clang-tidy` has several own checks and can run Clang static analyzer
-checks, but its power is in the ability to easily write custom checks.
-
-Checks are organized in modules, which can be linked into :program:`clang-tidy`
-with minimal or no code changes in :program:`clang-tidy`.
-
-Checks can plug into the analysis on the preprocessor level using `PPCallbacks`_
-or on the AST level using `AST Matchers`_. When an error is found, checks can
-report them in a way similar to how Clang diagnostics work. A fix-it hint can be
-attached to a diagnostic message.
-
-The interface provided by :program:`clang-tidy` makes it easy to write useful
-and precise checks in just a few lines of code. If you have an idea for a good
-check, the rest of this document explains how to do this.
-
-There are a few tools particularly useful when developing clang-tidy checks:
- * ``add_new_check.py`` is a script to automate the process of adding a new
- check, it will create the check, update the CMake file and create a test;
- * ``rename_check.py`` does what the script name suggests, renames an existing
- check;
- * :program:`clang-query` is invaluable for interactive prototyping of AST
- matchers and exploration of the Clang AST;
- * `clang-check`_ with the ``-ast-dump`` (and optionally ``-ast-dump-filter``)
- provides a convenient way to dump AST of a C++ program.
-
-If CMake is configured with ``CLANG_ENABLE_STATIC_ANALYZER``,
-:program:`clang-tidy` will not be built with support for the
-``clang-analyzer-*`` checks or the ``mpi-*`` checks.
-
-
-.. _AST Matchers: http://clang.llvm.org/docs/LibASTMatchers.html
-.. _PPCallbacks: http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html
-.. _clang-check: http://clang.llvm.org/docs/ClangCheck.html
-
-
-Choosing the Right Place for your Check
----------------------------------------
-
-If you have an idea of a check, you should decide whether it should be
-implemented as a:
-
-+ *Clang diagnostic*: if the check is generic enough, targets code patterns that
- most probably are bugs (rather than style or readability issues), can be
- implemented effectively and with extremely low false positive rate, it may
- make a good Clang diagnostic.
-
-+ *Clang static analyzer check*: if the check requires some sort of control flow
- analysis, it should probably be implemented as a static analyzer check.
-
-+ *clang-tidy check* is a good choice for linter-style checks, checks that are
- related to a certain coding style, checks that address code readability, etc.
-
-
-Preparing your Workspace
-------------------------
-
-If you are new to LLVM development, you should read the `Getting Started with
-the LLVM System`_, `Using Clang Tools`_ and `How To Setup Tooling For LLVM`_
-documents to check out and build LLVM, Clang and Clang Extra Tools with CMake.
-
-Once you are done, change to the ``llvm/tools/clang/tools/extra`` directory, and
-let's start!
-
-.. _Getting Started with the LLVM System: http://llvm.org/docs/GettingStarted.html
-.. _Using Clang Tools: http://clang.llvm.org/docs/ClangTools.html
-
-
-The Directory Structure
------------------------
-
-:program:`clang-tidy` source code resides in the
-``llvm/tools/clang/tools/extra`` directory and is structured as follows:
-
-::
-
- clang-tidy/ # Clang-tidy core.
- |-- ClangTidy.h # Interfaces for users and checks.
- |-- ClangTidyModule.h # Interface for clang-tidy modules.
- |-- ClangTidyModuleRegistry.h # Interface for registering of modules.
- ...
- |-- google/ # Google clang-tidy module.
- |-+
- |-- GoogleTidyModule.cpp
- |-- GoogleTidyModule.h
- ...
- |-- llvm/ # LLVM clang-tidy module.
- |-+
- |-- LLVMTidyModule.cpp
- |-- LLVMTidyModule.h
- ...
- |-- objc/ # Objective-C clang-tidy module.
- |-+
- |-- ObjCTidyModule.cpp
- |-- ObjCTidyModule.h
- ...
- |-- tool/ # Sources of the clang-tidy binary.
- ...
- test/clang-tidy/ # Integration tests.
- ...
- unittests/clang-tidy/ # Unit tests.
- |-- ClangTidyTest.h
- |-- GoogleModuleTest.cpp
- |-- LLVMModuleTest.cpp
- |-- ObjCModuleTest.cpp
- ...
-
-
-Writing a clang-tidy Check
---------------------------
-
-So you have an idea of a useful check for :program:`clang-tidy`.
-
-First, if you're not familiar with LLVM development, read through the `Getting
-Started with LLVM`_ document for instructions on setting up your workflow and
-the `LLVM Coding Standards`_ document to familiarize yourself with the coding
-style used in the project. For code reviews we mostly use `LLVM Phabricator`_.
-
-.. _Getting Started with LLVM: http://llvm.org/docs/GettingStarted.html
-.. _LLVM Coding Standards: http://llvm.org/docs/CodingStandards.html
-.. _LLVM Phabricator: http://llvm.org/docs/Phabricator.html
-
-Next, you need to decide which module the check belongs to. Modules
-are located in subdirectories of `clang-tidy/
-<http://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/clang-tidy/>`_
-and contain checks targeting a certain aspect of code quality (performance,
-readability, etc.), certain coding style or standard (Google, LLVM, CERT, etc.)
-or a widely used API (e.g. MPI). Their names are same as user-facing check
-groups names described :ref:`above <checks-groups-table>`.
-
-After choosing the module and the name for the check, run the
-``clang-tidy/add_new_check.py`` script to create the skeleton of the check and
-plug it to :program:`clang-tidy`. It's the recommended way of adding new checks.
-
-If we want to create a `readability-awesome-function-names`, we would run:
-
-.. code-block:: console
-
- $ clang-tidy/add_new_check.py readability awesome-function-names
-
-
-The ``add_new_check.py`` script will:
- * create the class for your check inside the specified module's directory and
- register it in the module and in the build system;
- * create a lit test file in the ``test/clang-tidy/`` directory;
- * create a documentation file and include it into the
- ``docs/clang-tidy/checks/list.rst``.
-
-Let's see in more detail at the check class definition:
-
-.. code-block:: c++
-
- ...
-
- #include "../ClangTidy.h"
-
- namespace clang {
- namespace tidy {
- namespace readability {
-
- ...
- class AwesomeFunctionNamesCheck : public ClangTidyCheck {
- public:
- AwesomeFunctionNamesCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context) {}
- void registerMatchers(ast_matchers::MatchFinder *Finder) override;
- void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
- };
-
- } // namespace readability
- } // namespace tidy
- } // namespace clang
-
- ...
-
-Constructor of the check receives the ``Name`` and ``Context`` parameters, and
-must forward them to the ``ClangTidyCheck`` constructor.
-
-In our case the check needs to operate on the AST level and it overrides the
-``registerMatchers`` and ``check`` methods. If we wanted to analyze code on the
-preprocessor level, we'd need instead to override the ``registerPPCallbacks``
-method.
-
-In the ``registerMatchers`` method we create an AST Matcher (see `AST Matchers`_
-for more information) that will find the pattern in the AST that we want to
-inspect. The results of the matching are passed to the ``check`` method, which
-can further inspect them and report diagnostics.
-
-.. code-block:: c++
-
- using namespace ast_matchers;
-
- void AwesomeFunctionNamesCheck::registerMatchers(MatchFinder *Finder) {
- Finder->addMatcher(functionDecl().bind("x"), this);
- }
-
- void AwesomeFunctionNamesCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>("x");
- if (MatchedDecl->getName().startswith("awesome_"))
- return;
- diag(MatchedDecl->getLocation(), "function %0 is insufficiently awesome")
- << MatchedDecl
- << FixItHint::CreateInsertion(MatchedDecl->getLocation(), "awesome_");
- }
-
-(If you want to see an example of a useful check, look at
-`clang-tidy/google/ExplicitConstructorCheck.h
-<http://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/clang-tidy/google/ExplicitConstructorCheck.h>`_
-and `clang-tidy/google/ExplicitConstructorCheck.cpp
-<http://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/clang-tidy/google/ExplicitConstructorCheck.cpp>`_).
-
-
-Registering your Check
-----------------------
-
-(The ``add_new_check.py`` takes care of registering the check in an existing
-module. If you want to create a new module or know the details, read on.)
-
-The check should be registered in the corresponding module with a distinct name:
-
-.. code-block:: c++
-
- class MyModule : public ClangTidyModule {
- public:
- void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
- CheckFactories.registerCheck<ExplicitConstructorCheck>(
- "my-explicit-constructor");
- }
- };
-
-Now we need to register the module in the ``ClangTidyModuleRegistry`` using a
-statically initialized variable:
-
-.. code-block:: c++
-
- static ClangTidyModuleRegistry::Add<MyModule> X("my-module",
- "Adds my lint checks.");
-
-
-When using LLVM build system, we need to use the following hack to ensure the
-module is linked into the :program:`clang-tidy` binary:
-
-Add this near the ``ClangTidyModuleRegistry::Add<MyModule>`` variable:
-
-.. code-block:: c++
-
- // This anchor is used to force the linker to link in the generated object file
- // and thus register the MyModule.
- volatile int MyModuleAnchorSource = 0;
-
-And this to the main translation unit of the :program:`clang-tidy` binary (or
-the binary you link the ``clang-tidy`` library in)
-``clang-tidy/tool/ClangTidyMain.cpp``:
-
-.. code-block:: c++
-
- // This anchor is used to force the linker to link the MyModule.
- extern volatile int MyModuleAnchorSource;
- static int MyModuleAnchorDestination = MyModuleAnchorSource;
-
-
-Configuring Checks
-------------------
-
-If a check needs configuration options, it can access check-specific options
-using the ``Options.get<Type>("SomeOption", DefaultValue)`` call in the check
-constructor. In this case the check should also override the
-``ClangTidyCheck::storeOptions`` method to make the options provided by the
-check discoverable. This method lets :program:`clang-tidy` know which options
-the check implements and what the current values are (e.g. for the
-``-dump-config`` command line option).
-
-.. code-block:: c++
-
- class MyCheck : public ClangTidyCheck {
- const unsigned SomeOption1;
- const std::string SomeOption2;
-
- public:
- MyCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context),
- SomeOption(Options.get("SomeOption1", -1U)),
- SomeOption(Options.get("SomeOption2", "some default")) {}
-
- void storeOptions(ClangTidyOptions::OptionMap &Opts) override {
- Options.store(Opts, "SomeOption1", SomeOption1);
- Options.store(Opts, "SomeOption2", SomeOption2);
- }
- ...
-
-Assuming the check is registered with the name "my-check", the option can then
-be set in a ``.clang-tidy`` file in the following way:
-
-.. code-block:: yaml
-
- CheckOptions:
- - key: my-check.SomeOption1
- value: 123
- - key: my-check.SomeOption2
- value: 'some other value'
-
-If you need to specify check options on a command line, you can use the inline
-YAML format:
-
-.. code-block:: console
-
- $ clang-tidy -config="{CheckOptions: [{key: a, value: b}, {key: x, value: y}]}" ...
-
-
-Testing Checks
---------------
-
-To run tests for :program:`clang-tidy` use the command:
-
-.. code-block:: console
-
- $ ninja check-clang-tools
-
-:program:`clang-tidy` checks can be tested using either unit tests or
-`lit`_ tests. Unit tests may be more convenient to test complex replacements
-with strict checks. `Lit`_ tests allow using partial text matching and regular
-expressions which makes them more suitable for writing compact tests for
-diagnostic messages.
-
-The ``check_clang_tidy.py`` script provides an easy way to test both
-diagnostic messages and fix-its. It filters out ``CHECK`` lines from the test
-file, runs :program:`clang-tidy` and verifies messages and fixes with two
-separate `FileCheck`_ invocations: once with FileCheck's directive
-prefix set to ``CHECK-MESSAGES``, validating the diagnostic messages,
-and once with the directive prefix set to ``CHECK-FIXES``, running
-against the fixed code (i.e., the code after generated fix-its are
-applied). In particular, ``CHECK-FIXES:`` can be used to check
-that code was not modified by fix-its, by checking that it is present
-unchanged in the fixed code. The full set of `FileCheck`_ directives
-is available (e.g., ``CHECK-MESSAGES-SAME:``, ``CHECK-MESSAGES-NOT:``), though
-typically the basic ``CHECK`` forms (``CHECK-MESSAGES`` and ``CHECK-FIXES``)
-are sufficient for clang-tidy tests. Note that the `FileCheck`_
-documentation mostly assumes the default prefix (``CHECK``), and hence
-describes the directive as ``CHECK:``, ``CHECK-SAME:``, ``CHECK-NOT:``, etc.
-Replace ``CHECK`` by either ``CHECK-FIXES`` or ``CHECK-MESSAGES`` for
-clang-tidy tests.
-
-An additional check enabled by ``check_clang_tidy.py`` ensures that
-if `CHECK-MESSAGES:` is used in a file then every warning or error
-must have an associated CHECK in that file. Or, you can use ``CHECK-NOTES:``
-instead, if you want to **also** ensure that all the notes are checked.
-
-To use the ``check_clang_tidy.py`` script, put a .cpp file with the
-appropriate ``RUN`` line in the ``test/clang-tidy`` directory. Use
-``CHECK-MESSAGES:`` and ``CHECK-FIXES:`` lines to write checks against
-diagnostic messages and fixed code.
-
-It's advised to make the checks as specific as possible to avoid checks matching
-to incorrect parts of the input. Use ``[[@LINE+X]]``/``[[@LINE-X]]``
-substitutions and distinct function and variable names in the test code.
-
-Here's an example of a test using the ``check_clang_tidy.py`` script (the full
-source code is at `test/clang-tidy/google-readability-casting.cpp`_):
-
-.. code-block:: c++
-
- // RUN: %check_clang_tidy %s google-readability-casting %t
-
- void f(int a) {
- int b = (int)a;
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant cast to the same type [google-readability-casting]
- // CHECK-FIXES: int b = a;
- }
-
-To check more than one scenario in the same test file use
-``-check-suffix=SUFFIX-NAME`` on ``check_clang_tidy.py`` command line or
-``-check-suffixes=SUFFIX-NAME-1,SUFFIX-NAME-2,...``.
-With ``-check-suffix[es]=SUFFIX-NAME`` you need to replace your ``CHECK-*``
-directives with ``CHECK-MESSAGES-SUFFIX-NAME`` and ``CHECK-FIXES-SUFFIX-NAME``.
-
-Here's an example:
-
-.. code-block:: c++
-
- // RUN: %check_clang_tidy -check-suffix=USING-A %s misc-unused-using-decls %t -- -- -DUSING_A
- // RUN: %check_clang_tidy -check-suffix=USING-B %s misc-unused-using-decls %t -- -- -DUSING_B
- // RUN: %check_clang_tidy %s misc-unused-using-decls %t
- ...
- // CHECK-MESSAGES-USING-A: :[[@LINE-8]]:10: warning: using decl 'A' {{.*}}
- // CHECK-MESSAGES-USING-B: :[[@LINE-7]]:10: warning: using decl 'B' {{.*}}
- // CHECK-MESSAGES: :[[@LINE-6]]:10: warning: using decl 'C' {{.*}}
- // CHECK-FIXES-USING-A-NOT: using a::A;$
- // CHECK-FIXES-USING-B-NOT: using a::B;$
- // CHECK-FIXES-NOT: using a::C;$
-
-
-There are many dark corners in the C++ language, and it may be difficult to make
-your check work perfectly in all cases, especially if it issues fix-it hints. The
-most frequent pitfalls are macros and templates:
-
-1. code written in a macro body/template definition may have a different meaning
- depending on the macro expansion/template instantiation;
-2. multiple macro expansions/template instantiations may result in the same code
- being inspected by the check multiple times (possibly, with different
- meanings, see 1), and the same warning (or a slightly different one) may be
- issued by the check multiple times; :program:`clang-tidy` will deduplicate
- _identical_ warnings, but if the warnings are slightly different, all of them
- will be shown to the user (and used for applying fixes, if any);
-3. making replacements to a macro body/template definition may be fine for some
- macro expansions/template instantiations, but easily break some other
- expansions/instantiations.
-
-.. _lit: http://llvm.org/docs/CommandGuide/lit.html
-.. _FileCheck: http://llvm.org/docs/CommandGuide/FileCheck.html
-.. _test/clang-tidy/google-readability-casting.cpp: http://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/test/clang-tidy/google-readability-casting.cpp
-
-
-Running clang-tidy on LLVM
---------------------------
-
-To test a check it's best to try it out on a larger code base. LLVM and Clang
-are the natural targets as you already have the source code around. The most
-convenient way to run :program:`clang-tidy` is with a compile command database;
-CMake can automatically generate one, for a description of how to enable it see
-`How To Setup Tooling For LLVM`_. Once ``compile_commands.json`` is in place and
-a working version of :program:`clang-tidy` is in ``PATH`` the entire code base
-can be analyzed with ``clang-tidy/tool/run-clang-tidy.py``. The script executes
-:program:`clang-tidy` with the default set of checks on every translation unit
-in the compile command database and displays the resulting warnings and errors.
-The script provides multiple configuration flags.
-
-* The default set of checks can be overridden using the ``-checks`` argument,
- taking the identical format as :program:`clang-tidy` does. For example
- ``-checks=-*,modernize-use-override`` will run the ``modernize-use-override``
- check only.
-
-* To restrict the files examined you can provide one or more regex arguments
- that the file names are matched against.
- ``run-clang-tidy.py clang-tidy/.*Check\.cpp`` will only analyze clang-tidy
- checks. It may also be necessary to restrict the header files warnings are
- displayed from using the ``-header-filter`` flag. It has the same behavior
- as the corresponding :program:`clang-tidy` flag.
-
-* To apply suggested fixes ``-fix`` can be passed as an argument. This gathers
- all changes in a temporary directory and applies them. Passing ``-format``
- will run clang-format over changed lines.
-
-
-On checks profiling
--------------------
-
-:program:`clang-tidy` can collect per-check profiling info, and output it
-for each processed source file (translation unit).
-
-To enable profiling info collection, use the ``-enable-check-profile`` argument.
-The timings will be output to ``stderr`` as a table. Example output:
-
-.. code-block:: console
-
- $ clang-tidy -enable-check-profile -checks=-*,readability-function-size source.cpp
- ===-------------------------------------------------------------------------===
- clang-tidy checks profiling
- ===-------------------------------------------------------------------------===
- Total Execution Time: 1.0282 seconds (1.0258 wall clock)
-
- ---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Name ---
- 0.9136 (100.0%) 0.1146 (100.0%) 1.0282 (100.0%) 1.0258 (100.0%) readability-function-size
- 0.9136 (100.0%) 0.1146 (100.0%) 1.0282 (100.0%) 1.0258 (100.0%) Total
-
-It can also store that data as JSON files for further processing. Example output:
-
-.. code-block:: console
+``NOLINT``/``NOLINTNEXTLINE``), whereas in check names list (inside the
+parenthesis) whitespaces can be used and will be ignored.
- $ clang-tidy -enable-check-profile -store-check-profile=. -checks=-*,readability-function-size source.cpp
- $ # Note that there won't be timings table printed to the console.
- $ ls /tmp/out/
- 20180516161318717446360-source.cpp.json
- $ cat 20180516161318717446360-source.cpp.json
- {
- "file": "/path/to/source.cpp",
- "timestamp": "2018-05-16 16:13:18.717446360",
- "profile": {
- "time.clang-tidy.readability-function-size.wall": 1.0421266555786133e+00,
- "time.clang-tidy.readability-function-size.user": 9.2088400000005421e-01,
- "time.clang-tidy.readability-function-size.sys": 1.2418899999999974e-01
- }
- }
-
-There is only one argument that controls profile storage:
-
-* ``-store-check-profile=<prefix>``
-
- By default reports are printed in tabulated format to stderr. When this option
- is passed, these per-TU profiles are instead stored as JSON.
- If the prefix is not an absolute path, it is considered to be relative to the
- directory from where you have run :program:`clang-tidy`. All ``.`` and ``..``
- patterns in the path are collapsed, and symlinks are resolved.
-
- Example:
- Let's suppose you have a source file named ``example.cpp``, located in the
- ``/source`` directory. Only the input filename is used, not the full path
- to the source file. Additionally, it is prefixed with the current timestamp.
-
- * If you specify ``-store-check-profile=/tmp``, then the profile will be saved
- to ``/tmp/<ISO8601-like timestamp>-example.cpp.json``
-
- * If you run :program:`clang-tidy` from within ``/foo`` directory, and specify
- ``-store-check-profile=.``, then the profile will still be saved to
- ``/foo/<ISO8601-like timestamp>-example.cpp.json``
+.. _LibTooling: https://clang.llvm.org/docs/LibTooling.html
+.. _How To Setup Tooling For LLVM: https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
diff --git a/docs/clangd.rst b/docs/clangd.rst
index 0b276380..7910fac3 100644
--- a/docs/clangd.rst
+++ b/docs/clangd.rst
@@ -1,161 +1,6 @@
-============
-Clangd
-============
+:orphan:
-.. contents::
+.. meta::
+ :http-equiv=refresh: 0;URL='clangd/'
-.. toctree::
- :maxdepth: 1
-
-:program:`Clangd` is an implementation of the `Language Server Protocol
-<https://github.com/Microsoft/language-server-protocol>`_ leveraging Clang.
-Clangd's goal is to provide language "smartness" features like code completion,
-find references, etc. for clients such as C/C++ Editors.
-
-Using Clangd
-==================
-
-:program:`Clangd` is not meant to be used by C/C++ developers directly but
-rather from a client implementing the protocol. A client would be typically
-implemented in an IDE or an editor.
-
-At the moment, `Visual Studio Code <https://code.visualstudio.com/>`_ is mainly
-used in order to test :program:`Clangd` but more clients are likely to make
-use of :program:`Clangd` in the future as it matures and becomes a production
-quality tool. If you are interested in trying :program:`Clangd` in combination
-with Visual Studio Code, you can start by `installing Clangd`_ or
-`building Clangd`_, then open Visual Studio Code in the clangd-vscode folder and
-launch the extension.
-
-Installing Clangd
-==================
-
-Packages are available for debian-based distributions, see the `LLVM packages
-page <http://apt.llvm.org/>`_. :program:`Clangd` is included in the
-`clang-tools` package.
-However, it is a good idea to check your distribution's packaging system first
-as it might already be available.
-
-Otherwise, you can install :program:`Clangd` by `building Clangd`_ first.
-
-Building Clangd
-==================
-
-You can follow the instructions for `building Clang
-<https://clang.llvm.org/get_started.html>`_ but "extra Clang tools" is **not**
-optional.
-
-Current Status
-==================
-
-Many features could be implemented in :program:`Clangd`.
-Here is a list of features that could be useful with the status of whether or
-not they are already implemented in :program:`Clangd` and specified in the
-Language Server Protocol. Note that for some of the features, it is not clear
-whether or not they should be part of the Language Server Protocol, so those
-features might be eventually developed outside :program:`Clangd` or as an
-extension to the protocol.
-
-+-------------------------------------+------------+----------+
-| C/C++ Editor feature | LSP | Clangd |
-+=====================================+============+==========+
-| Formatting | Yes | Yes |
-+-------------------------------------+------------+----------+
-| Completion | Yes | Yes |
-+-------------------------------------+------------+----------+
-| Diagnostics | Yes | Yes |
-+-------------------------------------+------------+----------+
-| Fix-its | Yes | Yes |
-+-------------------------------------+------------+----------+
-| Go to Definition | Yes | Yes |
-+-------------------------------------+------------+----------+
-| Signature Help | Yes | Yes |
-+-------------------------------------+------------+----------+
-| Document Highlights | Yes | Yes |
-+-------------------------------------+------------+----------+
-| Rename | Yes | Yes |
-+-------------------------------------+------------+----------+
-| Source hover | Yes | Yes |
-+-------------------------------------+------------+----------+
-| Find References | Yes | No |
-+-------------------------------------+------------+----------+
-| Code Lens | Yes | No |
-+-------------------------------------+------------+----------+
-| Document Symbols | Yes | Yes |
-+-------------------------------------+------------+----------+
-| Workspace Symbols | Yes | Yes |
-+-------------------------------------+------------+----------+
-| Syntax and Semantic Coloring | No | No |
-+-------------------------------------+------------+----------+
-| Code folding | No | No |
-+-------------------------------------+------------+----------+
-| Call hierarchy | No | No |
-+-------------------------------------+------------+----------+
-| Type hierarchy | No | No |
-+-------------------------------------+------------+----------+
-| Organize Includes | No | No |
-+-------------------------------------+------------+----------+
-| Quick Assist | No | No |
-+-------------------------------------+------------+----------+
-| Extract Local Variable | No | No |
-+-------------------------------------+------------+----------+
-| Extract Function/Method | No | No |
-+-------------------------------------+------------+----------+
-| Hide Method | No | No |
-+-------------------------------------+------------+----------+
-| Implement Method | No | No |
-+-------------------------------------+------------+----------+
-| Gen. Getters/Setters | No | No |
-+-------------------------------------+------------+----------+
-
-Editor Integration
-==================
-
-Any full-featured Language Server Protocol Client implementation should work
-with :program:`Clangd`. This `list
-<https://langserver.org/#implementations-client>`_ contains information about
-extensions and plugins that are known to work for different editors.
-
-Vim Integration
----------------
-
-LanguageClient-neovim
-~~~~~~~~~~~~~~~~~~~~~
-
-One of the options of using :program:`Clangd` in :program:`vim` (or
-:program:`nvim`) is to utilize `LanguageClient-neovim
-<https://github.com/autozimu/LanguageClient-neovim>`_ plugin. Please see the
-`Clangd Wiki page
-<https://github.com/autozimu/LanguageClient-neovim/wiki/Clangd>`_ for
-instructions.
-
-VSCode Integration
-------------------
-
-:program:`VSCode` provides `vscode-clangd
-<https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd>`_
-which is published in Visual Studio Marketplace and can be installed direcetly
-from :program:`VSCode`.
-
-Emacs Integration
------------------
-
-:program:`Emacs` provides `lsp-mode <github.com/emacs-lsp/lsp-mode>`_ and
-`Eglot <https://github.com/joaotavora/eglot>`_ plugins for LSP integration.
-
-Getting Involved
-==================
-
-A good place for interested contributors is the `Clangd developer mailing list
-<http://lists.llvm.org/mailman/listinfo/clangd-dev>`_. For discussions with the
-broader community on topics not only related to Clangd, use
-`Clang developer mailing list
-<http://lists.llvm.org/mailman/listinfo/cfe-dev>`_.
-If you're also interested in contributing patches to :program:`Clangd`, take a
-look at the `LLVM Developer Policy
-<http://llvm.org/docs/DeveloperPolicy.html>`_ and `Code Reviews
-<http://llvm.org/docs/Phabricator.html>`_ page. Contributions of new features
-to the `Language Server Protocol
-<https://github.com/Microsoft/language-server-protocol>`_ itself would also be
-very useful, so that :program:`Clangd` can eventually implement them in a
-conforming way.
+All :program:`clangd` documentation was moved to the :doc:`clangd/index` pages.
diff --git a/docs/clangd/ApplyClangTidyFixInVSCode.gif b/docs/clangd/ApplyClangTidyFixInVSCode.gif
new file mode 100644
index 00000000..b07bdeb4
--- /dev/null
+++ b/docs/clangd/ApplyClangTidyFixInVSCode.gif
Binary files differ
diff --git a/docs/clangd/ApplyFixInVSCode.gif b/docs/clangd/ApplyFixInVSCode.gif
new file mode 100644
index 00000000..929a98c3
--- /dev/null
+++ b/docs/clangd/ApplyFixInVSCode.gif
Binary files differ
diff --git a/docs/clangd/CodeCompletionInEmacsCompanyMode.png b/docs/clangd/CodeCompletionInEmacsCompanyMode.png
new file mode 100644
index 00000000..1accc5af
--- /dev/null
+++ b/docs/clangd/CodeCompletionInEmacsCompanyMode.png
Binary files differ
diff --git a/docs/clangd/CodeCompletionInSublimeText.png b/docs/clangd/CodeCompletionInSublimeText.png
new file mode 100644
index 00000000..b09fed3b
--- /dev/null
+++ b/docs/clangd/CodeCompletionInSublimeText.png
Binary files differ
diff --git a/docs/clangd/CodeCompletionInVSCode.png b/docs/clangd/CodeCompletionInVSCode.png
new file mode 100644
index 00000000..bc42e9dd
--- /dev/null
+++ b/docs/clangd/CodeCompletionInVSCode.png
Binary files differ
diff --git a/docs/clangd/CodeCompletionInYCM.png b/docs/clangd/CodeCompletionInYCM.png
new file mode 100644
index 00000000..b74508d6
--- /dev/null
+++ b/docs/clangd/CodeCompletionInYCM.png
Binary files differ
diff --git a/docs/clangd/CodeCompletionInsertsNamespaceQualifiersInVSCode.gif b/docs/clangd/CodeCompletionInsertsNamespaceQualifiersInVSCode.gif
new file mode 100644
index 00000000..f0d49d63
--- /dev/null
+++ b/docs/clangd/CodeCompletionInsertsNamespaceQualifiersInVSCode.gif
Binary files differ
diff --git a/docs/clangd/DeveloperDocumentation.rst b/docs/clangd/DeveloperDocumentation.rst
new file mode 100644
index 00000000..75843279
--- /dev/null
+++ b/docs/clangd/DeveloperDocumentation.rst
@@ -0,0 +1,29 @@
+==================================
+Developer documentation for clangd
+==================================
+
+.. toctree::
+ :maxdepth: 1
+
+ Extensions
+
+Compiling clangd
+================
+
+To build clangd from source, please follow the instructions for `building Clang
+<https://clang.llvm.org/get_started.html>`_ and include LLVM, Clang, and the
+"extra Clang tools" in your build.
+
+Contributing to clangd
+======================
+
+A good place for interested contributors is the `Clangd developer mailing list
+<https://lists.llvm.org/mailman/listinfo/clangd-dev>`_. For discussions with
+the broader community on topics not only related to Clangd, use `Clang
+developer mailing list <https://lists.llvm.org/mailman/listinfo/cfe-dev>`_. If
+you're also interested in contributing patches to clangd, take a look at the
+`LLVM Developer Policy <https://llvm.org/docs/DeveloperPolicy.html>`_ and `Code
+Reviews <https://llvm.org/docs/Phabricator.html>`_ page. Contributions of new
+features to the `Language Server Protocol
+<https://github.com/Microsoft/language-server-protocol>`_ itself would also be
+very useful, so that clangd can eventually implement them in a conforming way.
diff --git a/docs/clangd/DiagnosticsInEmacsEglot.png b/docs/clangd/DiagnosticsInEmacsEglot.png
new file mode 100644
index 00000000..f5be84bf
--- /dev/null
+++ b/docs/clangd/DiagnosticsInEmacsEglot.png
Binary files differ
diff --git a/docs/clangd/ErrorsInVSCode.png b/docs/clangd/ErrorsInVSCode.png
new file mode 100644
index 00000000..52de4029
--- /dev/null
+++ b/docs/clangd/ErrorsInVSCode.png
Binary files differ
diff --git a/docs/clangd/Extensions.rst b/docs/clangd/Extensions.rst
new file mode 100644
index 00000000..6c972ebd
--- /dev/null
+++ b/docs/clangd/Extensions.rst
@@ -0,0 +1,175 @@
+===================
+Protocol extensions
+===================
+
+.. contents::
+
+clangd supports some features that are not in the official
+`Language Server Protocol specification
+<https://microsoft.github.io/language-server-protocol/specification>`__.
+
+We cautious about adding extensions. The most important considerations are:
+
+- **Editor support**: How many users will the feature be available to?
+- **Standardization**: Is the feature stable? Is it likely to be adopted by more
+ editors over time?
+- **Utility**: Does the feature provide a lot of value?
+- **Complexity**: Is this hard to implement in clangd, or constrain future work?
+ Is the protocol complicated?
+
+These extensions may evolve or disappear over time. If you use them, try to
+recover gracefully if the structures aren't what's expected.
+
+Switch between the implementation file and the header
+=====================================================
+
+*This extension is supported in clangd 6 and newer.*
+
+Switching between the implementation file and the header is an important
+feature for C++. A language server that understands C++ can do a better job
+than the editor.
+
+**New client->server request**: ``textDocument/switchSourceHeader``.
+
+Lets editors switch between the main source file (``*.cpp``) and header (``*.h``).
+
+Parameter: ``TextDocumentIdentifier``: an open file.
+
+Result: ``string``: the URI of the corresponding header (if a source file was
+provided) or source file (if a header was provided).
+
+If the corresponding file can't be determined, ``""`` is returned.
+
+File status
+===========
+
+*This extension is supported in clangd 8 and newer.*
+
+It is important to provide feedback to the user when the UI is not responsive.
+
+This extension provides information about activity on clangd's per-file worker
+thread. This information can be displayed to users to let them know that the
+language server is busy with something. For example, in clangd, building the
+AST blocks many other operations.
+
+**New server->client notification**: ``textDocument/clangd.fileStatus``
+
+Sent when the current activity for a file changes. Replaces previous activity
+for that file.
+
+Parameter: ``FileStatus`` object with properties:
+
+- ``uri : string``: the document whose status is being updated.
+- ``state : string``: human-readable information about current activity.
+
+**New initialization option**: ``initializationOptions.clangdFileStatus : bool``
+
+Enables receiving ``textDocument/clangd.fileStatus`` notifications.
+
+Compilation commands
+====================
+
+*This extension is supported in clangd 8 and newer.*
+
+clangd relies on knowing accurate compilation options to correctly interpret a
+file. Typically they are found in a ``compile_commands.json`` file in a
+directory that contains the file, or an ancestor directory. The following
+extensions allow editors to supply the commands over LSP instead.
+
+**New initialization option**: ``initializationOptions.compilationDatabasePath : string``
+
+Specifies the directory containing the compilation database (e.g.,
+``compile_commands.json``). This path will be used for all files, instead of
+searching their ancestor directories.
+
+**New initialization option**: ``initializationOptions.fallbackFlags : string[]``
+
+Controls the flags used when no specific compile command is found. The compile
+command will be approximately ``clang $FILE $fallbackFlags`` in this case.
+
+**New configuration setting**: ``settings.compilationDatabaseChanges : {string: CompileCommand}``
+
+Provides compile commands for files. This can also be provided on startup as
+``initializationOptions.compilationDatabaseChanges``.
+
+Keys are file paths (Not URIs!)
+
+Values are ``{workingDirectory: string, compilationCommand: string[]}``.
+
+Force diagnostics generation
+============================
+
+*This extension is supported in clangd 7 and newer.*
+
+Clangd does not regenerate diagnostics for every version of a file (e.g., after
+every keystroke), as that would be too slow. Its heuristics ensure:
+
+- diagnostics do not get too stale,
+- if you stop editing, diagnostics will catch up.
+
+This extension allows editors to force diagnostics to be generated or not
+generated at a particular revision.
+
+**New property of** ``textDocument/didChange`` **request**: ``wantDiagnostics : bool``
+
+- if true, diagnostics will be produced for exactly this version.
+- if false, diagnostics will not be produced for this version, even if there
+ are no further edits.
+- if unset, diagnostics will be produced for this version or some subsequent
+ one in a bounded amount of time.
+
+Diagnostic categories
+=====================
+
+*This extension is supported in clangd 8 and newer.*
+
+Clang compiler groups diagnostics into categories (e.g., "Inline Assembly
+Issue"). Clangd can emit these categories for interested editors.
+
+**New property of** ``Diagnostic`` **object**: ``category : string``:
+
+A human-readable name for a group of related diagnostics. Diagnostics with the
+same code will always have the same category.
+
+**New client capability**: ``textDocument.publishDiagnostics.categorySupport``:
+
+Requests that clangd send ``Diagnostic.category``.
+
+Inline fixes for diagnostics
+============================
+
+*This extension is supported in clangd 8 and newer.*
+
+LSP specifies that code actions for diagnostics (fixes) are retrieved
+asynchronously using ``textDocument/codeAction``. clangd always computes fixes
+eagerly. Providing them alongside diagnostics can improve the UX in editors.
+
+**New property of** ``Diagnostic`` **object**: ``codeActions : CodeAction[]``:
+
+All the code actions that address this diagnostic.
+
+**New client capability**: ``textDocument.publishDiagnostics.codeActionsInline : bool``
+
+Requests clangd to send ``Diagnostic.codeActions``.
+
+Symbol info request
+===================
+
+*This extension is supported in clangd 8 and newer.*
+
+**New client->server request**: ``textDocument/symbolInfo``:
+
+This request attempts to resolve the symbol under the cursor, without
+retrieving further information (like definition location, which may require
+consulting an index). This request was added to support integration with
+indexes outside clangd.
+
+Parameter: ``TextDocumentPositionParams``
+
+Response: ``SymbolDetails``, an object with properties:
+
+- ``name : string`` the unqualified name of the symbol
+- ``containerName : string`` the enclosing namespace, class etc (without
+ trailing ``::``)
+- ``usr : string``: the clang-specific "unified symbol resolution" identifier
+- ``id : string?``: the clangd-specific opaque symbol ID
diff --git a/docs/clangd/Features.rst b/docs/clangd/Features.rst
new file mode 100644
index 00000000..3e6e745a
--- /dev/null
+++ b/docs/clangd/Features.rst
@@ -0,0 +1,267 @@
+========
+Features
+========
+
+.. contents::
+
+.. role:: raw-html(raw)
+ :format: html
+
+Here is what clangd can do for you. Screenshots below show `VSCode
+<https://code.visualstudio.com/>`__; the available features and UI depend on
+the editor.
+
+Errors and warnings
+===================
+
+clangd runs the clang compiler on your code as you type, and shows errors and
+warnings in-place. Some errors are suppressed: diagnostics that require
+expanding templates in headers are disabled for performance reasons.
+
+:raw-html:`<details><summary markdown="span">Screenshot</summary>`
+
+.. image:: ErrorsInVSCode.png
+ :align: center
+ :alt: Demonstration of errors
+
+:raw-html:`</details>`
+
+Fixes in errors and warnings
+----------------------------
+
+The compiler can suggest fixes for many common problems automatically, and
+clangd can update the code for you.
+
+:raw-html:`<details><summary markdown="span">Animated demo</summary>`
+
+.. image:: ApplyFixInVSCode.gif
+ :align: center
+ :alt: Applying a fix suggested by the compiler
+
+:raw-html:`</details>`
+
+**(New in v9)**
+If a missing symbol was seen in a file you've edited recently, clangd will
+suggest inserting it.
+
+clang-tidy checks
+-----------------
+
+**(New in v9)**
+clangd embeds `clang-tidy <https://clang.llvm.org/extra/clang-tidy/>`__
+which provides extra hints about code problems: bug-prone patterns,
+performance traps, and style issues.
+
+:raw-html:`<details><summary markdown="span">Animated demo</summary>`
+
+.. image:: ApplyClangTidyFixInVSCode.gif
+ :align: center
+ :alt: Applying a fix suggested by the compiler
+
+:raw-html:`</details>`
+
+clangd respects your project's ``.clang-tidy`` file which controls the checks
+to run. Not all checks work within clangd. You must pass the ``-clang-tidy``
+flag to enable this feature.
+
+Code completion
+===============
+
+You'll see suggestions as you type based on what methods, variables, etc are
+available in this context.
+
+:raw-html:`<details><summary markdown="span">Screenshot</summary>`
+
+.. image:: CodeCompletionInVSCode.png
+ :align: center
+ :alt: Code completion demonstration
+
+:raw-html:`</details>`
+
+Abbreviating words may help you find the right result faster. If you type in
+``camelCase`` but the function you're looking for is ``snake_case``, that's OK.
+
+Insertion of namespace qualifiers and includes
+----------------------------------------------
+
+**(New in v8)**
+clangd will sometimes suggest results from other files and namespaces. In this
+case the correct qualifier and ``#include`` directive will be inserted.
+
+:raw-html:`<details><summary markdown="span">Animated demo</summary>`
+
+.. image:: CodeCompletionInsertsNamespaceQualifiersInVSCode.gif
+ :align: center
+ :alt: Code completion inserts namespace qualifiers
+
+:raw-html:`</details>`
+
+Signature help
+--------------
+
+Some editors will show you the parameters of the function you're calling, as
+you fill them in.
+
+:raw-html:`<details><summary markdown="span">Animated demo</summary>`
+
+.. image:: SignatureHelpInVSCode.gif
+ :align: center
+ :alt: Demonstration of the signature help feature
+
+:raw-html:`</details>`
+
+Cross-references
+================
+
+The following features let you navigate your codebase.
+
+If there is no project-wide index, cross-references work across the files
+you have opened.
+
+**(New in v9)**
+clangd will also automatically index your whole project.
+
+Find definition/declaration
+---------------------------
+
+Jump to the definition or declaration of a symbol under the cursor.
+
+:raw-html:`<details><summary markdown="span">Animated demo</summary>`
+
+.. image:: GoToDefinitionInVSCode.gif
+ :align: center
+ :alt: Demonstration of the "Go to definition" feature
+
+:raw-html:`</details>`
+
+**(New in v9)**
+Some editors only expose "find definition"; use "find definition" on the
+definition to jump to the declaration.
+
+"Find definition" also works on ``#include`` lines, to jump to the included
+file.
+
+Find references
+---------------
+
+Show all references to a symbol under the cursor.
+
+:raw-html:`<details><summary markdown="span">Animated demo</summary>`
+
+.. image:: FindAllReferencesInVSCode.gif
+ :align: center
+ :alt: Demonstration of the "Find all references" feature
+
+:raw-html:`</details>`
+
+Some editors will automatically highlight local references to the selected
+symbol as you move around a file.
+
+Navigation
+==========
+
+clangd informs the editor of the code structure in the current file.
+Some editors use this to present an outline view:
+
+:raw-html:`<details><summary markdown="span">Screenshot</summary>`
+
+.. image:: OutlineInVSCode.png
+ :align: center
+ :alt: Outline of a file
+
+:raw-html:`</details>`
+
+In VSCode, the outline is also presented as breadcrumbs that allow jumping to a
+symbol within the current file. Searching for symbols within the scope of the
+whole project is also possible.
+
+:raw-html:`<details><summary markdown="span">Animated demo</summary>`
+
+.. image:: NavigationWithBreadcrumbsInVSCode.gif
+ :align: center
+ :alt: Navigation with breadcrumbs
+
+:raw-html:`</details>`
+
+Formatting
+==========
+
+clangd embeds `clang-format <https://clang.llvm.org/docs/ClangFormat.html>`__,
+which can reformat your code: fixing indentation, breaking lines, and reflowing
+comments.
+
+:raw-html:`<details><summary markdown="span">Animated demo</summary>`
+
+.. image:: FormatSelectionInVSCode.gif
+ :align: center
+ :alt: Formatting selected code
+
+:raw-html:`</details>`
+
+clangd respects your project's ``.clang-format`` file which controls styling
+options.
+
+Format-as-you-type is experimental and doesn't work well yet.
+
+Complete list of features
+=========================
+
+Here is a list of features that could be useful for editors, together with the
+implementation status in clangd, and specification in the Language Server
+Protocol.
+
+It is not clear whether or not some of the features mentioned below should be a
+part of the Language Server Protocol; those features might be eventually
+developed outside clangd or become clangd extensions to LSP.
+
++-------------------------------------+------------+----------+
+| C/C++ Editor feature | LSP | Clangd |
++=====================================+============+==========+
+| Formatting | Yes | Yes |
++-------------------------------------+------------+----------+
+| Completion | Yes | Yes |
++-------------------------------------+------------+----------+
+| Diagnostics | Yes | Yes |
++-------------------------------------+------------+----------+
+| Fix-its | Yes | Yes |
++-------------------------------------+------------+----------+
+| Go to Definition | Yes | Yes |
++-------------------------------------+------------+----------+
+| Signature Help | Yes | Yes |
++-------------------------------------+------------+----------+
+| Document Highlights | Yes | Yes |
++-------------------------------------+------------+----------+
+| Rename | Yes | Yes |
++-------------------------------------+------------+----------+
+| Source hover | Yes | Yes |
++-------------------------------------+------------+----------+
+| Find References | Yes | Yes |
++-------------------------------------+------------+----------+
+| Document Symbols | Yes | Yes |
++-------------------------------------+------------+----------+
+| Workspace Symbols | Yes | Yes |
++-------------------------------------+------------+----------+
+| Code Lens | Yes | No |
++-------------------------------------+------------+----------+
+| Code folding | Yes | No |
++-------------------------------------+------------+----------+
+| Extract Local Variable | Yes | No |
++-------------------------------------+------------+----------+
+| Extract Function/Method | Yes | No |
++-------------------------------------+------------+----------+
+| Quick Assist | Yes | No |
++-------------------------------------+------------+----------+
+| Hide Method | Yes | No |
++-------------------------------------+------------+----------+
+| Implement Method | Yes | No |
++-------------------------------------+------------+----------+
+| Gen. Getters/Setters | Yes | No |
++-------------------------------------+------------+----------+
+| Syntax and Semantic Coloring | No | No |
++-------------------------------------+------------+----------+
+| Call hierarchy | No | No |
++-------------------------------------+------------+----------+
+| Type hierarchy | No | No |
++-------------------------------------+------------+----------+
+| Organize Includes | No | No |
++-------------------------------------+------------+----------+
diff --git a/docs/clangd/FindAllReferencesInVSCode.gif b/docs/clangd/FindAllReferencesInVSCode.gif
new file mode 100644
index 00000000..b9eecf3c
--- /dev/null
+++ b/docs/clangd/FindAllReferencesInVSCode.gif
Binary files differ
diff --git a/docs/clangd/FormatSelectionInVSCode.gif b/docs/clangd/FormatSelectionInVSCode.gif
new file mode 100644
index 00000000..1d4be410
--- /dev/null
+++ b/docs/clangd/FormatSelectionInVSCode.gif
Binary files differ
diff --git a/docs/clangd/GoToDefinitionInVSCode.gif b/docs/clangd/GoToDefinitionInVSCode.gif
new file mode 100644
index 00000000..396966f7
--- /dev/null
+++ b/docs/clangd/GoToDefinitionInVSCode.gif
Binary files differ
diff --git a/docs/clangd/Installation.rst b/docs/clangd/Installation.rst
new file mode 100644
index 00000000..1552efce
--- /dev/null
+++ b/docs/clangd/Installation.rst
@@ -0,0 +1,371 @@
+===========================
+Getting started with clangd
+===========================
+
+.. contents::
+
+.. role:: raw-html(raw)
+ :format: html
+
+To use clangd, you need to:
+
+- install clangd,
+- install a plugin for your editor,
+- tell clangd how your project is built.
+
+Installing clangd
+=================
+
+You need a **recent** version of clangd: 7.0 was the first usable release, and
+8.0 is much better.
+
+After installing, ``clangd --version`` should print ``clangd version 7.0.0`` or
+later.
+
+:raw-html:`<details><summary markdown="span">macOS</summary>`
+
+`Homebrew <https://brew.sh>`__ can install clangd along with LLVM:
+
+.. code-block:: console
+
+ $ brew install llvm
+
+If you don't want to use Homebrew, you can download the a binary release of
+LLVM from `releases.llvm.org <http://releases.llvm.org/download.html>`__.
+Alongside ``bin/clangd`` you will need at least ``lib/clang/*/include``:
+
+.. code-block:: console
+
+ $ cp clang+llvm-7.0.0/bin/clangd /usr/local/bin/clangd
+ $ cp -r clang+llvm-7.0.0/lib/clang/ /usr/local/lib/
+
+:raw-html:`</details>`
+
+:raw-html:`<details><summary markdown="span">Windows</summary>`
+
+Download and run the LLVM installer from `releases.llvm.org
+<http://releases.llvm.org/download.html>`__.
+
+:raw-html:`</details>`
+
+:raw-html:`<details><summary markdown="span">Debian/Ubuntu</summary>`
+
+The ``clang-tools`` package usually contains an old version of clangd.
+
+Try to install the latest release (8.0):
+
+.. code-block:: console
+
+ $ sudo apt-get install clang-tools-8
+
+If that is not found, at least ``clang-tools-7`` should be available.
+
+The ``clangd`` executable will be installed as ``/usr/bin/clangd-8``. Make it
+the default ``clangd``:
+
+.. code-block:: console
+
+ $ sudo update-alternatives --install /usr/bin/clangd clangd /usr/bin/clangd-8 100
+
+:raw-html:`</details>`
+
+:raw-html:`<details><summary markdown="span">Other systems</summary>`
+
+Most distributions include clangd in a ``clang-tools`` package, or in the full
+``llvm`` distribution.
+
+For some platforms, binaries are also avaliable at `releases.llvm.org
+<http://releases.llvm.org/download.html>`__.
+
+:raw-html:`</details>`
+
+Editor plugins
+==============
+
+Language Server plugins are available for many editors. In principle, clangd
+should work with any of them, though the feature set and UI may vary.
+
+Here are some plugins we know work well with clangd.
+
+:raw-html:`<details><summary markdown="span">YouCompleteMe for Vim</summary>`
+
+`YouCompleteMe <https://valloric.github.io/YouCompleteMe/>`__ supports clangd.
+However, clangd support is not turned on by default, so you must install
+YouCompleteMe with ``install.py --clangd-completer``.
+
+We recommend changing a couple of YCM's default settings. In ``.vimrc`` add:
+
+::
+
+ " Let clangd fully control code completion
+ let g:ycm_clangd_uses_ycmd_caching = 0
+ " Use installed clangd, not YCM-bundled clangd which doesn't get updates.
+ let g:ycm_clangd_binary_path = exepath("clangd")
+
+You should see errors highlighted and code completions as you type.
+
+.. image:: CodeCompletionInYCM.png
+ :align: center
+ :alt: Code completion in YouCompleteMe
+
+YouCompleteMe supports many of clangd's features:
+
+- code completion,
+- diagnostics and fixes (``:YcmCompleter FixIt``),
+- find declarations, references, and definitions (``:YcmCompleter GoTo`` etc),
+- rename symbol (``:YcmCompleter RefactorRename``).
+
+**Under the hood**
+
+- **Debug logs**: run ``:YcmDebugInfo`` to see clangd status, and ``:YcmToggleLogs``
+ to view clangd's debug logs.
+- **Command-line flags**: Set ``g:ycm_clangd_args`` in ``.vimrc``, e.g.:
+
+ ::
+
+ let g:ycm_clangd_args = ['-log=verbose', '-pretty']
+
+- **Alternate clangd binary**: set ``g:ycm_clangd_binary_path`` in ``.vimrc``.
+
+:raw-html:`</details>`
+
+:raw-html:`<details><summary markdown="span">LanguageClient for Vim and Neovim</summary>`
+
+`LanguageClient-neovim <https://github.com/autozimu/LanguageClient-neovim>`__
+has `instructions for using clangd
+<https://github.com/autozimu/LanguageClient-neovim/wiki/Clangd>`__, and **may**
+be easier to install than YouCompleteMe.
+
+:raw-html:`</details>`
+
+:raw-html:`<details><summary markdown="span">Eglot for Emacs</summary>`
+
+`eglot <https://github.com/joaotavora/eglot>`__ can be configured to work with
+clangd.
+
+Install eglot with ``M-x package-install RET eglot RET``.
+
+Add the following to ``~/.emacs`` to enable clangd:
+
+::
+
+ (require 'eglot)
+ (add-to-list 'eglot-server-programs '((c++-mode c-mode) "clangd"))
+ (add-hook 'c-mode-hook 'eglot-ensure)
+ (add-hook 'c++-mode-hook 'eglot-ensure)
+
+After restarting you should see diagnostics for errors in your code, and ``M-x
+completion-at-point`` should work.
+
+.. image:: DiagnosticsInEmacsEglot.png
+ :align: center
+ :alt: Diagnostics in Emacs
+
+eglot supports many of clangd's features, with caveats:
+
+- code completion, though the interaction is quite poor (even with
+ ``company-mode``, see below),
+- diagnostics and fixes,
+- find definitions and references (``M-x xref-find-definitions`` etc),
+- hover and highlights,
+- code actions (``M-x eglot-code-actions``).
+
+**company-mode**
+
+eglot does have basic integration with company-mode, which provides a more
+fluent completion UI.
+
+You can install it with ``M-x package-install RET company RET``, and enable it
+with ``M-x company-mode``.
+
+**company-clang is enabled by default**, and will interfere with clangd.
+Disable it in ``M-x customize-variable RET company-backends RET``.
+
+Completion still has some major limitations:
+
+- completions are alphabetically sorted, not ranked.
+- only pure-prefix completions are shown - no fuzzy matches.
+- completion triggering seems to be a bit hit-and-miss.
+
+.. image:: CodeCompletionInEmacsCompanyMode.png
+ :align: center
+ :alt: Completion in company-mode
+
+**Under the hood**
+
+- **Debug logs**: available in the ``EGLOT stderr`` buffer.
+- **Command-line flags and alternate binary**: instead of adding ``"clangd"``
+ to ``eglot-server-programs``, add ``("/path/to/clangd" "-log=verbose")`` etc.
+
+:raw-html:`</details>`
+
+:raw-html:`<details><summary markdown="span">Visual Studio Code</summary>`
+
+The official extension is `vscode-clangd
+<https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd>`__
+and can be installed from within VSCode.
+
+Choose **View** --> **Extensions**, then search for "clangd". (Make sure the
+Microsoft C/C++ extension is **not** installed).
+
+After restarting, you should see red underlines underneath errors, and you
+should get rich code completions including e.g. function parameters.
+
+.. image:: CodeCompletionInVSCode.png
+ :align: center
+ :alt: Code completion in VSCode
+
+vscode-clangd has excellent support for all clangd features, including:
+
+- code completion
+- diagnostics and fixes
+- find declarations, references, and definitions
+- find symbol in file (``Ctrl-P @foo``) or workspace (``Ctrl-P #foo``)
+- hover and highlights
+- code actions
+
+**Under the hood**
+
+- **Debug logs**: when clangd is running, you should see "Clang Language
+ Server" in the dropdown of the Output panel (**View** -> **Output**).
+
+- **Command-line flags**: these can be passed in the ``clangd.arguments`` array
+ in your ``settings.json``. (**File** -> **Preferences** -> **Settings**).
+
+- **Alternate clangd binary**: set the ``clangd.path`` string in
+ ``settings.json``.
+
+:raw-html:`</details>`
+
+:raw-html:`<details><summary markdown="span">Sublime Text</summary>`
+
+`tomv564/LSP <https://github.com/tomv564/LSP>`__ works with clangd out of the box.
+
+Select **Tools** --> **Install Package Control** (if you haven't installed it
+yet).
+
+Press ``Ctrl-Shift-P`` and select **Package Control: Install Package**. Select
+**LSP**.
+
+Press ``Ctrl-Shift-P`` and select **LSP: Enable Language Server Globally**.
+Select **clangd**.
+
+Open a C++ file, and you should see diagnostics and completion:
+
+.. image:: CodeCompletionInSublimeText.png
+ :align: center
+ :alt: Code completion in Sublime Text
+
+
+The LSP package has excellent support for all most clangd features, including:
+
+- code completion (a bit noisy due to how snippets are presented)
+- diagnostics and fixes
+- find definition and references
+- hover and highlights
+- code actions
+
+**Under the hood**
+
+Settings can be tweaked under **Preferences** --> **Package Settings** -->
+**LSP**.
+
+- **Debug logs**: add ``"log_stderr": true``
+- **Command-line flags and alternate clangd binary**: inside the ``"clients":
+ {"clangd": { ... } }`` section, add ``"command": ["/path/to/clangd",
+ "-log=verbose"]`` etc.
+
+:raw-html:`</details>`
+
+:raw-html:`<details><summary markdown="span">Other editors</summary>`
+
+There is a directory of LSP clients at `langserver.org
+<http://langserver.org>`__.
+
+A generic client should be configured to run the command ``clangd``, and
+communicate via the language server protocol on standard input/output.
+
+If you don't have strong feelings about an editor, we suggest you try out
+`VSCode <https://code.visualstudio.com/>`__, it has excellent language server
+support and most faithfully demonstrates what clangd can do.
+
+:raw-html:`</details>`
+
+Project setup
+=============
+
+To understand source code in your project, clangd needs to know the build
+flags. (This is just a fact of life in C++, source files are not
+self-contained.)
+
+By default, clangd will assume that source code is built as ``clang
+some_file.cc``, and you'll probably get spurious errors about missing
+``#include``\ d files, etc. There are a couple of ways to fix this.
+
+``compile_commands.json``
+-------------------------
+
+``compile_commands.json`` file provides compile commands for all source files
+in the project. This file is usually generated by the build system, or tools
+integrated with the build system. Clangd will look for this file in the parent
+directories of the files you edit.
+
+:raw-html:`<details><summary markdown="span">CMake-based projects</summary>`
+
+If your project builds with CMake, it can generate ``compile_commands.json``.
+You should enable it with:
+
+::
+
+ $ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1
+
+``compile_commands.json`` will be written to your build directory. You should
+symlink it (or copy it) to the root of your source tree, if they are different.
+
+::
+
+ $ ln -s ~/myproject/compile_commands.json ~/myproject-build/
+
+:raw-html:`</details>`
+
+:raw-html:`<details><summary markdown="span">Other build systems, using Bear</summary>`
+
+`Bear <https://github.com/rizsotto/Bear>`__ is a tool that generates a
+``compile_commands.json`` file by recording a complete build.
+
+For a ``make``-based build, you can run ``make clean; bear make`` to generate the
+file (and run a clean build!)
+
+:raw-html:`</details>`
+
+Other tools can also generate this file. See `the compile_commands.json
+specification <https://clang.llvm.org/docs/JSONCompilationDatabase.html>`__.
+
+``compile_flags.txt``
+---------------------
+
+If all files in a project use the same build flags, you can put those flags,
+one flag per line, in ``compile_flags.txt`` in your source root.
+
+Clangd will assume the compile command is ``clang $FLAGS some_file.cc``.
+
+Creating this file by hand is a reasonable place to start if your project is
+quite simple.
+
+Project-wide Index
+==================
+
+By default clangd only has a view on symbols coming from files you are
+currently editing. You can extend this view to whole project by providing a
+project-wide index to clangd. There are two ways to do this.
+
+- Pass an experimental `-background-index` command line argument. With
+ this feature enabled, clangd incrementally builds an index of projects
+ that you work on and uses the just-built index automatically.
+
+- Generate an index file using `clangd-indexer
+ <https://github.com/llvm/llvm-project/blob/master/clang-tools-extra/clangd/indexer/IndexerMain.cpp>`__
+ Then you can pass generated index file to clangd using
+ `-index-file=/path/to/index_file`. *Note that clangd-indexer isn't
+ included alongside clangd in the Debian clang-tools package. You will
+ likely have to build it from source to use this option.*
diff --git a/docs/clangd/NavigationWithBreadcrumbsInVSCode.gif b/docs/clangd/NavigationWithBreadcrumbsInVSCode.gif
new file mode 100644
index 00000000..499f5c1a
--- /dev/null
+++ b/docs/clangd/NavigationWithBreadcrumbsInVSCode.gif
Binary files differ
diff --git a/docs/clangd/OutlineInVSCode.png b/docs/clangd/OutlineInVSCode.png
new file mode 100644
index 00000000..570a80de
--- /dev/null
+++ b/docs/clangd/OutlineInVSCode.png
Binary files differ
diff --git a/docs/clangd/SignatureHelpInVSCode.gif b/docs/clangd/SignatureHelpInVSCode.gif
new file mode 100644
index 00000000..e5700f22
--- /dev/null
+++ b/docs/clangd/SignatureHelpInVSCode.gif
Binary files differ
diff --git a/docs/clangd/index.rst b/docs/clangd/index.rst
new file mode 100644
index 00000000..46939062
--- /dev/null
+++ b/docs/clangd/index.rst
@@ -0,0 +1,27 @@
+======
+clangd
+======
+
+.. toctree::
+ :maxdepth: 1
+
+ Installation
+ Features
+
+What is clangd?
+===============
+
+clangd understands your C++ code and adds smart features to your editor: code
+completion, compile errors, go-to-definition and more.
+
+clangd is a language server that implements the `Language Server Protocol
+<https://github.com/Microsoft/language-server-protocol>`__; it can work with
+many editors through a plugin. Here's Visual Studio Code with the clangd
+plugin, demonstrating code completion:
+
+.. image:: CodeCompletionInVSCode.png
+ :align: center
+ :alt: Code completion in VSCode
+
+clangd is based on the `Clang <https://clang.llvm.org>`__ C++ compiler, and is
+part of the `LLVM <https://llvm.org>`__ project.
diff --git a/docs/conf.py b/docs/conf.py
index 1b07e8ef..16e81051 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -49,9 +49,9 @@ copyright = u'2007-%d, The Clang Team' % date.today().year
# built documents.
#
# The short version.
-version = '8'
+version = '9'
# The full version, including alpha/beta/rc tags.
-release = '8'
+release = '9'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -121,7 +121,7 @@ html_theme = 'haiku'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = []
+html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
diff --git a/docs/doxygen.cfg.in b/docs/doxygen.cfg.in
index 88095889..fd77fc47 100644
--- a/docs/doxygen.cfg.in
+++ b/docs/doxygen.cfg.in
@@ -752,7 +752,7 @@ INPUT = \
@abs_srcdir@/../clang-reorder-fields \
@abs_srcdir@/../clang-tidy \
@abs_srcdir@/../clangd \
- @abs_srcdir@/../include-fixer \
+ @abs_srcdir@/../clang-include-fixer \
@abs_srcdir@/../modularize \
@abs_srcdir@/../pp-trace \
@abs_srcdir@/../tool-template \
diff --git a/docs/index.rst b/docs/index.rst
index 8e6beb35..0fe98952 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,14 +1,9 @@
-.. Extra Clang Tools documentation master file, created by
- sphinx-quickstart on Wed Feb 13 10:00:18 2013.
- You can adapt this file completely to your liking, but it should at least
- contain the root `toctree` directive.
-
.. title:: Welcome to Extra Clang Tools's documentation!
Introduction
============
Welcome to the clang-tools-extra project which contains extra tools built using
-Clang's tooling API's.
+Clang's tooling APIs.
.. toctree::
:maxdepth: 1
@@ -21,11 +16,12 @@ Contents
:maxdepth: 2
clang-tidy/index
- include-fixer
+ clang-include-fixer
modularize
pp-trace
clang-rename
- clangd
+ clangd/index
+ clangd/DeveloperDocumentation
clang-doc
diff --git a/docs/modularize.rst b/docs/modularize.rst
index 6fe49b42..406ab9ce 100644
--- a/docs/modularize.rst
+++ b/docs/modularize.rst
@@ -42,9 +42,9 @@ To build from source:
Before continuing, take a look at :doc:`ModularizeUsage` to see how to invoke
modularize.
-.. _Getting Started with the LLVM System: http://llvm.org/docs/GettingStarted.html
-.. _Building LLVM with CMake: http://llvm.org/docs/CMake.html
-.. _Clang Tools Documentation: http://clang.llvm.org/docs/ClangTools.html
+.. _Getting Started with the LLVM System: https://llvm.org/docs/GettingStarted.html
+.. _Building LLVM with CMake: https://llvm.org/docs/CMake.html
+.. _Clang Tools Documentation: https://clang.llvm.org/docs/ClangTools.html
What Modularize Checks
======================
@@ -262,4 +262,4 @@ names. If a header has one of these names, an underscore ('_') will be
prepended to the name. For example, if the header name is ``header.h``,
because ``header`` is a keyword, the module name will be ``_header``.
For a list of the module map keywords, please see:
-`Lexical structure <http://clang.llvm.org/docs/Modules.html#lexical-structure>`_
+`Lexical structure <https://clang.llvm.org/docs/Modules.html#lexical-structure>`_
diff --git a/docs/pp-trace.rst b/docs/pp-trace.rst
index b8768ed0..ed01ae94 100644
--- a/docs/pp-trace.rst
+++ b/docs/pp-trace.rst
@@ -11,7 +11,7 @@ pp-trace User's Manual
activity. It's also used as a test of Clang's PPCallbacks interface.
It runs a given source file through the Clang preprocessor, displaying
selected information from callback functions overridden in a
-`PPCallbacks <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html>`_
+`PPCallbacks <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html>`_
derivation. The output is in a high-level YAML format, described in
:ref:`OutputFormat`.
@@ -23,7 +23,7 @@ pp-trace Usage
Command Line Format
-------------------
-``pp-trace [<pp-trace-options>] <source-file> [<front-end-options>]``
+``pp-trace [<pp-trace-options>] <source-file> [-- <front-end-options>]``
``<pp-trace-options>`` is a place-holder for options
specific to pp-trace, which are described below in
@@ -32,7 +32,7 @@ specific to pp-trace, which are described below in
``<source-file>`` specifies the source file to run through the preprocessor.
``<front-end-options>`` is a place-holder for regular
-`Clang Compiler Options <http://clang.llvm.org/docs/UsersManual.html#command-line-options>`_,
+`Clang Compiler Options <https://clang.llvm.org/docs/UsersManual.html#command-line-options>`_,
which must follow the <source-file>.
.. _CommandLineOptions:
@@ -40,12 +40,12 @@ which must follow the <source-file>.
Command Line Options
--------------------
-.. option:: -ignore <callback-name-list>
+.. option:: -callbacks <comma-separated-globs>
- This option specifies a comma-separated list of names of callbacks
- that shouldn't be traced. It can be used to eliminate unwanted
- trace output. The callback names are the name of the actual
- callback function names in the PPCallbacks class:
+ This option specifies a comma-separated list of globs describing the list of
+ callbacks that should be traced. Globs are processed in order of appearance.
+ Positive globs add matched callbacks to the set, netative globs (those with
+ the '-' prefix) remove callacks from the set.
* FileChanged
* FileSkipped
@@ -88,7 +88,7 @@ Command Line Options
pp-trace Output Format
======================
-The pp-trace output is formatted as YAML. See http://yaml.org/ for general
+The pp-trace output is formatted as YAML. See https://yaml.org/ for general
YAML information. It's arranged as a sequence of information about the
callback call, including the callback name and argument information, for
example:::
@@ -150,8 +150,8 @@ Note that in some cases, such as when a structure pointer is an argument
value, only some key member or members are shown to represent the value,
instead of trying to display all members of the structure.
-`FileChanged <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a7cc8cfaf34114fc65e92af621cd6464e>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`FileChanged <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a7cc8cfaf34114fc65e92af621cd6464e>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileChanged is called when the preprocessor enters or exits a file, both the
top level file being compiled, as well as any #include directives. It will
@@ -177,8 +177,8 @@ Example:::
FileType: C_User
PrevFID: (invalid)
-`FileSkipped <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ab5b338a0670188eb05fa7685bbfb5128>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`FileSkipped <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ab5b338a0670188eb05fa7685bbfb5128>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileSkipped is called when a source file is skipped as the result of header
guard optimization.
@@ -200,8 +200,8 @@ Example:::
FilenameTok: "filename.h"
FileType: C_User
-`FileNotFound <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a3045151545f987256bfa8d978916ef00>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`FileNotFound <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a3045151545f987256bfa8d978916ef00>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFound is called when an inclusion directive results in a file-not-found error.
@@ -220,8 +220,8 @@ Example:::
FileName: "/path/filename.h"
RecoveryPath:
-`InclusionDirective <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a557d9738c329793513a6f57d6b60de52>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`InclusionDirective <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a557d9738c329793513a6f57d6b60de52>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
InclusionDirective is called when an inclusion directive of any kind (#include</code>, #import</code>, etc.) has been processed, regardless of whether the inclusion will actually result in an inclusion.
@@ -253,8 +253,8 @@ Example:::
RelativePath: "Input/Level1B.h"
Imported: (null)
-`moduleImport <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#af32dcf1b8b7c179c7fcd3e24e89830fe>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`moduleImport <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#af32dcf1b8b7c179c7fcd3e24e89830fe>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
moduleImport is called when there was an explicit module-import syntax.
@@ -275,8 +275,8 @@ Example:::
Path: [{Name: Level1B, Loc: "d:/Clang/llvmnewmod/tools/clang/tools/extra/test/pp-trace/pp-trace-modules.cpp:4:9"}, {Name: Level2B, Loc: "d:/Clang/llvmnewmod/tools/clang/tools/extra/test/pp-trace/pp-trace-modules.cpp:4:17"}]
Imported: Level2B
-`EndOfMainFile <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a63e170d069e99bc1c9c7ea0f3bed8bcc>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`EndOfMainFile <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a63e170d069e99bc1c9c7ea0f3bed8bcc>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
EndOfMainFile is called when the end of the main file is reached.
@@ -292,8 +292,8 @@ Example:::
- Callback: EndOfMainFile
-`Ident <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a3683f1d1fa513e9b6193d446a5cc2b66>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`Ident <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a3683f1d1fa513e9b6193d446a5cc2b66>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Ident is called when a #ident or #sccs directive is read.
@@ -312,8 +312,8 @@ Example:::
Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-ident.cpp:3:1"
str: "$Id$"
-`PragmaDirective <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a0a2d7a72c62184b3cbde31fb62c6f2f7>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`PragmaDirective <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a0a2d7a72c62184b3cbde31fb62c6f2f7>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PragmaDirective is called when start reading any pragma directive.
@@ -332,8 +332,8 @@ Example:::
Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
Introducer: PIK_HashPragma
-`PragmaComment <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ace0d940fc2c12ab76441466aab58dc37>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`PragmaComment <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ace0d940fc2c12ab76441466aab58dc37>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PragmaComment is called when a #pragma comment directive is read.
@@ -354,8 +354,8 @@ Example:::
Kind: library
Str: kernel32.lib
-`PragmaDetectMismatch <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ab11158c9149fb8ad8af1903f4a6cd65d>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`PragmaDetectMismatch <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ab11158c9149fb8ad8af1903f4a6cd65d>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PragmaDetectMismatch is called when a #pragma detect_mismatch directive is read.
@@ -376,8 +376,8 @@ Example:::
Name: name
Value: value
-`PragmaDebug <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a57cdccb6dcc07e926513ac3d5b121466>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`PragmaDebug <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a57cdccb6dcc07e926513ac3d5b121466>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PragmaDebug is called when a #pragma clang __debug directive is read.
@@ -396,8 +396,8 @@ Example:::
Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
DebugType: warning
-`PragmaMessage <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#abb42935d9a9fd8e2c4f51cfdc4ea2ae1>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`PragmaMessage <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#abb42935d9a9fd8e2c4f51cfdc4ea2ae1>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PragmaMessage is called when a #pragma message directive is read.
@@ -420,8 +420,8 @@ Example:::
Kind: PMK_Message
Str: The message text.
-`PragmaDiagnosticPush <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a0f3ff19762baa38fe6c5c58022d32979>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`PragmaDiagnosticPush <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a0f3ff19762baa38fe6c5c58022d32979>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PragmaDiagnosticPush is called when a #pragma gcc dianostic push directive is read.
@@ -440,7 +440,7 @@ Example:::
Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
Namespace: "GCC"
-`PragmaDiagnosticPop <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ac94d789873122221fba8d76f6c5ea45e>`_ Callback
+`PragmaDiagnosticPop <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ac94d789873122221fba8d76f6c5ea45e>`_ Callback
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PragmaDiagnosticPop is called when a #pragma gcc dianostic pop directive is read.
@@ -460,8 +460,8 @@ Example:::
Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
Namespace: "GCC"
-`PragmaDiagnostic <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#afe7938f38a83cb7b4b25a13edfdd7bdd>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`PragmaDiagnostic <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#afe7938f38a83cb7b4b25a13edfdd7bdd>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PragmaDiagnostic is called when a #pragma gcc dianostic directive is read.
@@ -484,8 +484,8 @@ Example:::
mapping: MAP_WARNING
Str: WarningName
-`PragmaOpenCLExtension <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a92a20a21fadbab4e2c788f4e27fe07e7>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`PragmaOpenCLExtension <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a92a20a21fadbab4e2c788f4e27fe07e7>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PragmaOpenCLExtension is called when OpenCL extension is either disabled or enabled with a pragma.
@@ -508,8 +508,8 @@ Example:::
StateLoc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:18"
State: 1
-`PragmaWarning <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#aa17169d25fa1cf0a6992fc944d1d8730>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`PragmaWarning <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#aa17169d25fa1cf0a6992fc944d1d8730>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PragmaWarning is called when a #pragma warning directive is read.
@@ -530,8 +530,8 @@ Example:::
WarningSpec: disable
Ids: 1,2,3
-`PragmaWarningPush <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ae5626ef70502687a859f323a809ed0b6>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`PragmaWarningPush <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ae5626ef70502687a859f323a809ed0b6>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PragmaWarningPush is called when a #pragma warning(push) directive is read.
@@ -550,8 +550,8 @@ Example:::
Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
Level: 1
-`PragmaWarningPop <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ac98d502af8811b8a6e7342d7cd2b3b95>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`PragmaWarningPop <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ac98d502af8811b8a6e7342d7cd2b3b95>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PragmaWarningPop is called when a #pragma warning(pop) directive is read.
@@ -568,8 +568,8 @@ Example:::
- Callback: PragmaWarningPop
Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-pragma.cpp:3:1"
-`MacroExpands <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a9bc725209d3a071ea649144ab996d515>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`MacroExpands <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a9bc725209d3a071ea649144ab996d515>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
MacroExpands is called when ::HandleMacroExpandedIdentifier when a macro invocation is found.
@@ -592,8 +592,8 @@ Example:::
Range: [(nonfile), (nonfile)]
Args: [a <plus> y, b]
-`MacroDefined <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a8448fc9f96f22ad1b93ff393cffc5a76>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`MacroDefined <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a8448fc9f96f22ad1b93ff393cffc5a76>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
MacroDefined is called when a macro definition is seen.
@@ -612,8 +612,8 @@ Example:::
MacroNameTok: X_IMPL
MacroDirective: MD_Define
-`MacroUndefined <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#acb80fc6171a839db8e290945bf2c9d7a>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`MacroUndefined <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#acb80fc6171a839db8e290945bf2c9d7a>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
MacroUndefined is called when a macro #undef is seen.
@@ -632,8 +632,8 @@ Example:::
MacroNameTok: X_IMPL
MacroDirective: MD_Define
-`Defined <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a3cc2a644533d0e4088a13d2baf90db94>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`Defined <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a3cc2a644533d0e4088a13d2baf90db94>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Defined is called when the 'defined' operator is seen.
@@ -654,8 +654,8 @@ Example:::
MacroDirective: (null)
Range: ["D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:8:5", "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:8:19"]
-`SourceRangeSkipped <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#abdb4ebe11610f079ac33515965794b46>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`SourceRangeSkipped <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#abdb4ebe11610f079ac33515965794b46>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SourceRangeSkipped is called when a source range is skipped.
@@ -672,8 +672,8 @@ Example:::
- Callback: SourceRangeSkipped
Range: [":/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:8:2", ":/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:9:2"]
-`If <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a645edcb0d6becbc6f256f02fd1287778>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`If <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a645edcb0d6becbc6f256f02fd1287778>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If is called when an #if is seen.
@@ -694,8 +694,8 @@ Example:::
ConditionRange: ["D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:8:4", "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:9:1"]
ConditionValue: false
-`Elif <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a180c9e106a28d60a6112e16b1bb8302a>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`Elif <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a180c9e106a28d60a6112e16b1bb8302a>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Elif is called when an #elif is seen.
@@ -718,8 +718,8 @@ Example:::
ConditionValue: false
IfLoc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:8:2"
-`Ifdef <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a0ce79575dda307784fd51a6dd4eec33d>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`Ifdef <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a0ce79575dda307784fd51a6dd4eec33d>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Ifdef is called when an #ifdef is seen.
@@ -740,8 +740,8 @@ Example:::
MacroNameTok: MACRO
MacroDirective: MD_Define
-`Ifndef <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a767af69f1cdcc4cd880fa2ebf77ad3ad>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`Ifndef <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#a767af69f1cdcc4cd880fa2ebf77ad3ad>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Ifndef is called when an #ifndef is seen.
@@ -762,8 +762,8 @@ Example:::
MacroNameTok: MACRO
MacroDirective: MD_Define
-`Else <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ad57f91b6d9c3cbcca326a2bfb49e0314>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`Else <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#ad57f91b6d9c3cbcca326a2bfb49e0314>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Else is called when an #else is seen.
@@ -782,8 +782,8 @@ Example:::
Loc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:10:2"
IfLoc: "D:/Clang/llvm/tools/clang/tools/extra/test/pp-trace/pp-trace-macro.cpp:8:2"
-`Endif <http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#afc62ca1401125f516d58b1629a2093ce>`_ Callback
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`Endif <https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html#afc62ca1401125f516d58b1629a2093ce>`_ Callback
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Endif is called when an #endif is seen.
@@ -819,7 +819,7 @@ To build from source:
* If using CMake, you can also use the ``pp-trace`` target to build
just the pp-trace tool and its dependencies.
-.. _Getting Started with the LLVM System: http://llvm.org/docs/GettingStarted.html
-.. _Building LLVM with CMake: http://llvm.org/docs/CMake.html
-.. _Clang Tools Documentation: http://clang.llvm.org/docs/ClangTools.html
+.. _Getting Started with the LLVM System: https://llvm.org/docs/GettingStarted.html
+.. _Building LLVM with CMake: https://llvm.org/docs/CMake.html
+.. _Clang Tools Documentation: https://clang.llvm.org/docs/ClangTools.html
diff --git a/modularize/CoverageChecker.cpp b/modularize/CoverageChecker.cpp
index 4e2a23ca..8bcb1c75 100644
--- a/modularize/CoverageChecker.cpp
+++ b/modularize/CoverageChecker.cpp
@@ -1,9 +1,8 @@
//===--- extra/module-map-checker/CoverageChecker.cpp -------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/modularize/CoverageChecker.h b/modularize/CoverageChecker.h
index f6c8367a..caafaeb4 100644
--- a/modularize/CoverageChecker.h
+++ b/modularize/CoverageChecker.h
@@ -1,9 +1,8 @@
//===-- CoverageChecker.h - Module map coverage checker -*- C++ -*-------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===--------------------------------------------------------------------===//
///
diff --git a/modularize/Modularize.cpp b/modularize/Modularize.cpp
index 83f23402..59fc5c35 100644
--- a/modularize/Modularize.cpp
+++ b/modularize/Modularize.cpp
@@ -1,9 +1,8 @@
//===- extra/modularize/Modularize.cpp - Check modularized headers --------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/modularize/Modularize.h b/modularize/Modularize.h
index a3f2ad3e..d11a6650 100644
--- a/modularize/Modularize.h
+++ b/modularize/Modularize.h
@@ -1,9 +1,8 @@
//===--- Modularize.h - Common definitions for Modularize -*- C++ -*-----===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===--------------------------------------------------------------------===//
///
diff --git a/modularize/ModularizeUtilities.cpp b/modularize/ModularizeUtilities.cpp
index 85768d5a..c4e13abc 100644
--- a/modularize/ModularizeUtilities.cpp
+++ b/modularize/ModularizeUtilities.cpp
@@ -1,9 +1,8 @@
//===--- extra/modularize/ModularizeUtilities.cpp -------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/modularize/ModularizeUtilities.h b/modularize/ModularizeUtilities.h
index 4ad2b565..1c8c0b6d 100644
--- a/modularize/ModularizeUtilities.h
+++ b/modularize/ModularizeUtilities.h
@@ -1,9 +1,8 @@
//=====-- ModularizeUtilities.h - Utilities for modularize -*- C++ -*-======//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===--------------------------------------------------------------------===//
///
diff --git a/modularize/ModuleAssistant.cpp b/modularize/ModuleAssistant.cpp
index dacb4f91..c34308c2 100644
--- a/modularize/ModuleAssistant.cpp
+++ b/modularize/ModuleAssistant.cpp
@@ -1,9 +1,8 @@
//===--- ModuleAssistant.cpp - Module map generation manager --*- C++ -*---===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/modularize/PreprocessorTracker.cpp b/modularize/PreprocessorTracker.cpp
index 6cb34c7b..445c0c16 100644
--- a/modularize/PreprocessorTracker.cpp
+++ b/modularize/PreprocessorTracker.cpp
@@ -1,9 +1,8 @@
//===--- PreprocessorTracker.cpp - Preprocessor tracking -*- C++ -*------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===--------------------------------------------------------------------===//
//
diff --git a/modularize/PreprocessorTracker.h b/modularize/PreprocessorTracker.h
index a283d9f2..8eec76cd 100644
--- a/modularize/PreprocessorTracker.h
+++ b/modularize/PreprocessorTracker.h
@@ -1,9 +1,8 @@
//===- PreprocessorTracker.h - Tracks preprocessor activities -*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===--------------------------------------------------------------------===//
///
diff --git a/pp-trace/PPCallbacksTracker.cpp b/pp-trace/PPCallbacksTracker.cpp
index 2530dc2d..ae4d5847 100644
--- a/pp-trace/PPCallbacksTracker.cpp
+++ b/pp-trace/PPCallbacksTracker.cpp
@@ -1,9 +1,8 @@
//===--- PPCallbacksTracker.cpp - Preprocessor tracker -*--*---------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
@@ -18,16 +17,17 @@
#include "clang/Lex/MacroArgs.h"
#include "llvm/Support/raw_ostream.h"
-// Utility functions.
+namespace clang {
+namespace pp_trace {
// Get a "file:line:column" source location string.
-static std::string getSourceLocationString(clang::Preprocessor &PP,
- clang::SourceLocation Loc) {
+static std::string getSourceLocationString(Preprocessor &PP,
+ SourceLocation Loc) {
if (Loc.isInvalid())
return std::string("(none)");
if (Loc.isFileID()) {
- clang::PresumedLoc PLoc = PP.getSourceManager().getPresumedLoc(Loc);
+ PresumedLoc PLoc = PP.getSourceManager().getPresumedLoc(Loc);
if (PLoc.isInvalid()) {
return std::string("(invalid)");
@@ -89,19 +89,20 @@ static const char *const MappingStrings[] = { "0", "MAP_IGNORE",
// PPCallbacksTracker functions.
-PPCallbacksTracker::PPCallbacksTracker(llvm::SmallSet<std::string, 4> &Ignore,
+PPCallbacksTracker::PPCallbacksTracker(const FilterType &Filters,
std::vector<CallbackCall> &CallbackCalls,
- clang::Preprocessor &PP)
- : CallbackCalls(CallbackCalls), Ignore(Ignore), PP(PP) {}
+ Preprocessor &PP)
+ : CallbackCalls(CallbackCalls), Filters(Filters), PP(PP) {}
PPCallbacksTracker::~PPCallbacksTracker() {}
// Callback functions.
// Callback invoked whenever a source file is entered or exited.
-void PPCallbacksTracker::FileChanged(
- clang::SourceLocation Loc, clang::PPCallbacks::FileChangeReason Reason,
- clang::SrcMgr::CharacteristicKind FileType, clang::FileID PrevFID) {
+void PPCallbacksTracker::FileChanged(SourceLocation Loc,
+ PPCallbacks::FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID) {
beginCallback("FileChanged");
appendArgument("Loc", Loc);
appendArgument("Reason", Reason, FileChangeReasonStrings);
@@ -111,10 +112,9 @@ void PPCallbacksTracker::FileChanged(
// Callback invoked whenever a source file is skipped as the result
// of header guard optimization.
-void
-PPCallbacksTracker::FileSkipped(const clang::FileEntry &SkippedFile,
- const clang::Token &FilenameTok,
- clang::SrcMgr::CharacteristicKind FileType) {
+void PPCallbacksTracker::FileSkipped(const FileEntry &SkippedFile,
+ const Token &FilenameTok,
+ SrcMgr::CharacteristicKind FileType) {
beginCallback("FileSkipped");
appendArgument("ParentFile", &SkippedFile);
appendArgument("FilenameTok", FilenameTok);
@@ -135,11 +135,10 @@ PPCallbacksTracker::FileNotFound(llvm::StringRef FileName,
// any kind (#include, #import, etc.) has been processed, regardless
// of whether the inclusion will actually result in an inclusion.
void PPCallbacksTracker::InclusionDirective(
- clang::SourceLocation HashLoc, const clang::Token &IncludeTok,
- llvm::StringRef FileName, bool IsAngled,
- clang::CharSourceRange FilenameRange, const clang::FileEntry *File,
+ SourceLocation HashLoc, const Token &IncludeTok, llvm::StringRef FileName,
+ bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
llvm::StringRef SearchPath, llvm::StringRef RelativePath,
- const clang::Module *Imported, clang::SrcMgr::CharacteristicKind FileType) {
+ const Module *Imported, SrcMgr::CharacteristicKind FileType) {
beginCallback("InclusionDirective");
appendArgument("IncludeTok", IncludeTok);
appendFilePathArgument("FileName", FileName);
@@ -153,9 +152,9 @@ void PPCallbacksTracker::InclusionDirective(
// Callback invoked whenever there was an explicit module-import
// syntax.
-void PPCallbacksTracker::moduleImport(clang::SourceLocation ImportLoc,
- clang::ModuleIdPath Path,
- const clang::Module *Imported) {
+void PPCallbacksTracker::moduleImport(SourceLocation ImportLoc,
+ ModuleIdPath Path,
+ const Module *Imported) {
beginCallback("moduleImport");
appendArgument("ImportLoc", ImportLoc);
appendArgument("Path", Path);
@@ -167,24 +166,23 @@ void PPCallbacksTracker::moduleImport(clang::SourceLocation ImportLoc,
void PPCallbacksTracker::EndOfMainFile() { beginCallback("EndOfMainFile"); }
// Callback invoked when a #ident or #sccs directive is read.
-void PPCallbacksTracker::Ident(clang::SourceLocation Loc, llvm::StringRef Str) {
+void PPCallbacksTracker::Ident(SourceLocation Loc, llvm::StringRef Str) {
beginCallback("Ident");
appendArgument("Loc", Loc);
appendArgument("Str", Str);
}
// Callback invoked when start reading any pragma directive.
-void
-PPCallbacksTracker::PragmaDirective(clang::SourceLocation Loc,
- clang::PragmaIntroducerKind Introducer) {
+void PPCallbacksTracker::PragmaDirective(SourceLocation Loc,
+ PragmaIntroducerKind Introducer) {
beginCallback("PragmaDirective");
appendArgument("Loc", Loc);
appendArgument("Introducer", Introducer, PragmaIntroducerKindStrings);
}
// Callback invoked when a #pragma comment directive is read.
-void PPCallbacksTracker::PragmaComment(clang::SourceLocation Loc,
- const clang::IdentifierInfo *Kind,
+void PPCallbacksTracker::PragmaComment(SourceLocation Loc,
+ const IdentifierInfo *Kind,
llvm::StringRef Str) {
beginCallback("PragmaComment");
appendArgument("Loc", Loc);
@@ -194,7 +192,7 @@ void PPCallbacksTracker::PragmaComment(clang::SourceLocation Loc,
// Callback invoked when a #pragma detect_mismatch directive is
// read.
-void PPCallbacksTracker::PragmaDetectMismatch(clang::SourceLocation Loc,
+void PPCallbacksTracker::PragmaDetectMismatch(SourceLocation Loc,
llvm::StringRef Name,
llvm::StringRef Value) {
beginCallback("PragmaDetectMismatch");
@@ -204,7 +202,7 @@ void PPCallbacksTracker::PragmaDetectMismatch(clang::SourceLocation Loc,
}
// Callback invoked when a #pragma clang __debug directive is read.
-void PPCallbacksTracker::PragmaDebug(clang::SourceLocation Loc,
+void PPCallbacksTracker::PragmaDebug(SourceLocation Loc,
llvm::StringRef DebugType) {
beginCallback("PragmaDebug");
appendArgument("Loc", Loc);
@@ -212,9 +210,10 @@ void PPCallbacksTracker::PragmaDebug(clang::SourceLocation Loc,
}
// Callback invoked when a #pragma message directive is read.
-void PPCallbacksTracker::PragmaMessage(
- clang::SourceLocation Loc, llvm::StringRef Namespace,
- clang::PPCallbacks::PragmaMessageKind Kind, llvm::StringRef Str) {
+void PPCallbacksTracker::PragmaMessage(SourceLocation Loc,
+ llvm::StringRef Namespace,
+ PPCallbacks::PragmaMessageKind Kind,
+ llvm::StringRef Str) {
beginCallback("PragmaMessage");
appendArgument("Loc", Loc);
appendArgument("Namespace", Namespace);
@@ -224,7 +223,7 @@ void PPCallbacksTracker::PragmaMessage(
// Callback invoked when a #pragma gcc dianostic push directive
// is read.
-void PPCallbacksTracker::PragmaDiagnosticPush(clang::SourceLocation Loc,
+void PPCallbacksTracker::PragmaDiagnosticPush(SourceLocation Loc,
llvm::StringRef Namespace) {
beginCallback("PragmaDiagnosticPush");
appendArgument("Loc", Loc);
@@ -233,7 +232,7 @@ void PPCallbacksTracker::PragmaDiagnosticPush(clang::SourceLocation Loc,
// Callback invoked when a #pragma gcc dianostic pop directive
// is read.
-void PPCallbacksTracker::PragmaDiagnosticPop(clang::SourceLocation Loc,
+void PPCallbacksTracker::PragmaDiagnosticPop(SourceLocation Loc,
llvm::StringRef Namespace) {
beginCallback("PragmaDiagnosticPop");
appendArgument("Loc", Loc);
@@ -241,9 +240,9 @@ void PPCallbacksTracker::PragmaDiagnosticPop(clang::SourceLocation Loc,
}
// Callback invoked when a #pragma gcc dianostic directive is read.
-void PPCallbacksTracker::PragmaDiagnostic(clang::SourceLocation Loc,
+void PPCallbacksTracker::PragmaDiagnostic(SourceLocation Loc,
llvm::StringRef Namespace,
- clang::diag::Severity Mapping,
+ diag::Severity Mapping,
llvm::StringRef Str) {
beginCallback("PragmaDiagnostic");
appendArgument("Loc", Loc);
@@ -254,9 +253,10 @@ void PPCallbacksTracker::PragmaDiagnostic(clang::SourceLocation Loc,
// Called when an OpenCL extension is either disabled or
// enabled with a pragma.
-void PPCallbacksTracker::PragmaOpenCLExtension(
- clang::SourceLocation NameLoc, const clang::IdentifierInfo *Name,
- clang::SourceLocation StateLoc, unsigned State) {
+void PPCallbacksTracker::PragmaOpenCLExtension(SourceLocation NameLoc,
+ const IdentifierInfo *Name,
+ SourceLocation StateLoc,
+ unsigned State) {
beginCallback("PragmaOpenCLExtension");
appendArgument("NameLoc", NameLoc);
appendArgument("Name", Name);
@@ -265,7 +265,7 @@ void PPCallbacksTracker::PragmaOpenCLExtension(
}
// Callback invoked when a #pragma warning directive is read.
-void PPCallbacksTracker::PragmaWarning(clang::SourceLocation Loc,
+void PPCallbacksTracker::PragmaWarning(SourceLocation Loc,
llvm::StringRef WarningSpec,
llvm::ArrayRef<int> Ids) {
beginCallback("PragmaWarning");
@@ -285,26 +285,40 @@ void PPCallbacksTracker::PragmaWarning(clang::SourceLocation Loc,
}
// Callback invoked when a #pragma warning(push) directive is read.
-void PPCallbacksTracker::PragmaWarningPush(clang::SourceLocation Loc,
- int Level) {
+void PPCallbacksTracker::PragmaWarningPush(SourceLocation Loc, int Level) {
beginCallback("PragmaWarningPush");
appendArgument("Loc", Loc);
appendArgument("Level", Level);
}
// Callback invoked when a #pragma warning(pop) directive is read.
-void PPCallbacksTracker::PragmaWarningPop(clang::SourceLocation Loc) {
+void PPCallbacksTracker::PragmaWarningPop(SourceLocation Loc) {
beginCallback("PragmaWarningPop");
appendArgument("Loc", Loc);
}
+// Callback invoked when a #pragma execution_character_set(push) directive
+// is read.
+void PPCallbacksTracker::PragmaExecCharsetPush(SourceLocation Loc,
+ StringRef Str) {
+ beginCallback("PragmaExecCharsetPush");
+ appendArgument("Loc", Loc);
+ appendArgument("Charset", Str);
+}
+
+// Callback invoked when a #pragma execution_character_set(pop) directive
+// is read.
+void PPCallbacksTracker::PragmaExecCharsetPop(SourceLocation Loc) {
+ beginCallback("PragmaExecCharsetPop");
+ appendArgument("Loc", Loc);
+}
+
// Called by Preprocessor::HandleMacroExpandedIdentifier when a
// macro invocation is found.
-void
-PPCallbacksTracker::MacroExpands(const clang::Token &MacroNameTok,
- const clang::MacroDefinition &MacroDefinition,
- clang::SourceRange Range,
- const clang::MacroArgs *Args) {
+void PPCallbacksTracker::MacroExpands(const Token &MacroNameTok,
+ const MacroDefinition &MacroDefinition,
+ SourceRange Range,
+ const MacroArgs *Args) {
beginCallback("MacroExpands");
appendArgument("MacroNameTok", MacroNameTok);
appendArgument("MacroDefinition", MacroDefinition);
@@ -313,28 +327,26 @@ PPCallbacksTracker::MacroExpands(const clang::Token &MacroNameTok,
}
// Hook called whenever a macro definition is seen.
-void
-PPCallbacksTracker::MacroDefined(const clang::Token &MacroNameTok,
- const clang::MacroDirective *MacroDirective) {
+void PPCallbacksTracker::MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MacroDirective) {
beginCallback("MacroDefined");
appendArgument("MacroNameTok", MacroNameTok);
appendArgument("MacroDirective", MacroDirective);
}
// Hook called whenever a macro #undef is seen.
-void PPCallbacksTracker::MacroUndefined(
- const clang::Token &MacroNameTok,
- const clang::MacroDefinition &MacroDefinition,
- const clang::MacroDirective *Undef) {
+void PPCallbacksTracker::MacroUndefined(const Token &MacroNameTok,
+ const MacroDefinition &MacroDefinition,
+ const MacroDirective *Undef) {
beginCallback("MacroUndefined");
appendArgument("MacroNameTok", MacroNameTok);
appendArgument("MacroDefinition", MacroDefinition);
}
// Hook called whenever the 'defined' operator is seen.
-void PPCallbacksTracker::Defined(const clang::Token &MacroNameTok,
- const clang::MacroDefinition &MacroDefinition,
- clang::SourceRange Range) {
+void PPCallbacksTracker::Defined(const Token &MacroNameTok,
+ const MacroDefinition &MacroDefinition,
+ SourceRange Range) {
beginCallback("Defined");
appendArgument("MacroNameTok", MacroNameTok);
appendArgument("MacroDefinition", MacroDefinition);
@@ -342,15 +354,14 @@ void PPCallbacksTracker::Defined(const clang::Token &MacroNameTok,
}
// Hook called when a source range is skipped.
-void PPCallbacksTracker::SourceRangeSkipped(clang::SourceRange Range,
- clang::SourceLocation EndifLoc) {
+void PPCallbacksTracker::SourceRangeSkipped(SourceRange Range,
+ SourceLocation EndifLoc) {
beginCallback("SourceRangeSkipped");
- appendArgument("Range", clang::SourceRange(Range.getBegin(), EndifLoc));
+ appendArgument("Range", SourceRange(Range.getBegin(), EndifLoc));
}
// Hook called whenever an #if is seen.
-void PPCallbacksTracker::If(clang::SourceLocation Loc,
- clang::SourceRange ConditionRange,
+void PPCallbacksTracker::If(SourceLocation Loc, SourceRange ConditionRange,
ConditionValueKind ConditionValue) {
beginCallback("If");
appendArgument("Loc", Loc);
@@ -359,10 +370,9 @@ void PPCallbacksTracker::If(clang::SourceLocation Loc,
}
// Hook called whenever an #elif is seen.
-void PPCallbacksTracker::Elif(clang::SourceLocation Loc,
- clang::SourceRange ConditionRange,
+void PPCallbacksTracker::Elif(SourceLocation Loc, SourceRange ConditionRange,
ConditionValueKind ConditionValue,
- clang::SourceLocation IfLoc) {
+ SourceLocation IfLoc) {
beginCallback("Elif");
appendArgument("Loc", Loc);
appendArgument("ConditionRange", ConditionRange);
@@ -371,9 +381,8 @@ void PPCallbacksTracker::Elif(clang::SourceLocation Loc,
}
// Hook called whenever an #ifdef is seen.
-void PPCallbacksTracker::Ifdef(clang::SourceLocation Loc,
- const clang::Token &MacroNameTok,
- const clang::MacroDefinition &MacroDefinition) {
+void PPCallbacksTracker::Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MacroDefinition) {
beginCallback("Ifdef");
appendArgument("Loc", Loc);
appendArgument("MacroNameTok", MacroNameTok);
@@ -381,9 +390,8 @@ void PPCallbacksTracker::Ifdef(clang::SourceLocation Loc,
}
// Hook called whenever an #ifndef is seen.
-void PPCallbacksTracker::Ifndef(clang::SourceLocation Loc,
- const clang::Token &MacroNameTok,
- const clang::MacroDefinition &MacroDefinition) {
+void PPCallbacksTracker::Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MacroDefinition) {
beginCallback("Ifndef");
appendArgument("Loc", Loc);
appendArgument("MacroNameTok", MacroNameTok);
@@ -391,16 +399,14 @@ void PPCallbacksTracker::Ifndef(clang::SourceLocation Loc,
}
// Hook called whenever an #else is seen.
-void PPCallbacksTracker::Else(clang::SourceLocation Loc,
- clang::SourceLocation IfLoc) {
+void PPCallbacksTracker::Else(SourceLocation Loc, SourceLocation IfLoc) {
beginCallback("Else");
appendArgument("Loc", Loc);
appendArgument("IfLoc", IfLoc);
}
// Hook called whenever an #endif is seen.
-void PPCallbacksTracker::Endif(clang::SourceLocation Loc,
- clang::SourceLocation IfLoc) {
+void PPCallbacksTracker::Endif(SourceLocation Loc, SourceLocation IfLoc) {
beginCallback("Endif");
appendArgument("Loc", Loc);
appendArgument("IfLoc", IfLoc);
@@ -410,7 +416,14 @@ void PPCallbacksTracker::Endif(clang::SourceLocation Loc,
// Start a new callback.
void PPCallbacksTracker::beginCallback(const char *Name) {
- DisableTrace = Ignore.count(std::string(Name));
+ auto R = CallbackIsEnabled.try_emplace(Name, false);
+ if (R.second) {
+ llvm::StringRef N(Name);
+ for (const std::pair<llvm::GlobPattern, bool> &Filter : Filters)
+ if (Filter.first.match(N))
+ R.first->second = Filter.second;
+ }
+ DisableTrace = !R.first->second;
if (DisableTrace)
return;
CallbackCalls.push_back(CallbackCall(Name));
@@ -433,7 +446,7 @@ void PPCallbacksTracker::appendArgument(const char *Name, int Value) {
void PPCallbacksTracker::appendArgument(const char *Name, const char *Value) {
if (DisableTrace)
return;
- CallbackCalls.back().Arguments.push_back(Argument(Name, Value));
+ CallbackCalls.back().Arguments.push_back(Argument{Name, Value});
}
// Append a string object argument to the top trace item.
@@ -449,8 +462,7 @@ void PPCallbacksTracker::appendArgument(const char *Name,
}
// Append a token argument to the top trace item.
-void PPCallbacksTracker::appendArgument(const char *Name,
- const clang::Token &Value) {
+void PPCallbacksTracker::appendArgument(const char *Name, const Token &Value) {
appendArgument(Name, PP.getSpelling(Value));
}
@@ -461,13 +473,12 @@ void PPCallbacksTracker::appendArgument(const char *Name, int Value,
}
// Append a FileID argument to the top trace item.
-void PPCallbacksTracker::appendArgument(const char *Name, clang::FileID Value) {
+void PPCallbacksTracker::appendArgument(const char *Name, FileID Value) {
if (Value.isInvalid()) {
appendArgument(Name, "(invalid)");
return;
}
- const clang::FileEntry *FileEntry =
- PP.getSourceManager().getFileEntryForID(Value);
+ const FileEntry *FileEntry = PP.getSourceManager().getFileEntryForID(Value);
if (!FileEntry) {
appendArgument(Name, "(getFileEntryForID failed)");
return;
@@ -477,7 +488,7 @@ void PPCallbacksTracker::appendArgument(const char *Name, clang::FileID Value) {
// Append a FileEntry argument to the top trace item.
void PPCallbacksTracker::appendArgument(const char *Name,
- const clang::FileEntry *Value) {
+ const FileEntry *Value) {
if (!Value) {
appendArgument(Name, "(null)");
return;
@@ -487,7 +498,7 @@ void PPCallbacksTracker::appendArgument(const char *Name,
// Append a SourceLocation argument to the top trace item.
void PPCallbacksTracker::appendArgument(const char *Name,
- clang::SourceLocation Value) {
+ SourceLocation Value) {
if (Value.isInvalid()) {
appendArgument(Name, "(invalid)");
return;
@@ -496,8 +507,7 @@ void PPCallbacksTracker::appendArgument(const char *Name,
}
// Append a SourceRange argument to the top trace item.
-void PPCallbacksTracker::appendArgument(const char *Name,
- clang::SourceRange Value) {
+void PPCallbacksTracker::appendArgument(const char *Name, SourceRange Value) {
if (DisableTrace)
return;
if (Value.isInvalid()) {
@@ -513,7 +523,7 @@ void PPCallbacksTracker::appendArgument(const char *Name,
// Append a CharSourceRange argument to the top trace item.
void PPCallbacksTracker::appendArgument(const char *Name,
- clang::CharSourceRange Value) {
+ CharSourceRange Value) {
if (Value.isInvalid()) {
appendArgument(Name, "(invalid)");
return;
@@ -522,8 +532,7 @@ void PPCallbacksTracker::appendArgument(const char *Name,
}
// Append a SourceLocation argument to the top trace item.
-void PPCallbacksTracker::appendArgument(const char *Name,
- clang::ModuleIdPath Value) {
+void PPCallbacksTracker::appendArgument(const char *Name, ModuleIdPath Value) {
if (DisableTrace)
return;
std::string Str;
@@ -542,7 +551,7 @@ void PPCallbacksTracker::appendArgument(const char *Name,
// Append an IdentifierInfo argument to the top trace item.
void PPCallbacksTracker::appendArgument(const char *Name,
- const clang::IdentifierInfo *Value) {
+ const IdentifierInfo *Value) {
if (!Value) {
appendArgument(Name, "(null)");
return;
@@ -552,7 +561,7 @@ void PPCallbacksTracker::appendArgument(const char *Name,
// Append a MacroDirective argument to the top trace item.
void PPCallbacksTracker::appendArgument(const char *Name,
- const clang::MacroDirective *Value) {
+ const MacroDirective *Value) {
if (!Value) {
appendArgument(Name, "(null)");
return;
@@ -562,7 +571,7 @@ void PPCallbacksTracker::appendArgument(const char *Name,
// Append a MacroDefinition argument to the top trace item.
void PPCallbacksTracker::appendArgument(const char *Name,
- const clang::MacroDefinition &Value) {
+ const MacroDefinition &Value) {
std::string Str;
llvm::raw_string_ostream SS(Str);
SS << "[";
@@ -581,7 +590,7 @@ void PPCallbacksTracker::appendArgument(const char *Name,
// Append a MacroArgs argument to the top trace item.
void PPCallbacksTracker::appendArgument(const char *Name,
- const clang::MacroArgs *Value) {
+ const MacroArgs *Value) {
if (!Value) {
appendArgument(Name, "(null)");
return;
@@ -593,18 +602,17 @@ void PPCallbacksTracker::appendArgument(const char *Name,
// Each argument is is a series of contiguous Tokens, terminated by a eof.
// Go through each argument printing tokens until we reach eof.
for (unsigned I = 0; I < Value->getNumMacroArguments(); ++I) {
- const clang::Token *Current = Value->getUnexpArgument(I);
+ const Token *Current = Value->getUnexpArgument(I);
if (I)
SS << ", ";
bool First = true;
- while (Current->isNot(clang::tok::eof)) {
+ while (Current->isNot(tok::eof)) {
if (!First)
SS << " ";
// We need to be careful here because the arguments might not be legal in
// YAML, so we use the token name for anything but identifiers and
// numeric literals.
- if (Current->isAnyIdentifier() ||
- Current->is(clang::tok::numeric_constant)) {
+ if (Current->isAnyIdentifier() || Current->is(tok::numeric_constant)) {
SS << PP.getSpelling(*Current);
} else {
SS << "<" << Current->getName() << ">";
@@ -618,8 +626,7 @@ void PPCallbacksTracker::appendArgument(const char *Name,
}
// Append a Module argument to the top trace item.
-void PPCallbacksTracker::appendArgument(const char *Name,
- const clang::Module *Value) {
+void PPCallbacksTracker::appendArgument(const char *Name, const Module *Value) {
if (!Value) {
appendArgument(Name, "(null)");
return;
@@ -646,9 +653,11 @@ void PPCallbacksTracker::appendFilePathArgument(const char *Name,
}
// Get the raw source string of the range.
-llvm::StringRef
-PPCallbacksTracker::getSourceString(clang::CharSourceRange Range) {
+llvm::StringRef PPCallbacksTracker::getSourceString(CharSourceRange Range) {
const char *B = PP.getSourceManager().getCharacterData(Range.getBegin());
const char *E = PP.getSourceManager().getCharacterData(Range.getEnd());
return llvm::StringRef(B, E - B);
}
+
+} // namespace pp_trace
+} // namespace clang
diff --git a/pp-trace/PPCallbacksTracker.h b/pp-trace/PPCallbacksTracker.h
index b46210ef..1fb5c6f3 100644
--- a/pp-trace/PPCallbacksTracker.h
+++ b/pp-trace/PPCallbacksTracker.h
@@ -1,9 +1,8 @@
//===--- PPCallbacksTracker.h - Preprocessor tracking -----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
@@ -27,18 +26,17 @@
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/GlobPattern.h"
#include <string>
#include <vector>
-/// \brief This class represents one callback function argument by name
-/// and value.
-class Argument {
-public:
- Argument(llvm::StringRef Name, llvm::StringRef Value)
- : Name(Name), Value(Value) {}
- Argument() = default;
+namespace clang {
+namespace pp_trace {
+// This struct represents one callback function argument by name and value.
+struct Argument {
std::string Name;
std::string Value;
};
@@ -54,6 +52,8 @@ public:
std::vector<Argument> Arguments;
};
+using FilterType = std::vector<std::pair<llvm::GlobPattern, bool>>;
+
/// \brief This class overrides the PPCallbacks class for tracking preprocessor
/// activity by means of its callback functions.
///
@@ -71,95 +71,81 @@ public:
/// overidden callback functions are defined. The remaining functions are
/// helpers for recording the trace data, to reduce the coupling between it
/// and the recorded data structure.
-class PPCallbacksTracker : public clang::PPCallbacks {
+class PPCallbacksTracker : public PPCallbacks {
public:
/// \brief Note that all of the arguments are references, and owned
/// by the caller.
- /// \param Ignore - Set of names of callbacks to ignore.
+ /// \param Filters - List of (Glob,Enabled) pairs used to filter callbacks.
/// \param CallbackCalls - Trace buffer.
/// \param PP - The preprocessor. Needed for getting some argument strings.
- PPCallbacksTracker(llvm::SmallSet<std::string, 4> &Ignore,
+ PPCallbacksTracker(const FilterType &Filters,
std::vector<CallbackCall> &CallbackCalls,
- clang::Preprocessor &PP);
+ Preprocessor &PP);
~PPCallbacksTracker() override;
// Overidden callback functions.
- void FileChanged(clang::SourceLocation Loc,
- clang::PPCallbacks::FileChangeReason Reason,
- clang::SrcMgr::CharacteristicKind FileType,
- clang::FileID PrevFID = clang::FileID()) override;
- void FileSkipped(const clang::FileEntry &SkippedFile,
- const clang::Token &FilenameTok,
- clang::SrcMgr::CharacteristicKind FileType) override;
+ void FileChanged(SourceLocation Loc, PPCallbacks::FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID = FileID()) override;
+ void FileSkipped(const FileEntry &SkippedFile, const Token &FilenameTok,
+ SrcMgr::CharacteristicKind FileType) override;
bool FileNotFound(llvm::StringRef FileName,
llvm::SmallVectorImpl<char> &RecoveryPath) override;
- void InclusionDirective(clang::SourceLocation HashLoc,
- const clang::Token &IncludeTok,
+ void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
llvm::StringRef FileName, bool IsAngled,
- clang::CharSourceRange FilenameRange,
- const clang::FileEntry *File,
+ CharSourceRange FilenameRange, const FileEntry *File,
llvm::StringRef SearchPath,
- llvm::StringRef RelativePath,
- const clang::Module *Imported,
- clang::SrcMgr::CharacteristicKind FileType) override;
- void moduleImport(clang::SourceLocation ImportLoc, clang::ModuleIdPath Path,
- const clang::Module *Imported) override;
+ llvm::StringRef RelativePath, const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override;
+ void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
+ const Module *Imported) override;
void EndOfMainFile() override;
- void Ident(clang::SourceLocation Loc, llvm::StringRef str) override;
- void PragmaDirective(clang::SourceLocation Loc,
- clang::PragmaIntroducerKind Introducer) override;
- void PragmaComment(clang::SourceLocation Loc,
- const clang::IdentifierInfo *Kind,
+ void Ident(SourceLocation Loc, llvm::StringRef str) override;
+ void PragmaDirective(SourceLocation Loc,
+ PragmaIntroducerKind Introducer) override;
+ void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
llvm::StringRef Str) override;
- void PragmaDetectMismatch(clang::SourceLocation Loc, llvm::StringRef Name,
+ void PragmaDetectMismatch(SourceLocation Loc, llvm::StringRef Name,
llvm::StringRef Value) override;
- void PragmaDebug(clang::SourceLocation Loc,
- llvm::StringRef DebugType) override;
- void PragmaMessage(clang::SourceLocation Loc, llvm::StringRef Namespace,
- clang::PPCallbacks::PragmaMessageKind Kind,
+ void PragmaDebug(SourceLocation Loc, llvm::StringRef DebugType) override;
+ void PragmaMessage(SourceLocation Loc, llvm::StringRef Namespace,
+ PPCallbacks::PragmaMessageKind Kind,
llvm::StringRef Str) override;
- void PragmaDiagnosticPush(clang::SourceLocation Loc,
+ void PragmaDiagnosticPush(SourceLocation Loc,
llvm::StringRef Namespace) override;
- void PragmaDiagnosticPop(clang::SourceLocation Loc,
+ void PragmaDiagnosticPop(SourceLocation Loc,
llvm::StringRef Namespace) override;
- void PragmaDiagnostic(clang::SourceLocation Loc, llvm::StringRef Namespace,
- clang::diag::Severity mapping,
- llvm::StringRef Str) override;
- void PragmaOpenCLExtension(clang::SourceLocation NameLoc,
- const clang::IdentifierInfo *Name,
- clang::SourceLocation StateLoc,
- unsigned State) override;
- void PragmaWarning(clang::SourceLocation Loc, llvm::StringRef WarningSpec,
+ void PragmaDiagnostic(SourceLocation Loc, llvm::StringRef Namespace,
+ diag::Severity mapping, llvm::StringRef Str) override;
+ void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *Name,
+ SourceLocation StateLoc, unsigned State) override;
+ void PragmaWarning(SourceLocation Loc, llvm::StringRef WarningSpec,
llvm::ArrayRef<int> Ids) override;
- void PragmaWarningPush(clang::SourceLocation Loc, int Level) override;
- void PragmaWarningPop(clang::SourceLocation Loc) override;
- void MacroExpands(const clang::Token &MacroNameTok,
- const clang::MacroDefinition &MD, clang::SourceRange Range,
- const clang::MacroArgs *Args) override;
- void MacroDefined(const clang::Token &MacroNameTok,
- const clang::MacroDirective *MD) override;
- void MacroUndefined(const clang::Token &MacroNameTok,
- const clang::MacroDefinition &MD,
- const clang::MacroDirective *Undef) override;
- void Defined(const clang::Token &MacroNameTok,
- const clang::MacroDefinition &MD,
- clang::SourceRange Range) override;
- void SourceRangeSkipped(clang::SourceRange Range,
- clang::SourceLocation EndifLoc) override;
- void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
+ void PragmaWarningPush(SourceLocation Loc, int Level) override;
+ void PragmaWarningPop(SourceLocation Loc) override;
+ void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) override;
+ void PragmaExecCharsetPop(SourceLocation Loc) override;
+ void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
+ SourceRange Range, const MacroArgs *Args) override;
+ void MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) override;
+ void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,
+ const MacroDirective *Undef) override;
+ void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
+ SourceRange Range) override;
+ void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override;
+ void If(SourceLocation Loc, SourceRange ConditionRange,
ConditionValueKind ConditionValue) override;
- void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
- ConditionValueKind ConditionValue, clang::SourceLocation IfLoc) override;
- void Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
- const clang::MacroDefinition &MD) override;
- void Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
- const clang::MacroDefinition &MD) override;
- void Else(clang::SourceLocation Loc,
- clang::SourceLocation IfLoc) override;
- void Endif(clang::SourceLocation Loc,
- clang::SourceLocation IfLoc) override;
+ void Elif(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue, SourceLocation IfLoc) override;
+ void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+ void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+ void Else(SourceLocation Loc, SourceLocation IfLoc) override;
+ void Endif(SourceLocation Loc, SourceLocation IfLoc) override;
// Helper functions.
@@ -185,43 +171,43 @@ public:
void appendArgument(const char *Name, const std::string &Value);
/// \brief Append a token argument to the top trace item.
- void appendArgument(const char *Name, const clang::Token &Value);
+ void appendArgument(const char *Name, const Token &Value);
/// \brief Append an enum argument to the top trace item.
void appendArgument(const char *Name, int Value, const char *const Strings[]);
/// \brief Append a FileID argument to the top trace item.
- void appendArgument(const char *Name, clang::FileID Value);
+ void appendArgument(const char *Name, FileID Value);
/// \brief Append a FileEntry argument to the top trace item.
- void appendArgument(const char *Name, const clang::FileEntry *Value);
+ void appendArgument(const char *Name, const FileEntry *Value);
/// \brief Append a SourceLocation argument to the top trace item.
- void appendArgument(const char *Name, clang::SourceLocation Value);
+ void appendArgument(const char *Name, SourceLocation Value);
/// \brief Append a SourceRange argument to the top trace item.
- void appendArgument(const char *Name, clang::SourceRange Value);
+ void appendArgument(const char *Name, SourceRange Value);
/// \brief Append a CharSourceRange argument to the top trace item.
- void appendArgument(const char *Name, clang::CharSourceRange Value);
+ void appendArgument(const char *Name, CharSourceRange Value);
/// \brief Append a ModuleIdPath argument to the top trace item.
- void appendArgument(const char *Name, clang::ModuleIdPath Value);
+ void appendArgument(const char *Name, ModuleIdPath Value);
/// \brief Append an IdentifierInfo argument to the top trace item.
- void appendArgument(const char *Name, const clang::IdentifierInfo *Value);
+ void appendArgument(const char *Name, const IdentifierInfo *Value);
/// \brief Append a MacroDirective argument to the top trace item.
- void appendArgument(const char *Name, const clang::MacroDirective *Value);
+ void appendArgument(const char *Name, const MacroDirective *Value);
/// \brief Append a MacroDefinition argument to the top trace item.
- void appendArgument(const char *Name, const clang::MacroDefinition &Value);
+ void appendArgument(const char *Name, const MacroDefinition &Value);
/// \brief Append a MacroArgs argument to the top trace item.
- void appendArgument(const char *Name, const clang::MacroArgs *Value);
+ void appendArgument(const char *Name, const MacroArgs *Value);
/// \brief Append a Module argument to the top trace item.
- void appendArgument(const char *Name, const clang::Module *Value);
+ void appendArgument(const char *Name, const Module *Value);
/// \brief Append a double-quoted argument to the top trace item.
void appendQuotedArgument(const char *Name, const std::string &Value);
@@ -230,20 +216,26 @@ public:
void appendFilePathArgument(const char *Name, llvm::StringRef Value);
/// \brief Get the raw source string of the range.
- llvm::StringRef getSourceString(clang::CharSourceRange Range);
+ llvm::StringRef getSourceString(CharSourceRange Range);
/// \brief Callback trace information.
/// We use a reference so the trace will be preserved for the caller
/// after this object is destructed.
std::vector<CallbackCall> &CallbackCalls;
- /// \brief Names of callbacks to ignore.
- llvm::SmallSet<std::string, 4> &Ignore;
+ // List of (Glob,Enabled) pairs used to filter callbacks.
+ const FilterType &Filters;
+
+ // Whether a callback should be printed.
+ llvm::StringMap<bool> CallbackIsEnabled;
/// \brief Inhibit trace while this is set.
bool DisableTrace;
- clang::Preprocessor &PP;
+ Preprocessor &PP;
};
+} // namespace pp_trace
+} // namespace clang
+
#endif // PPTRACE_PPCALLBACKSTRACKER_H
diff --git a/pp-trace/PPTrace.cpp b/pp-trace/PPTrace.cpp
index 08e0f514..5155a8b2 100644
--- a/pp-trace/PPTrace.cpp
+++ b/pp-trace/PPTrace.cpp
@@ -1,9 +1,8 @@
//===--- tools/pp-trace/PPTrace.cpp - Clang preprocessor tracer -----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -18,44 +17,22 @@
//
// The pp-trace tool supports the following general command line format:
//
-// pp-trace [pp-trace options] (source file) [compiler options]
+// pp-trace [options] file... [-- compiler options]
//
// Basically you put the pp-trace options first, then the source file or files,
-// and then any options you want to pass to the compiler.
-//
-// These are the pp-trace options:
-//
-// -ignore (callback list) Don't display output for a comma-separated
-// list of callbacks, i.e.:
-// -ignore "FileChanged,InclusionDirective"
-//
-// -output (file) Output trace to the given file in a YAML
-// format, e.g.:
-//
-// ---
-// - Callback: Name
-// Argument1: Value1
-// Argument2: Value2
-// (etc.)
-// ...
-//
-// Future Directions:
-//
-// 1. Add option opposite to "-ignore" that specifys a comma-separated option
-// list of callbacs. Perhaps "-only" or "-exclusive".
+// and then -- followed by any options you want to pass to the compiler.
//
//===----------------------------------------------------------------------===//
#include "PPCallbacksTracker.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Driver/Options.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Execution.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
@@ -63,168 +40,126 @@
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/GlobPattern.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ToolOutputFile.h"
-#include <algorithm>
-#include <fstream>
-#include <iterator>
+#include "llvm/Support/WithColor.h"
#include <string>
#include <vector>
-using namespace clang;
-using namespace clang::tooling;
using namespace llvm;
-// Options:
+namespace clang {
+namespace pp_trace {
-// Collect the source files.
-static cl::list<std::string> SourcePaths(cl::Positional,
- cl::desc("<source0> [... <sourceN>]"),
- cl::OneOrMore);
+static cl::OptionCategory Cat("pp-trace options");
-// Option to specify a list or one or more callback names to ignore.
-static cl::opt<std::string> IgnoreCallbacks(
- "ignore", cl::init(""),
- cl::desc("Ignore callbacks, i.e. \"Callback1, Callback2...\"."));
+static cl::opt<std::string> Callbacks(
+ "callbacks", cl::init("*"),
+ cl::desc("Comma-separated list of globs describing the list of callbacks "
+ "to output. Globs are processed in order of appearance. Globs "
+ "with the '-' prefix remove callbacks from the set. e.g. "
+ "'*,-Macro*'."),
+ cl::cat(Cat));
-// Option to specify the trace output file name.
static cl::opt<std::string> OutputFileName(
- "output", cl::init(""),
- cl::desc("Output trace to the given file name or '-' for stdout."));
+ "output", cl::init("-"),
+ cl::desc("Output trace to the given file name or '-' for stdout."),
+ cl::cat(Cat));
-// Collect all other arguments, which will be passed to the front end.
-static cl::list<std::string>
- CC1Arguments(cl::ConsumeAfter,
- cl::desc("<arguments to be passed to front end>..."));
-
-// Frontend action stuff:
+LLVM_ATTRIBUTE_NORETURN static void error(Twine Message) {
+ WithColor::error() << Message << '\n';
+ exit(1);
+}
namespace {
-// Consumer is responsible for setting up the callbacks.
-class PPTraceConsumer : public ASTConsumer {
-public:
- PPTraceConsumer(SmallSet<std::string, 4> &Ignore,
- std::vector<CallbackCall> &CallbackCalls, Preprocessor &PP) {
- // PP takes ownership.
- PP.addPPCallbacks(llvm::make_unique<PPCallbacksTracker>(Ignore,
- CallbackCalls, PP));
- }
-};
-class PPTraceAction : public SyntaxOnlyAction {
+class PPTraceAction : public ASTFrontendAction {
public:
- PPTraceAction(SmallSet<std::string, 4> &Ignore,
- std::vector<CallbackCall> &CallbackCalls)
- : Ignore(Ignore), CallbackCalls(CallbackCalls) {}
+ PPTraceAction(const FilterType &Filters, raw_ostream &OS)
+ : Filters(Filters), OS(OS) {}
protected:
- std::unique_ptr<clang::ASTConsumer>
- CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override {
- return llvm::make_unique<PPTraceConsumer>(Ignore, CallbackCalls,
- CI.getPreprocessor());
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override {
+ Preprocessor &PP = CI.getPreprocessor();
+ PP.addPPCallbacks(
+ llvm::make_unique<PPCallbacksTracker>(Filters, CallbackCalls, PP));
+ return llvm::make_unique<ASTConsumer>();
+ }
+
+ void EndSourceFileAction() override {
+ OS << "---\n";
+ for (const CallbackCall &Callback : CallbackCalls) {
+ OS << "- Callback: " << Callback.Name << "\n";
+ for (const Argument &Arg : Callback.Arguments)
+ OS << " " << Arg.Name << ": " << Arg.Value << "\n";
+ }
+ OS << "...\n";
+
+ CallbackCalls.clear();
}
private:
- SmallSet<std::string, 4> &Ignore;
- std::vector<CallbackCall> &CallbackCalls;
+ const FilterType &Filters;
+ raw_ostream &OS;
+ std::vector<CallbackCall> CallbackCalls;
};
-class PPTraceFrontendActionFactory : public FrontendActionFactory {
+class PPTraceFrontendActionFactory : public tooling::FrontendActionFactory {
public:
- PPTraceFrontendActionFactory(SmallSet<std::string, 4> &Ignore,
- std::vector<CallbackCall> &CallbackCalls)
- : Ignore(Ignore), CallbackCalls(CallbackCalls) {}
+ PPTraceFrontendActionFactory(const FilterType &Filters, raw_ostream &OS)
+ : Filters(Filters), OS(OS) {}
- PPTraceAction *create() override {
- return new PPTraceAction(Ignore, CallbackCalls);
- }
+ PPTraceAction *create() override { return new PPTraceAction(Filters, OS); }
private:
- SmallSet<std::string, 4> &Ignore;
- std::vector<CallbackCall> &CallbackCalls;
+ const FilterType &Filters;
+ raw_ostream &OS;
};
} // namespace
-
-// Output the trace given its data structure and a stream.
-static int outputPPTrace(std::vector<CallbackCall> &CallbackCalls,
- llvm::raw_ostream &OS) {
- // Mark start of document.
- OS << "---\n";
-
- for (std::vector<CallbackCall>::const_iterator I = CallbackCalls.begin(),
- E = CallbackCalls.end();
- I != E; ++I) {
- const CallbackCall &Callback = *I;
- OS << "- Callback: " << Callback.Name << "\n";
-
- for (auto AI = Callback.Arguments.begin(), AE = Callback.Arguments.end();
- AI != AE; ++AI) {
- const Argument &Arg = *AI;
- OS << " " << Arg.Name << ": " << Arg.Value << "\n";
- }
- }
-
- // Mark end of document.
- OS << "...\n";
-
- return 0;
-}
-
-// Program entry point.
-int main(int Argc, const char **Argv) {
-
- // Parse command line.
- cl::ParseCommandLineOptions(Argc, Argv, "pp-trace.\n");
-
+} // namespace pp_trace
+} // namespace clang
+
+int main(int argc, const char **argv) {
+ using namespace clang::pp_trace;
+ InitLLVM X(argc, argv);
+ auto OptionsParser = clang::tooling::CommonOptionsParser::create(
+ argc, argv, Cat, llvm::cl::ZeroOrMore);
+ if (!OptionsParser)
+ error(toString(OptionsParser.takeError()));
// Parse the IgnoreCallbacks list into strings.
- SmallVector<StringRef, 32> IgnoreCallbacksStrings;
- StringRef(IgnoreCallbacks).split(IgnoreCallbacksStrings, ",",
- /*MaxSplit=*/ -1, /*KeepEmpty=*/false);
- SmallSet<std::string, 4> Ignore;
- for (SmallVector<StringRef, 32>::iterator I = IgnoreCallbacksStrings.begin(),
- E = IgnoreCallbacksStrings.end();
- I != E; ++I)
- Ignore.insert(*I);
-
- // Create the compilation database.
- SmallString<256> PathBuf;
- sys::fs::current_path(PathBuf);
- std::unique_ptr<CompilationDatabase> Compilations;
- Compilations.reset(
- new FixedCompilationDatabase(Twine(PathBuf), CC1Arguments));
-
- // Store the callback trace information here.
- std::vector<CallbackCall> CallbackCalls;
+ SmallVector<StringRef, 32> Patterns;
+ FilterType Filters;
+ StringRef(Callbacks).split(Patterns, ",",
+ /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ for (StringRef Pattern : Patterns) {
+ Pattern = Pattern.trim();
+ bool Enabled = !Pattern.consume_front("-");
+ Expected<GlobPattern> Pat = GlobPattern::create(Pattern);
+ if (Pat)
+ Filters.emplace_back(std::move(*Pat), Enabled);
+ else
+ error(toString(Pat.takeError()));
+ }
// Create the tool and run the compilation.
- ClangTool Tool(*Compilations, SourcePaths);
- PPTraceFrontendActionFactory Factory(Ignore, CallbackCalls);
+ clang::tooling::ClangTool Tool(OptionsParser->getCompilations(),
+ OptionsParser->getSourcePathList());
+
+ std::error_code EC;
+ llvm::ToolOutputFile Out(OutputFileName, EC, llvm::sys::fs::F_Text);
+ if (EC)
+ error(EC.message());
+ PPTraceFrontendActionFactory Factory(Filters, Out.os());
int HadErrors = Tool.run(&Factory);
// If we had errors, exit early.
if (HadErrors)
return HadErrors;
- // Do the output.
- if (!OutputFileName.size()) {
- HadErrors = outputPPTrace(CallbackCalls, llvm::outs());
- } else {
- // Set up output file.
- std::error_code EC;
- llvm::ToolOutputFile Out(OutputFileName, EC, llvm::sys::fs::F_Text);
- if (EC) {
- llvm::errs() << "pp-trace: error creating " << OutputFileName << ":"
- << EC.message() << "\n";
- return 1;
- }
-
- HadErrors = outputPPTrace(CallbackCalls, Out.os());
-
- // Tell ToolOutputFile that we want to keep the file.
- if (HadErrors == 0)
- Out.keep();
- }
+ Out.keep();
- return HadErrors;
+ return 0;
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index adeb0368..a2cedeaa 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -15,18 +15,20 @@ endif ()
string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} CLANG_TOOLS_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR})
-llvm_canonicalize_cmake_booleans(
- CLANG_ENABLE_STATIC_ANALYZER
- CLANGD_BUILD_XPC_SUPPORT)
+llvm_canonicalize_cmake_booleans(CLANG_ENABLE_STATIC_ANALYZER)
configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
- ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py
+ MAIN_CONFIG
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py
)
configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in
- ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg
+ ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg.py
+ MAIN_CONFIG
+ ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.cfg.py
)
option(CLANG_TOOLS_TEST_USE_VG "Run Clang tools' tests under Valgrind" OFF)
@@ -59,39 +61,23 @@ set(CLANG_TOOLS_TEST_DEPS
# For the clang-tidy libclang integration test.
c-index-test
# clang-tidy tests require it.
- clang-headers
+ clang-resource-headers
clang-tidy
+ # Clang-tidy tests need clang for building modules.
+ clang
)
-if(CLANGD_BUILD_XPC_SUPPORT)
- list(APPEND CLANG_TOOLS_TEST_DEPS clangd-xpc-test-client)
-endif()
-
-set(CLANGD_TEST_DEPS
- clangd
- ClangdTests
- # clangd-related tools which don't have tests, add them to the test to make
- # sure we don't introduce new changes that break their compilations.
- clangd-indexer
- dexp
- )
-
# Add lit test dependencies.
set(LLVM_UTILS_DEPS
FileCheck count not
)
foreach(dep ${LLVM_UTILS_DEPS})
if(TARGET ${dep})
- list(APPEND CLANGD_TEST_DEPS ${dep})
+ list(APPEND CLANG_TOOLS_TEST_DEPS ${dep})
endif()
endforeach()
-foreach(clangd_dep ${CLANGD_TEST_DEPS})
- list(APPEND CLANG_TOOLS_TEST_DEPS
- ${clangd_dep})
-endforeach()
-
add_lit_testsuite(check-clang-tools "Running the Clang extra tools' regression tests"
${CMAKE_CURRENT_BINARY_DIR}
DEPENDS ${CLANG_TOOLS_TEST_DEPS}
@@ -99,15 +85,3 @@ add_lit_testsuite(check-clang-tools "Running the Clang extra tools' regression t
)
set_target_properties(check-clang-tools PROPERTIES FOLDER "Clang extra tools' tests")
-
-# Setup an individual test for building and testing clangd-only stuff.
-# Note: all clangd tests have been covered in check-clang-tools, this is a
-# convenient target for clangd developers.
-# Exclude check-clangd from check-all.
-set(EXCLUDE_FROM_ALL ON)
-add_lit_testsuite(check-clangd "Running the Clangd regression tests"
- ${CMAKE_CURRENT_BINARY_DIR}/Unit/clangd;${CMAKE_CURRENT_BINARY_DIR}/clangd
- DEPENDS ${CLANGD_TEST_DEPS}
-)
-set_target_properties(check-clangd PROPERTIES FOLDER "Clangd tests")
-set(EXCLUDE_FROM_ALL OFF)
diff --git a/test/Unit/lit.cfg b/test/Unit/lit.cfg.py
index b40e1cae..b40e1cae 100644
--- a/test/Unit/lit.cfg
+++ b/test/Unit/lit.cfg.py
diff --git a/test/Unit/lit.site.cfg.in b/test/Unit/lit.site.cfg.py.in
index 69a5cd5d..dc7ee330 100644
--- a/test/Unit/lit.site.cfg.in
+++ b/test/Unit/lit.site.cfg.py.in
@@ -6,4 +6,4 @@ config.llvm_libs_dir = "@LLVM_LIBS_DIR@"
config.shlibdir = "@SHLIBDIR@"
config.target_triple = "@TARGET_TRIPLE@"
-lit_config.load_config(config, "@CLANG_TOOLS_SOURCE_DIR@/test/Unit/lit.cfg")
+lit_config.load_config(config, "@CLANG_TOOLS_SOURCE_DIR@/test/Unit/lit.cfg.py")
diff --git a/test/clang-apply-replacements/Inputs/basic/file1.yaml b/test/clang-apply-replacements/Inputs/basic/file1.yaml
index 3a5375e6..0703f62c 100644
--- a/test/clang-apply-replacements/Inputs/basic/file1.yaml
+++ b/test/clang-apply-replacements/Inputs/basic/file1.yaml
@@ -2,24 +2,25 @@
MainSourceFile: source1.cpp
Diagnostics:
- DiagnosticName: test-basic
- Message: Fix
- FilePath: $(path)/basic.h
- FileOffset: 242
- Replacements:
- - FilePath: $(path)/basic.h
- Offset: 242
- Length: 26
- ReplacementText: 'auto & elem : ints'
- - FilePath: $(path)/basic.h
- Offset: 276
- Length: 22
- ReplacementText: ''
- - FilePath: $(path)/basic.h
- Offset: 298
- Length: 1
- ReplacementText: elem
- - FilePath: $(path)/../basic/basic.h
- Offset: 148
- Length: 0
- ReplacementText: 'override '
+ DiagnosticMessage:
+ Message: Fix
+ FilePath: $(path)/basic.h
+ FileOffset: 242
+ Replacements:
+ - FilePath: $(path)/basic.h
+ Offset: 242
+ Length: 26
+ ReplacementText: 'auto & elem : ints'
+ - FilePath: $(path)/basic.h
+ Offset: 276
+ Length: 22
+ ReplacementText: ''
+ - FilePath: $(path)/basic.h
+ Offset: 298
+ Length: 1
+ ReplacementText: elem
+ - FilePath: $(path)/../basic/basic.h
+ Offset: 148
+ Length: 0
+ ReplacementText: 'override '
...
diff --git a/test/clang-apply-replacements/Inputs/basic/file2.yaml b/test/clang-apply-replacements/Inputs/basic/file2.yaml
index 8f6f65ad..de99d860 100644
--- a/test/clang-apply-replacements/Inputs/basic/file2.yaml
+++ b/test/clang-apply-replacements/Inputs/basic/file2.yaml
@@ -2,12 +2,13 @@
MainSourceFile: source2.cpp
Diagnostics:
- DiagnosticName: test-basic
- Message: Fix
- FilePath: $(path)/basic.h
- FileOffset: 148
- Replacements:
- - FilePath: $(path)/../basic/basic.h
- Offset: 298
- Length: 1
- ReplacementText: elem
+ DiagnosticMessage:
+ Message: Fix
+ FilePath: $(path)/basic.h
+ FileOffset: 148
+ Replacements:
+ - FilePath: $(path)/../basic/basic.h
+ Offset: 298
+ Length: 1
+ ReplacementText: elem
...
diff --git a/test/clang-apply-replacements/Inputs/conflict/file1.yaml b/test/clang-apply-replacements/Inputs/conflict/file1.yaml
index 85052736..8dccc567 100644
--- a/test/clang-apply-replacements/Inputs/conflict/file1.yaml
+++ b/test/clang-apply-replacements/Inputs/conflict/file1.yaml
@@ -2,20 +2,21 @@
MainSourceFile: source1.cpp
Diagnostics:
- DiagnosticName: test-conflict
- Message: Fix
- FilePath: $(path)/common.h
- FileOffset: 106
- Replacements:
- - FilePath: $(path)/common.h
- Offset: 106
- Length: 26
- ReplacementText: 'auto & i : ints'
- - FilePath: $(path)/common.h
- Offset: 140
- Length: 7
- ReplacementText: i
- - FilePath: $(path)/common.h
- Offset: 160
- Length: 12
- ReplacementText: ''
+ DiagnosticMessage:
+ Message: Fix
+ FilePath: $(path)/common.h
+ FileOffset: 106
+ Replacements:
+ - FilePath: $(path)/common.h
+ Offset: 106
+ Length: 26
+ ReplacementText: 'auto & i : ints'
+ - FilePath: $(path)/common.h
+ Offset: 140
+ Length: 7
+ ReplacementText: i
+ - FilePath: $(path)/common.h
+ Offset: 160
+ Length: 12
+ ReplacementText: ''
...
diff --git a/test/clang-apply-replacements/Inputs/conflict/file2.yaml b/test/clang-apply-replacements/Inputs/conflict/file2.yaml
index 32b35acf..d7339662 100644
--- a/test/clang-apply-replacements/Inputs/conflict/file2.yaml
+++ b/test/clang-apply-replacements/Inputs/conflict/file2.yaml
@@ -2,20 +2,21 @@
MainSourceFile: source2.cpp
Diagnostics:
- DiagnosticName: test-conflict
- Message: Fix
- FilePath: $(path)/common.h
- FileOffset: 106
- Replacements:
- - FilePath: $(path)/common.h
- Offset: 106
- Length: 26
- ReplacementText: 'int & elem : ints'
- - FilePath: $(path)/common.h
- Offset: 140
- Length: 7
- ReplacementText: elem
- - FilePath: $(path)/common.h
- Offset: 169
- Length: 1
- ReplacementText: nullptr
+ DiagnosticMessage:
+ Message: Fix
+ FilePath: $(path)/common.h
+ FileOffset: 106
+ Replacements:
+ - FilePath: $(path)/common.h
+ Offset: 106
+ Length: 26
+ ReplacementText: 'int & elem : ints'
+ - FilePath: $(path)/common.h
+ Offset: 140
+ Length: 7
+ ReplacementText: elem
+ - FilePath: $(path)/common.h
+ Offset: 169
+ Length: 1
+ ReplacementText: nullptr
...
diff --git a/test/clang-apply-replacements/Inputs/conflict/file3.yaml b/test/clang-apply-replacements/Inputs/conflict/file3.yaml
index 88543e0a..fee1108c 100644
--- a/test/clang-apply-replacements/Inputs/conflict/file3.yaml
+++ b/test/clang-apply-replacements/Inputs/conflict/file3.yaml
@@ -2,12 +2,13 @@
MainSourceFile: source1.cpp
Diagnostics:
- DiagnosticName: test-conflict
- Message: Fix
- FilePath: $(path)/common.h
- FileOffset: 169
- Replacements:
- - FilePath: $(path)/common.h
- Offset: 169
- Length: 0
- ReplacementText: "(int*)"
+ DiagnosticMessage:
+ Message: Fix
+ FilePath: $(path)/common.h
+ FileOffset: 169
+ Replacements:
+ - FilePath: $(path)/common.h
+ Offset: 169
+ Length: 0
+ ReplacementText: "(int*)"
...
diff --git a/test/clang-apply-replacements/Inputs/crlf/file1.yaml b/test/clang-apply-replacements/Inputs/crlf/file1.yaml
index 06b058e3..2c3d56e8 100644
--- a/test/clang-apply-replacements/Inputs/crlf/file1.yaml
+++ b/test/clang-apply-replacements/Inputs/crlf/file1.yaml
@@ -2,12 +2,13 @@
MainSourceFile: source1.cpp
Diagnostics:
- DiagnosticName: test-crlf
- Message: Fix
- FilePath: $(path)/crlf.cpp
- FileOffset: 79
- Replacements:
- - FilePath: $(path)/crlf.cpp
- Offset: 79
- Length: 1
- ReplacementText: nullptr
+ DiagnosticMessage:
+ Message: Fix
+ FilePath: $(path)/crlf.cpp
+ FileOffset: 79
+ Replacements:
+ - FilePath: $(path)/crlf.cpp
+ Offset: 79
+ Length: 1
+ ReplacementText: nullptr
...
diff --git a/test/clang-apply-replacements/Inputs/format/no.yaml b/test/clang-apply-replacements/Inputs/format/no.yaml
index 3118cc61..48aafd9d 100644
--- a/test/clang-apply-replacements/Inputs/format/no.yaml
+++ b/test/clang-apply-replacements/Inputs/format/no.yaml
@@ -2,12 +2,13 @@
MainSourceFile: no.cpp
Diagnostics:
- DiagnosticName: test-no
- Message: Fix
- FilePath: $(path)/no.cpp
- FileOffset: 94
- Replacements:
- - FilePath: $(path)/no.cpp
- Offset: 94
- Length: 3
- ReplacementText: 'auto '
+ DiagnosticMessage:
+ Message: Fix
+ FilePath: $(path)/no.cpp
+ FileOffset: 94
+ Replacements:
+ - FilePath: $(path)/no.cpp
+ Offset: 94
+ Length: 3
+ ReplacementText: 'auto '
...
diff --git a/test/clang-apply-replacements/Inputs/format/yes.yaml b/test/clang-apply-replacements/Inputs/format/yes.yaml
index 6ded4db3..337004d7 100644
--- a/test/clang-apply-replacements/Inputs/format/yes.yaml
+++ b/test/clang-apply-replacements/Inputs/format/yes.yaml
@@ -4,24 +4,25 @@
MainSourceFile: yes.cpp
Diagnostics:
- DiagnosticName: test-yes
- Message: Fix
- FilePath: $(path)/yes.cpp
- FileOffset: 494
- Replacements:
- - FilePath: $(path)/yes.cpp
- Offset: 494
- Length: 1
- ReplacementText: nullptr
- - FilePath: $(path)/yes.cpp
- Offset: 410
- Length: 1
- ReplacementText: nullptr
- - FilePath: $(path)/yes.cpp
- Offset: 454
- Length: 1
- ReplacementText: nullptr
- - FilePath: $(path)/yes.cpp
- Offset: 108
- Length: 38
- ReplacementText: 'auto '
+ DiagnosticMessage:
+ Message: Fix
+ FilePath: $(path)/yes.cpp
+ FileOffset: 494
+ Replacements:
+ - FilePath: $(path)/yes.cpp
+ Offset: 494
+ Length: 1
+ ReplacementText: nullptr
+ - FilePath: $(path)/yes.cpp
+ Offset: 410
+ Length: 1
+ ReplacementText: nullptr
+ - FilePath: $(path)/yes.cpp
+ Offset: 454
+ Length: 1
+ ReplacementText: nullptr
+ - FilePath: $(path)/yes.cpp
+ Offset: 108
+ Length: 38
+ ReplacementText: 'auto '
...
diff --git a/test/clang-apply-replacements/Inputs/identical/file1.yaml b/test/clang-apply-replacements/Inputs/identical/file1.yaml
index cf273c48..9e3de7b4 100644
--- a/test/clang-apply-replacements/Inputs/identical/file1.yaml
+++ b/test/clang-apply-replacements/Inputs/identical/file1.yaml
@@ -2,13 +2,14 @@
MainSourceFile: identical.cpp
Diagnostics:
- DiagnosticName: test-identical-insertion
- Message: Fix
- FilePath: $(path)/identical.cpp
- FileOffset: 12
- Replacements:
- - FilePath: $(path)/identical.cpp
- Offset: 12
- Length: 0
- ReplacementText: '0'
+ DiagnosticMessage:
+ Message: Fix
+ FilePath: $(path)/identical.cpp
+ FileOffset: 12
+ Replacements:
+ - FilePath: $(path)/identical.cpp
+ Offset: 12
+ Length: 0
+ ReplacementText: '0'
...
diff --git a/test/clang-apply-replacements/Inputs/identical/file2.yaml b/test/clang-apply-replacements/Inputs/identical/file2.yaml
index cf273c48..9e3de7b4 100644
--- a/test/clang-apply-replacements/Inputs/identical/file2.yaml
+++ b/test/clang-apply-replacements/Inputs/identical/file2.yaml
@@ -2,13 +2,14 @@
MainSourceFile: identical.cpp
Diagnostics:
- DiagnosticName: test-identical-insertion
- Message: Fix
- FilePath: $(path)/identical.cpp
- FileOffset: 12
- Replacements:
- - FilePath: $(path)/identical.cpp
- Offset: 12
- Length: 0
- ReplacementText: '0'
+ DiagnosticMessage:
+ Message: Fix
+ FilePath: $(path)/identical.cpp
+ FileOffset: 12
+ Replacements:
+ - FilePath: $(path)/identical.cpp
+ Offset: 12
+ Length: 0
+ ReplacementText: '0'
...
diff --git a/test/clang-apply-replacements/Inputs/order-dependent/file1.yaml b/test/clang-apply-replacements/Inputs/order-dependent/file1.yaml
index a8234388..939839d9 100644
--- a/test/clang-apply-replacements/Inputs/order-dependent/file1.yaml
+++ b/test/clang-apply-replacements/Inputs/order-dependent/file1.yaml
@@ -2,12 +2,13 @@
MainSourceFile: order-dependent.cpp
Diagnostics:
- DiagnosticName: test-order-dependent-insertion
- Message: Fix
- FilePath: $(path)/order-dependent.cpp
- FileOffset: 12
- Replacements:
- - FilePath: $(path)/order-dependent.cpp
- Offset: 12
- Length: 0
- ReplacementText: '0'
+ DiagnosticMessage:
+ Message: Fix
+ FilePath: $(path)/order-dependent.cpp
+ FileOffset: 12
+ Replacements:
+ - FilePath: $(path)/order-dependent.cpp
+ Offset: 12
+ Length: 0
+ ReplacementText: '0'
...
diff --git a/test/clang-apply-replacements/Inputs/order-dependent/file2.yaml b/test/clang-apply-replacements/Inputs/order-dependent/file2.yaml
index 634d3ca6..1219c3b0 100644
--- a/test/clang-apply-replacements/Inputs/order-dependent/file2.yaml
+++ b/test/clang-apply-replacements/Inputs/order-dependent/file2.yaml
@@ -2,12 +2,13 @@
MainSourceFile: order-dependent.cpp
Diagnostics:
- DiagnosticName: test-order-dependent-insertion
- Message: Fix
- FilePath: $(path)/order-dependent.cpp
- FileOffset: 12
- Replacements:
- - FilePath: $(path)/order-dependent.cpp
- Offset: 12
- Length: 0
- ReplacementText: '1'
+ DiagnosticMessage:
+ Message: Fix
+ FilePath: $(path)/order-dependent.cpp
+ FileOffset: 12
+ Replacements:
+ - FilePath: $(path)/order-dependent.cpp
+ Offset: 12
+ Length: 0
+ ReplacementText: '1'
...
diff --git a/test/change-namespace/Inputs/fake-std.h b/test/clang-change-namespace/Inputs/fake-std.h
index 24d3f977..24d3f977 100644
--- a/test/change-namespace/Inputs/fake-std.h
+++ b/test/clang-change-namespace/Inputs/fake-std.h
diff --git a/test/change-namespace/lambda-function.cpp b/test/clang-change-namespace/lambda-function.cpp
index 452983ea..452983ea 100644
--- a/test/change-namespace/lambda-function.cpp
+++ b/test/clang-change-namespace/lambda-function.cpp
diff --git a/test/change-namespace/macro.cpp b/test/clang-change-namespace/macro.cpp
index ba47de60..ba47de60 100644
--- a/test/change-namespace/macro.cpp
+++ b/test/clang-change-namespace/macro.cpp
diff --git a/test/change-namespace/simple-move.cpp b/test/clang-change-namespace/simple-move.cpp
index ea3c3d33..ea3c3d33 100644
--- a/test/change-namespace/simple-move.cpp
+++ b/test/clang-change-namespace/simple-move.cpp
diff --git a/test/change-namespace/white-list.cpp b/test/clang-change-namespace/white-list.cpp
index 48e3a78a..48e3a78a 100644
--- a/test/change-namespace/white-list.cpp
+++ b/test/clang-change-namespace/white-list.cpp
diff --git a/test/include-fixer/Inputs/database_template.json b/test/clang-include-fixer/Inputs/database_template.json
index ec71c562..ec71c562 100644
--- a/test/include-fixer/Inputs/database_template.json
+++ b/test/clang-include-fixer/Inputs/database_template.json
diff --git a/test/include-fixer/Inputs/fake_yaml_db.yaml b/test/clang-include-fixer/Inputs/fake_yaml_db.yaml
index b599005e..134b3758 100644
--- a/test/include-fixer/Inputs/fake_yaml_db.yaml
+++ b/test/clang-include-fixer/Inputs/fake_yaml_db.yaml
@@ -65,7 +65,7 @@ Name: bar
Contexts:
- ContextType: Namespace
ContextName: c
-FilePath: test/include-fixer/baz.h
+FilePath: test/clang-include-fixer/baz.h
Type: Class
Seen: 1
Used: 0
diff --git a/test/include-fixer/Inputs/merge/a.yaml b/test/clang-include-fixer/Inputs/merge/a.yaml
index 174db0e5..174db0e5 100644
--- a/test/include-fixer/Inputs/merge/a.yaml
+++ b/test/clang-include-fixer/Inputs/merge/a.yaml
diff --git a/test/include-fixer/Inputs/merge/b.yaml b/test/clang-include-fixer/Inputs/merge/b.yaml
index 86893208..86893208 100644
--- a/test/include-fixer/Inputs/merge/b.yaml
+++ b/test/clang-include-fixer/Inputs/merge/b.yaml
diff --git a/test/include-fixer/commandline_options.cpp b/test/clang-include-fixer/commandline_options.cpp
index 3cc77b49..3cc77b49 100644
--- a/test/include-fixer/commandline_options.cpp
+++ b/test/clang-include-fixer/commandline_options.cpp
diff --git a/test/include-fixer/exit_on_fatal.cpp b/test/clang-include-fixer/exit_on_fatal.cpp
index fc8c95a0..fc8c95a0 100644
--- a/test/include-fixer/exit_on_fatal.cpp
+++ b/test/clang-include-fixer/exit_on_fatal.cpp
diff --git a/test/include-fixer/fixeddb.cpp b/test/clang-include-fixer/fixeddb.cpp
index 90068dbf..90068dbf 100644
--- a/test/include-fixer/fixeddb.cpp
+++ b/test/clang-include-fixer/fixeddb.cpp
diff --git a/test/clang-include-fixer/include_path.cpp b/test/clang-include-fixer/include_path.cpp
new file mode 100644
index 00000000..9185b7af
--- /dev/null
+++ b/test/clang-include-fixer/include_path.cpp
@@ -0,0 +1,19 @@
+// 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: 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
+
+// CHECK-YAML: ..{{[/\\]}}include{{[/\\]}}bar.h
+// CHECK: #include "bar.h"
+// CHECK: b::a::bar f;
diff --git a/test/include-fixer/merge.test b/test/clang-include-fixer/merge.test
index 230d38da..230d38da 100644
--- a/test/include-fixer/merge.test
+++ b/test/clang-include-fixer/merge.test
diff --git a/test/clang-include-fixer/multiple_fixes.cpp b/test/clang-include-fixer/multiple_fixes.cpp
new file mode 100644
index 00000000..791417a3
--- /dev/null
+++ b/test/clang-include-fixer/multiple_fixes.cpp
@@ -0,0 +1,13 @@
+// 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
+//
+// CHECK-FOO: #include "foo.h"
+// CHECK-FOO: foo f;
+// CHECK-BAR: #include "bar.h"
+// CHECK-BAR: bar b;
diff --git a/test/include-fixer/prefix_variable.cpp b/test/clang-include-fixer/prefix_variable.cpp
index b39cdb8d..b39cdb8d 100644
--- a/test/include-fixer/prefix_variable.cpp
+++ b/test/clang-include-fixer/prefix_variable.cpp
diff --git a/test/include-fixer/query_symbol.cpp b/test/clang-include-fixer/query_symbol.cpp
index 84c3a237..84c3a237 100644
--- a/test/include-fixer/query_symbol.cpp
+++ b/test/clang-include-fixer/query_symbol.cpp
diff --git a/test/include-fixer/ranking.cpp b/test/clang-include-fixer/ranking.cpp
index 2dabe16f..ee54d4c7 100644
--- a/test/include-fixer/ranking.cpp
+++ b/test/clang-include-fixer/ranking.cpp
@@ -2,7 +2,7 @@
// RUN: clang-include-fixer -query-symbol bar -db=yaml -input=%S/Inputs/fake_yaml_db.yaml -output-headers %s -- | FileCheck %s
// CHECK: "HeaderInfos": [
-// CHECK-NEXT: {"Header": "\"test/include-fixer/baz.h\"",
+// CHECK-NEXT: {"Header": "\"test/clang-include-fixer/baz.h\"",
// CHECK-NEXT: "QualifiedName": "c::bar"},
// CHECK-NEXT: {"Header": "\"../include/bar.h\"",
// CHECK-NEXT: "QualifiedName": "b::a::bar"},
diff --git a/test/include-fixer/yaml_fuzzy.cpp b/test/clang-include-fixer/yaml_fuzzy.cpp
index 705542dd..9a3daacb 100644
--- a/test/include-fixer/yaml_fuzzy.cpp
+++ b/test/clang-include-fixer/yaml_fuzzy.cpp
@@ -2,7 +2,7 @@
// RUN: clang-include-fixer -db=fuzzyYaml -input=%p/Inputs/fake_yaml_db.yaml %t.cpp --
// RUN: FileCheck %s -input-file=%t.cpp
-// include-fixer will add the include, but doesn't complete the symbol.
+// clang-include-fixer will add the include, but doesn't complete the symbol.
// CHECK: #include "foobar.h"
// CHECK: fba f;
diff --git a/test/include-fixer/yamldb.cpp b/test/clang-include-fixer/yamldb.cpp
index d17b4147..d17b4147 100644
--- a/test/include-fixer/yamldb.cpp
+++ b/test/clang-include-fixer/yamldb.cpp
diff --git a/test/include-fixer/yamldb_autodetect.cpp b/test/clang-include-fixer/yamldb_autodetect.cpp
index 1997390d..1997390d 100644
--- a/test/include-fixer/yamldb_autodetect.cpp
+++ b/test/clang-include-fixer/yamldb_autodetect.cpp
diff --git a/test/clang-tidy/Inputs/Headers/stdio.h b/test/clang-tidy/Inputs/Headers/stdio.h
new file mode 100644
index 00000000..eebe9fd9
--- /dev/null
+++ b/test/clang-tidy/Inputs/Headers/stdio.h
@@ -0,0 +1,18 @@
+//===--- stdio.h - Stub header for tests ------------------------*- 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 _STDIO_H_
+#define _STDIO_H_
+
+// A header intended to contain C standard input and output library
+// declarations.
+
+int printf(const char *, ...);
+
+#endif // _STDIO_H_
+
diff --git a/test/clang-tidy/Inputs/absl/time/time.h b/test/clang-tidy/Inputs/absl/time/time.h
index 9d136a5d..5454f978 100644
--- a/test/clang-tidy/Inputs/absl/time/time.h
+++ b/test/clang-tidy/Inputs/absl/time/time.h
@@ -14,11 +14,14 @@ public:
Duration &operator/=(float r);
Duration &operator/=(double r);
template <typename T> Duration &operator/=(T r);
+
+ Duration &operator+(Duration d);
};
template <typename T> Duration operator*(Duration lhs, T rhs);
template <typename T> Duration operator*(T lhs, Duration rhs);
template <typename T> Duration operator/(Duration lhs, T rhs);
+int64_t operator/(Duration lhs, Duration rhs);
class Time{};
@@ -55,6 +58,21 @@ int64_t ToInt64Milliseconds(Duration d);
int64_t ToInt64Microseconds(Duration d);
int64_t ToInt64Nanoseconds(Duration d);
+int64_t ToUnixHours(Time t);
+int64_t ToUnixMinutes(Time t);
+int64_t ToUnixSeconds(Time t);
+int64_t ToUnixMillis(Time t);
+int64_t ToUnixMicros(Time t);
+int64_t ToUnixNanos(Time t);
+Time FromUnixHours(int64_t);
+Time FromUnixMinutes(int64_t);
+Time FromUnixSeconds(int64_t);
+Time FromUnixMillis(int64_t);
+Time FromUnixMicros(int64_t);
+Time FromUnixNanos(int64_t);
+
+Time Now();
+
// Relational Operators
constexpr bool operator<(Duration lhs, Duration rhs);
constexpr bool operator>(Duration lhs, Duration rhs);
@@ -69,4 +87,6 @@ inline Time operator+(Duration lhs, Time rhs);
inline Time operator-(Time lhs, Duration rhs);
inline Duration operator-(Time lhs, Time rhs);
+double FDivDuration(Duration num, Duration den);
+
} // namespace absl
diff --git a/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/a.h b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/a.h
new file mode 100644
index 00000000..6651b4fa
--- /dev/null
+++ b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/a.h
@@ -0,0 +1 @@
+#define a
diff --git a/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/b.h b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/b.h
new file mode 100644
index 00000000..446eda1a
--- /dev/null
+++ b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/b.h
@@ -0,0 +1,2 @@
+#include "a.h"
+#define b
diff --git a/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/c.h b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/c.h
new file mode 100644
index 00000000..0d4c60df
--- /dev/null
+++ b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/c.h
@@ -0,0 +1,2 @@
+#include "b.h"
+#define c
diff --git a/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/module.modulemap b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/module.modulemap
new file mode 100644
index 00000000..d04240af
--- /dev/null
+++ b/test/clang-tidy/Inputs/expand-modular-headers-ppcallbacks/module.modulemap
@@ -0,0 +1,3 @@
+module a { header "a.h" export * }
+module b { header "b.h" export * use a }
+module c { header "c.h" export * use b }
diff --git a/test/clang-tidy/abseil-duration-addition.cpp b/test/clang-tidy/abseil-duration-addition.cpp
new file mode 100644
index 00000000..33cfc58f
--- /dev/null
+++ b/test/clang-tidy/abseil-duration-addition.cpp
@@ -0,0 +1,98 @@
+// RUN: %check_clang_tidy %s abseil-duration-addition %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+ absl::Time t;
+ int i;
+
+ i = absl::ToUnixHours(t) + 5;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixHours(t + absl::Hours(5))
+ i = absl::ToUnixMinutes(t) + 5;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixMinutes(t + absl::Minutes(5))
+ i = absl::ToUnixSeconds(t) + 5;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(5))
+ i = absl::ToUnixMillis(t) + 5;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixMillis(t + absl::Milliseconds(5))
+ i = absl::ToUnixMicros(t) + 5;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixMicros(t + absl::Microseconds(5))
+ i = absl::ToUnixNanos(t) + 5;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixNanos(t + absl::Nanoseconds(5))
+
+ i = 3 + absl::ToUnixHours(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixHours(absl::Hours(3) + t)
+ i = 3 + absl::ToUnixMinutes(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixMinutes(absl::Minutes(3) + t)
+ i = 3 + absl::ToUnixSeconds(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixSeconds(absl::Seconds(3) + t)
+ i = 3 + absl::ToUnixMillis(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixMillis(absl::Milliseconds(3) + t)
+ i = 3 + absl::ToUnixMicros(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixMicros(absl::Microseconds(3) + t)
+ i = 3 + absl::ToUnixNanos(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixNanos(absl::Nanoseconds(3) + t)
+
+ // Undoing inverse conversions
+ i = absl::ToUnixMicros(t) + absl::ToInt64Microseconds(absl::Seconds(1));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixMicros(t + absl::Seconds(1))
+
+ // Parens
+ i = 3 + (absl::ToUnixHours(t));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixHours(absl::Hours(3) + t)
+
+ // Float folding
+ i = absl::ToUnixSeconds(t) + 5.0;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(5))
+
+ // We can rewrite the argument of the duration conversion
+#define THIRTY absl::FromUnixSeconds(30)
+ i = absl::ToUnixSeconds(THIRTY) + 1;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixSeconds(THIRTY + absl::Seconds(1))
+#undef THIRTY
+
+ // Some other contexts
+ if (absl::ToUnixSeconds(t) + 1.0 > 10) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(1))
+
+ // These should not match
+ i = 5 + 6;
+ i = absl::ToUnixSeconds(t) - 1.0;
+ i = absl::ToUnixSeconds(t) * 1.0;
+ i = absl::ToUnixSeconds(t) / 1.0;
+ i += absl::ToInt64Microseconds(absl::Seconds(1));
+
+#define PLUS_FIVE(z) absl::ToUnixSeconds(z) + 5
+ i = PLUS_FIVE(t);
+#undef PLUS_FIVE
+}
+
+// Within a templated function
+template<typename T>
+void foo(absl::Time t) {
+ int i = absl::ToUnixNanos(t) + T{};
+ // CHECK-MESSAGES: [[@LINE-1]]:11: warning: perform addition in the duration domain [abseil-duration-addition]
+ // CHECK-FIXES: absl::ToUnixNanos(t + absl::Nanoseconds(T{}))
+}
+
+void g() {
+ absl::Time t;
+ foo<int>(t);
+ foo<double>(t);
+}
diff --git a/test/clang-tidy/abseil-duration-conversion-cast.cpp b/test/clang-tidy/abseil-duration-conversion-cast.cpp
new file mode 100644
index 00000000..260aa327
--- /dev/null
+++ b/test/clang-tidy/abseil-duration-conversion-cast.cpp
@@ -0,0 +1,95 @@
+// RUN: %check_clang_tidy %s abseil-duration-conversion-cast %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+ absl::Duration d1;
+ double x;
+ int i;
+
+ i = static_cast<int>(absl::ToDoubleHours(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToInt64Hours(d1);
+ x = static_cast<float>(absl::ToInt64Hours(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToDoubleHours(d1);
+ i = static_cast<int>(absl::ToDoubleMinutes(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToInt64Minutes(d1);
+ x = static_cast<float>(absl::ToInt64Minutes(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToDoubleMinutes(d1);
+ i = static_cast<int>(absl::ToDoubleSeconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToInt64Seconds(d1);
+ x = static_cast<float>(absl::ToInt64Seconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToDoubleSeconds(d1);
+ i = static_cast<int>(absl::ToDoubleMilliseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToInt64Milliseconds(d1);
+ x = static_cast<float>(absl::ToInt64Milliseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToDoubleMilliseconds(d1);
+ i = static_cast<int>(absl::ToDoubleMicroseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToInt64Microseconds(d1);
+ x = static_cast<float>(absl::ToInt64Microseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToDoubleMicroseconds(d1);
+ i = static_cast<int>(absl::ToDoubleNanoseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToInt64Nanoseconds(d1);
+ x = static_cast<float>(absl::ToInt64Nanoseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToDoubleNanoseconds(d1);
+
+ // Functional-style casts
+ i = int(absl::ToDoubleHours(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToInt64Hours(d1);
+ x = float(absl::ToInt64Microseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToDoubleMicroseconds(d1);
+
+ // C-style casts
+ i = (int) absl::ToDoubleHours(d1);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToInt64Hours(d1);
+ x = (float) absl::ToInt64Microseconds(d1);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToDoubleMicroseconds(d1);
+
+ // Type aliasing
+ typedef int FancyInt;
+ typedef float FancyFloat;
+
+ FancyInt j = static_cast<FancyInt>(absl::ToDoubleHours(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToInt64Hours(d1);
+ FancyFloat k = static_cast<FancyFloat>(absl::ToInt64Microseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:18: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: absl::ToDoubleMicroseconds(d1);
+
+ // Macro handling
+ // We want to transform things in macro arguments
+#define EXTERNAL(x) (x) + 5
+ i = EXTERNAL(static_cast<int>(absl::ToDoubleSeconds(d1)));
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+ // CHECK-FIXES: EXTERNAL(absl::ToInt64Seconds(d1));
+#undef EXTERNAL
+
+ // We don't want to transform this which get split across macro boundaries
+#define SPLIT(x) static_cast<int>((x)) + 5
+ i = SPLIT(absl::ToDoubleSeconds(d1));
+#undef SPLIT
+
+ // We also don't want to transform things inside of a macro definition
+#define INTERNAL(x) static_cast<int>(absl::ToDoubleSeconds((x))) + 5
+ i = INTERNAL(d1);
+#undef INTERNAL
+
+ // These shouldn't be converted
+ i = static_cast<int>(absl::ToInt64Seconds(d1));
+ i = static_cast<float>(absl::ToDoubleSeconds(d1));
+}
diff --git a/test/clang-tidy/abseil-duration-unnecessary-conversion.cpp b/test/clang-tidy/abseil-duration-unnecessary-conversion.cpp
new file mode 100644
index 00000000..d32837f8
--- /dev/null
+++ b/test/clang-tidy/abseil-duration-unnecessary-conversion.cpp
@@ -0,0 +1,111 @@
+// RUN: %check_clang_tidy %s abseil-duration-unnecessary-conversion %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+ absl::Duration d1, d2;
+
+ // Floating point
+ d2 = absl::Hours(absl::ToDoubleHours(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Minutes(absl::ToDoubleMinutes(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Seconds(absl::ToDoubleSeconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Milliseconds(absl::ToDoubleMilliseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Microseconds(absl::ToDoubleMicroseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Nanoseconds(absl::ToDoubleNanoseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+
+ // Integer point
+ d2 = absl::Hours(absl::ToInt64Hours(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Minutes(absl::ToInt64Minutes(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Seconds(absl::ToInt64Seconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Milliseconds(absl::ToInt64Milliseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Microseconds(absl::ToInt64Microseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Nanoseconds(absl::ToInt64Nanoseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+
+ d2 = absl::Hours(d1 / absl::Hours(1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Minutes(d1 / absl::Minutes(1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Seconds(d1 / absl::Seconds(1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Milliseconds(d1 / absl::Milliseconds(1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Microseconds(d1 / absl::Microseconds(1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Nanoseconds(d1 / absl::Nanoseconds(1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+
+ d2 = absl::Hours(absl::FDivDuration(d1, absl::Hours(1)));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Minutes(absl::FDivDuration(d1, absl::Minutes(1)));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Seconds(absl::FDivDuration(d1, absl::Seconds(1)));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Milliseconds(absl::FDivDuration(d1, absl::Milliseconds(1)));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Microseconds(absl::FDivDuration(d1, absl::Microseconds(1)));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+ d2 = absl::Nanoseconds(absl::FDivDuration(d1, absl::Nanoseconds(1)));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d2 = d1
+
+ // As macro argument
+#define PLUS_FIVE_S(x) x + absl::Seconds(5)
+ d2 = PLUS_FIVE_S(absl::Seconds(absl::ToInt64Seconds(d1)));
+ // CHECK-MESSAGES: [[@LINE-1]]:20: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: PLUS_FIVE_S(d1)
+#undef PLUS_FIVE_S
+
+ // Split by macro: should not change
+#define TOSECONDS(x) absl::Seconds(x)
+ d2 = TOSECONDS(absl::ToInt64Seconds(d1));
+#undef TOSECONDS
+
+ // Don't change something inside a macro definition
+#define VALUE(x) absl::Hours(absl::ToInt64Hours(x));
+ d2 = VALUE(d1);
+#undef VALUE
+
+ // These should not match
+ d2 = absl::Seconds(absl::ToDoubleMilliseconds(d1));
+ d2 = absl::Seconds(4);
+ int i = absl::ToInt64Milliseconds(d1);
+ d2 = absl::Hours(d1 / absl::Minutes(1));
+ d2 = absl::Seconds(d1 / absl::Seconds(30));
+ d2 = absl::Hours(absl::FDivDuration(d1, absl::Minutes(1)));
+ d2 = absl::Milliseconds(absl::FDivDuration(d1, absl::Milliseconds(20)));
+}
diff --git a/test/clang-tidy/abseil-time-comparison.cpp b/test/clang-tidy/abseil-time-comparison.cpp
new file mode 100644
index 00000000..ab03020c
--- /dev/null
+++ b/test/clang-tidy/abseil-time-comparison.cpp
@@ -0,0 +1,129 @@
+// RUN: %check_clang_tidy %s abseil-time-comparison %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+ double x;
+ absl::Duration d1, d2;
+ bool b;
+ absl::Time t1, t2;
+
+ // Check against the RHS
+ b = x > absl::ToUnixSeconds(t1);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: absl::FromUnixSeconds(x) > t1;
+ b = x >= absl::ToUnixSeconds(t1);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: absl::FromUnixSeconds(x) >= t1;
+ b = x == absl::ToUnixSeconds(t1);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: absl::FromUnixSeconds(x) == t1;
+ b = x <= absl::ToUnixSeconds(t1);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: absl::FromUnixSeconds(x) <= t1;
+ b = x < absl::ToUnixSeconds(t1);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: absl::FromUnixSeconds(x) < t1;
+ b = x == absl::ToUnixSeconds(t1 - d2);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: absl::FromUnixSeconds(x) == t1 - d2;
+ b = absl::ToUnixSeconds(t1) > absl::ToUnixSeconds(t2);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: t1 > t2;
+
+ // Check against the LHS
+ b = absl::ToUnixSeconds(t1) < x;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: t1 < absl::FromUnixSeconds(x);
+ b = absl::ToUnixSeconds(t1) <= x;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: t1 <= absl::FromUnixSeconds(x);
+ b = absl::ToUnixSeconds(t1) == x;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: t1 == absl::FromUnixSeconds(x);
+ b = absl::ToUnixSeconds(t1) >= x;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: t1 >= absl::FromUnixSeconds(x);
+ b = absl::ToUnixSeconds(t1) > x;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: t1 > absl::FromUnixSeconds(x);
+
+ // Comparison against zero
+ b = absl::ToUnixSeconds(t1) < 0.0;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: t1 < absl::UnixEpoch();
+ b = absl::ToUnixSeconds(t1) < 0;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: t1 < absl::UnixEpoch();
+
+ // Scales other than Seconds
+ b = x > absl::ToUnixMicros(t1);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: absl::FromUnixMicros(x) > t1;
+ b = x >= absl::ToUnixMillis(t1);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: absl::FromUnixMillis(x) >= t1;
+ b = x == absl::ToUnixNanos(t1);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: absl::FromUnixNanos(x) == t1;
+ b = x <= absl::ToUnixMinutes(t1);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: absl::FromUnixMinutes(x) <= t1;
+ b = x < absl::ToUnixHours(t1);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: absl::FromUnixHours(x) < t1;
+
+ // A long expression
+ bool some_condition;
+ int very_very_very_very_long_variable_name;
+ absl::Time SomeTime;
+ if (some_condition && very_very_very_very_long_variable_name
+ < absl::ToUnixSeconds(SomeTime)) {
+ // CHECK-MESSAGES: [[@LINE-2]]:25: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: if (some_condition && absl::FromUnixSeconds(very_very_very_very_long_variable_name) < SomeTime) {
+ return;
+ }
+
+ // A complex expression
+ int y;
+ b = (y + 5) * 10 > absl::ToUnixMillis(t1);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: absl::FromUnixMillis((y + 5) * 10) > t1;
+
+ // We should still transform the expression inside this macro invocation
+#define VALUE_IF(v, e) v ? (e) : 0
+ int a = VALUE_IF(1, 5 > absl::ToUnixSeconds(t1));
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: VALUE_IF(1, absl::FromUnixSeconds(5) > t1);
+#undef VALUE_IF
+
+#define VALUE_IF_2(e) (e)
+#define VALUE_IF(v, e) v ? VALUE_IF_2(e) : VALUE_IF_2(0)
+ int a2 = VALUE_IF(1, 5 > absl::ToUnixSeconds(t1));
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: perform comparison in the time domain [abseil-time-comparison]
+ // CHECK-FIXES: VALUE_IF(1, absl::FromUnixSeconds(5) > t1);
+#undef VALUE_IF
+#undef VALUE_IF_2
+
+#define VALUE_IF_2(e) (e)
+#define VALUE_IF(v, e, type) (v ? VALUE_IF_2(absl::To##type##Seconds(e)) : 0)
+ int a3 = VALUE_IF(1, t1, Unix);
+#undef VALUE_IF
+#undef VALUE_IF_2
+
+#define VALUE_IF_2(e) (e)
+#define VALUE_IF(v, e, type) (v ? (5 > VALUE_IF_2(absl::To##type##Seconds(e))) : 0)
+ int a4 = VALUE_IF(1, t1, Unix);
+#undef VALUE_IF
+#undef VALUE_IF_2
+
+ // These should not match
+ b = 6 < 4;
+
+#define TODOUBLE(x) absl::ToUnixSeconds(x)
+ b = 5.0 > TODOUBLE(t1);
+#undef TODOUBLE
+#define THIRTY 30.0
+ b = THIRTY > absl::ToUnixSeconds(t1);
+#undef THIRTY
+}
diff --git a/test/clang-tidy/abseil-time-subtraction.cpp b/test/clang-tidy/abseil-time-subtraction.cpp
new file mode 100644
index 00000000..6f5d4b45
--- /dev/null
+++ b/test/clang-tidy/abseil-time-subtraction.cpp
@@ -0,0 +1,117 @@
+// RUN: %check_clang_tidy %s abseil-time-subtraction %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void g(absl::Duration d);
+
+void f() {
+ absl::Time t;
+ int x, y;
+ absl::Duration d;
+
+ d = absl::Hours(absl::ToUnixHours(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixHours(x));
+ d = absl::Minutes(absl::ToUnixMinutes(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixMinutes(x));
+ d = absl::Seconds(absl::ToUnixSeconds(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x));
+ d = absl::Milliseconds(absl::ToUnixMillis(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixMillis(x));
+ d = absl::Microseconds(absl::ToUnixMicros(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixMicros(x));
+ d = absl::Nanoseconds(absl::ToUnixNanos(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixNanos(x));
+
+ y = x - absl::ToUnixHours(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: y = absl::ToInt64Hours(absl::FromUnixHours(x) - t);
+ y = x - absl::ToUnixMinutes(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: y = absl::ToInt64Minutes(absl::FromUnixMinutes(x) - t);
+ y = x - absl::ToUnixSeconds(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: y = absl::ToInt64Seconds(absl::FromUnixSeconds(x) - t);
+ y = x - absl::ToUnixMillis(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: y = absl::ToInt64Milliseconds(absl::FromUnixMillis(x) - t);
+ y = x - absl::ToUnixMicros(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: y = absl::ToInt64Microseconds(absl::FromUnixMicros(x) - t);
+ y = x - absl::ToUnixNanos(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: y = absl::ToInt64Nanoseconds(absl::FromUnixNanos(x) - t);
+
+ // Check parenthesis placement
+ d = 5 * absl::Seconds(absl::ToUnixSeconds(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:11: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = 5 * (t - absl::FromUnixSeconds(x));
+ d = absl::Seconds(absl::ToUnixSeconds(t) - x) / 5;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x)) / 5;
+
+ // No extra parens around arguments
+ g(absl::Seconds(absl::ToUnixSeconds(t) - x));
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: g(t - absl::FromUnixSeconds(x));
+ g(absl::Seconds(x - absl::ToUnixSeconds(t)));
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: g(absl::FromUnixSeconds(x) - t);
+
+ // More complex subexpressions
+ d = absl::Hours(absl::ToUnixHours(t) - 5 * x);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixHours(5 * x));
+
+ // These should not trigger; they are likely bugs
+ d = absl::Milliseconds(absl::ToUnixSeconds(t) - x);
+ d = absl::Seconds(absl::ToUnixMicros(t) - x);
+
+ // Various macro scenarios
+#define SUB(z, t1) z - absl::ToUnixSeconds(t1)
+ y = SUB(x, t);
+#undef SUB
+
+#define MILLIS(t1) absl::ToUnixMillis(t1)
+ y = x - MILLIS(t);
+#undef MILLIS
+
+#define HOURS(z) absl::Hours(z)
+ d = HOURS(absl::ToUnixHours(t) - x);
+#undef HOURS
+
+ // This should match the expression inside the macro invocation.
+#define SECONDS(z) absl::Seconds(z)
+ d = SECONDS(x - absl::ToUnixSeconds(t));
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: SECONDS(absl::ToInt64Seconds(absl::FromUnixSeconds(x) - t))
+#undef SECONDS
+}
+
+template<typename T>
+void func(absl::Time t, T x) {
+ absl::Duration d = absl::Seconds(absl::ToUnixSeconds(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:22: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: absl::Duration d = t - absl::FromUnixSeconds(x);
+}
+
+void g() {
+ func(absl::Now(), 5);
+}
+
+absl::Duration parens_in_return() {
+ absl::Time t;
+ int x;
+
+ return absl::Seconds(absl::ToUnixSeconds(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: return t - absl::FromUnixSeconds(x);
+ return absl::Seconds(x - absl::ToUnixSeconds(t));
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: return absl::FromUnixSeconds(x) - t;
+}
diff --git a/test/clang-tidy/abseil-upgrade-duration-conversions.cpp b/test/clang-tidy/abseil-upgrade-duration-conversions.cpp
index 7d8ad43e..fed0f8bd 100644
--- a/test/clang-tidy/abseil-upgrade-duration-conversions.cpp
+++ b/test/clang-tidy/abseil-upgrade-duration-conversions.cpp
@@ -430,3 +430,36 @@ void factoryInMacros() {
factoryTemplateAndMacro<ConvertibleTo<int>>();
TemplateFactoryInMacro(ConvertibleTo<int>());
}
+
+// This is a reduced test-case for PR39949 and manifested in this check.
+namespace std {
+template <typename _Tp>
+_Tp declval();
+
+template <typename _Functor, typename... _ArgTypes>
+struct __res {
+ template <typename... _Args>
+ static decltype(declval<_Functor>()(_Args()...)) _S_test(int);
+
+ template <typename...>
+ static void _S_test(...);
+
+ typedef decltype(_S_test<_ArgTypes...>(0)) type;
+};
+
+template <typename>
+struct function;
+
+template <typename... _ArgTypes>
+struct function<void(_ArgTypes...)> {
+ template <typename _Functor,
+ typename = typename __res<_Functor, _ArgTypes...>::type>
+ function(_Functor) {}
+};
+} // namespace std
+
+typedef std::function<void(void)> F;
+
+F foo() {
+ return F([] {});
+}
diff --git a/test/clang-tidy/alternative-fixes.cpp b/test/clang-tidy/alternative-fixes.cpp
new file mode 100644
index 00000000..d5cee68d
--- /dev/null
+++ b/test/clang-tidy/alternative-fixes.cpp
@@ -0,0 +1,9 @@
+// RUN: %check_clang_tidy %s "llvm-namespace-comment,clang-diagnostic-*" %t
+void foo(int a) {
+ if (a = 1) {
+ // CHECK-NOTES: [[@LINE-1]]:9: warning: using the result of an assignment as a condition without parentheses [clang-diagnostic-parentheses]
+ // CHECK-NOTES: [[@LINE-2]]:9: note: place parentheses around the assignment to silence this warning
+ // CHECK-NOTES: [[@LINE-3]]:9: note: use '==' to turn this assignment into an equality comparison
+ // CHECK-FIXES: if ((a = 1)) {
+ }
+}
diff --git a/test/clang-tidy/bugprone-argument-comment-literals.cpp b/test/clang-tidy/bugprone-argument-comment-literals.cpp
new file mode 100644
index 00000000..739c9a59
--- /dev/null
+++ b/test/clang-tidy/bugprone-argument-comment-literals.cpp
@@ -0,0 +1,124 @@
+// RUN: %check_clang_tidy %s bugprone-argument-comment %t -- \
+// RUN: -config="{CheckOptions: [{key: CommentBoolLiterals, value: 1},{key: CommentIntegerLiterals, value: 1}, {key: CommentFloatLiterals, value: 1}, {key: CommentUserDefinedLiterals, value: 1}, {key: CommentStringLiterals, value: 1}, {key: CommentNullPtrs, value: 1}, {key: CommentCharacterLiterals, value: 1}]}" --
+
+struct A {
+ void foo(bool abc);
+ void foo(bool abc, bool cde);
+ void foo(const char *, bool abc);
+ void foo(int iabc);
+ void foo(float fabc);
+ void foo(double dabc);
+ void foo(const char *strabc);
+ void fooW(const wchar_t *wstrabc);
+ void fooPtr(A *ptrabc);
+ void foo(char chabc);
+};
+
+#define FOO 1
+
+void g(int a);
+void h(double b);
+void i(const char *c);
+
+double operator"" _km(long double);
+
+void test() {
+ A a;
+
+ a.foo(true);
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'abc' [bugprone-argument-comment]
+ // CHECK-FIXES: a.foo(/*abc=*/true);
+
+ a.foo(false);
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'abc' [bugprone-argument-comment]
+ // CHECK-FIXES: a.foo(/*abc=*/false);
+
+ a.foo(true, false);
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'abc' [bugprone-argument-comment]
+ // CHECK-MESSAGES: [[@LINE-2]]:15: warning: argument comment missing for literal argument 'cde' [bugprone-argument-comment]
+ // CHECK-FIXES: a.foo(/*abc=*/true, /*cde=*/false);
+
+ a.foo(false, true);
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'abc' [bugprone-argument-comment]
+ // CHECK-MESSAGES: [[@LINE-2]]:16: warning: argument comment missing for literal argument 'cde' [bugprone-argument-comment]
+ // CHECK-FIXES: a.foo(/*abc=*/false, /*cde=*/true);
+
+ a.foo(/*abc=*/false, true);
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: argument comment missing for literal argument 'cde' [bugprone-argument-comment]
+ // CHECK-FIXES: a.foo(/*abc=*/false, /*cde=*/true);
+
+ a.foo(false, /*cde=*/true);
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'abc' [bugprone-argument-comment]
+ // CHECK-FIXES: a.foo(/*abc=*/false, /*cde=*/true);
+
+ bool val1 = true;
+ bool val2 = false;
+ a.foo(val1, val2);
+
+ a.foo("", true);
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: argument comment missing for literal argument 'abc' [bugprone-argument-comment]
+ // CHECK-FIXES: a.foo("", /*abc=*/true);
+
+ a.foo(0);
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'iabc' [bugprone-argument-comment]
+ // CHECK-FIXES: a.foo(/*iabc=*/0);
+
+ a.foo(1.0f);
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'fabc' [bugprone-argument-comment]
+ // CHECK-FIXES: a.foo(/*fabc=*/1.0f);
+
+ a.foo(1.0);
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'dabc' [bugprone-argument-comment]
+ // CHECK-FIXES: a.foo(/*dabc=*/1.0);
+
+ int val3 = 10;
+ a.foo(val3);
+
+ float val4 = 10.0;
+ a.foo(val4);
+
+ double val5 = 10.0;
+ a.foo(val5);
+
+ a.foo("Hello World");
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'strabc' [bugprone-argument-comment]
+ // CHECK-FIXES: a.foo(/*strabc=*/"Hello World");
+ //
+ a.fooW(L"Hello World");
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: argument comment missing for literal argument 'wstrabc' [bugprone-argument-comment]
+ // CHECK-FIXES: a.fooW(/*wstrabc=*/L"Hello World");
+
+ a.fooPtr(nullptr);
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: argument comment missing for literal argument 'ptrabc' [bugprone-argument-comment]
+ // CHECK-FIXES: a.fooPtr(/*ptrabc=*/nullptr);
+
+ a.foo(402.0_km);
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'dabc' [bugprone-argument-comment]
+ // CHECK-FIXES: a.foo(/*dabc=*/402.0_km);
+
+ a.foo('A');
+ // CHECK-MESSAGES: [[@LINE-1]]:9: warning: argument comment missing for literal argument 'chabc' [bugprone-argument-comment]
+ // CHECK-FIXES: a.foo(/*chabc=*/'A');
+
+ g(FOO);
+ h(1.0f);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: argument comment missing for literal argument 'b' [bugprone-argument-comment]
+ // CHECK-FIXES: h(/*b=*/1.0f);
+ i(__FILE__);
+
+ // FIXME Would like the below to add argument comments.
+ g((1));
+ // FIXME But we should not add argument comments here.
+ g(_Generic(0, int : 0));
+}
+
+void f(bool _with_underscores_);
+void ignores_underscores() {
+ f(false);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: argument comment missing for literal argument '_with_underscores_' [bugprone-argument-comment]
+ // CHECK-FIXES: f(/*_with_underscores_=*/false);
+
+ f(true);
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: argument comment missing for literal argument
+ // CHECK-FIXES: f(/*_with_underscores_=*/true);
+}
diff --git a/test/clang-tidy/bugprone-exception-escape-openmp.cpp b/test/clang-tidy/bugprone-exception-escape-openmp.cpp
new file mode 100644
index 00000000..101c339b
--- /dev/null
+++ b/test/clang-tidy/bugprone-exception-escape-openmp.cpp
@@ -0,0 +1,29 @@
+// RUN: %check_clang_tidy %s bugprone-exception-escape %t -- -extra-arg=-fopenmp=libomp -extra-arg=-fexceptions --
+
+int thrower() {
+ throw 42;
+}
+
+void ok_parallel() {
+#pragma omp parallel
+ thrower();
+}
+
+void bad_for_header_XFAIL(const int a) noexcept {
+#pragma omp for
+ for (int i = 0; i < thrower(); i++)
+ ;
+ // FIXME: this really should be caught by bugprone-exception-escape.
+ // https://bugs.llvm.org/show_bug.cgi?id=41102
+}
+
+void ok_forloop(const int a) {
+#pragma omp for
+ for (int i = 0; i < a; i++)
+ thrower();
+}
+
+void some_exception_just_so_that_check_clang_tidy_shuts_up() noexcept {
+ thrower();
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:6: warning: an exception may be thrown in function 'some_exception_just_so_that_check_clang_tidy_shuts_up' which should not throw exceptions
diff --git a/test/clang-tidy/bugprone-parent-virtual-call.cpp b/test/clang-tidy/bugprone-parent-virtual-call.cpp
index ad845886..ad845886 100755..100644
--- a/test/clang-tidy/bugprone-parent-virtual-call.cpp
+++ b/test/clang-tidy/bugprone-parent-virtual-call.cpp
diff --git a/test/clang-tidy/bugprone-sizeof-expression.cpp b/test/clang-tidy/bugprone-sizeof-expression.cpp
index 683ad083..57b73ea4 100644
--- a/test/clang-tidy/bugprone-sizeof-expression.cpp
+++ b/test/clang-tidy/bugprone-sizeof-expression.cpp
@@ -231,6 +231,35 @@ int Test5() {
return sum;
}
+int Test6() {
+ int sum = 0;
+
+ struct S A = AsStruct(), B = AsStruct();
+ struct S *P = &A, *Q = &B;
+ sum += sizeof(struct S) == P - Q;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += 5 * sizeof(S) != P - Q;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += sizeof(S) < P - Q;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += 5 * sizeof(S) <= P - Q;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += 5 * sizeof(*P) >= P - Q;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += Q - P > 3 * sizeof(*P);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += sizeof(S) + (P - Q);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += 5 * sizeof(S) - (P - Q);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += (P - Q) / sizeof(S);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += (P - Q) / sizeof(*Q);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+
+ return sum;
+}
+
int ValidExpressions() {
int A[] = {1, 2, 3, 4};
static const char str[] = "hello";
diff --git a/test/clang-tidy/bugprone-string-constructor.cpp b/test/clang-tidy/bugprone-string-constructor.cpp
index 3ab4f424..9e11a32a 100644
--- a/test/clang-tidy/bugprone-string-constructor.cpp
+++ b/test/clang-tidy/bugprone-string-constructor.cpp
@@ -65,3 +65,11 @@ void Valid() {
std::string s2("test", 3);
std::string s3("test");
}
+
+namespace instantiation_dependent_exprs {
+template<typename T>
+struct S {
+ bool x;
+ std::string f() { return x ? "a" : "b"; }
+};
+}
diff --git a/test/clang-tidy/bugprone-string-integer-assignment.cpp b/test/clang-tidy/bugprone-string-integer-assignment.cpp
index c4e13fc4..18fe5ef4 100644
--- a/test/clang-tidy/bugprone-string-integer-assignment.cpp
+++ b/test/clang-tidy/bugprone-string-integer-assignment.cpp
@@ -7,18 +7,29 @@ struct basic_string {
basic_string& operator=(basic_string);
basic_string& operator+=(T);
basic_string& operator+=(basic_string);
+ const T &operator[](int i) const;
+ T &operator[](int i);
};
typedef basic_string<char> string;
typedef basic_string<wchar_t> wstring;
+
+int tolower(int i);
+int toupper(int i);
}
+int tolower(int i);
+int toupper(int i);
+
typedef int MyArcaneChar;
+constexpr char kCharConstant = 'a';
+
int main() {
std::string s;
std::wstring ws;
int x = 5;
+ const char c = 'c';
s = 6;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: an integer is interpreted as a character code when assigning {{.*}} [bugprone-string-integer-assignment]
@@ -47,7 +58,52 @@ int main() {
std::basic_string<MyArcaneChar> as;
as = 6;
-// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: an integer is interpreted as a chara
-// CHECK-FIXES: {{^}} as = 6;{{$}}
+ as = static_cast<MyArcaneChar>(6);
+ as = 'a';
+
+ s += toupper(x);
+ s += tolower(x);
+ s += (std::tolower(x));
+
+ s += c & s[1];
+ s += c ^ s[1];
+ s += c | s[1];
+
+ s[x] += 1;
+ s += s[x];
+ as += as[x];
+
+ // Likely character expressions.
+ s += x & 0xff;
+ s += 0xff & x;
+ s += x % 26;
+ s += 26 % x;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: an integer is interpreted as a chara
+ // CHECK-FIXES: {{^}} s += std::to_string(26 % x);{{$}}
+ s += c | 0x80;
+ s += c | 0x8000;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: an integer is interpreted as a chara
+ // CHECK-FIXES: {{^}} s += std::to_string(c | 0x8000);{{$}}
+ as += c | 0x8000;
+
+ s += 'a' + (x % 26);
+ s += kCharConstant + (x % 26);
+ s += 'a' + (s[x] & 0xf);
+ s += (x % 10) + 'b';
+
+ s += x > 255 ? c : x;
+ s += x > 255 ? 12 : x;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: an integer is interpreted as a chara
+ // CHECK-FIXES: {{^}} s += std::to_string(x > 255 ? 12 : x);{{$}}
+}
+
+namespace instantiation_dependent_exprs {
+template<typename T>
+struct S {
+ static constexpr T t = 0x8000;
+ std::string s;
+ void f(char c) { s += c | static_cast<int>(t); }
+};
+template S<int>;
}
diff --git a/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp b/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
new file mode 100644
index 00000000..d602a1d0
--- /dev/null
+++ b/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
@@ -0,0 +1,23 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- -- --target=x86_64-linux
+
+// MagnitudeBitsUpperLimit = 16 (default value)
+
+unsigned long size() { return 294967296l; }
+
+void voidFilteredOutForLoop1() {
+ for (long i = 0; i < size(); ++i) {
+ // no warning
+ }
+}
+
+void voidCaughtForLoop1() {
+ for (int i = 0; i < size(); ++i) {
+ // no warning
+ }
+}
+
+void voidCaughtForLoop2() {
+ for (short i = 0; i < size(); ++i) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'unsigned long' [bugprone-too-small-loop-variable]
+ }
+}
diff --git a/test/clang-tidy/bugprone-too-small-loop-variable.cpp b/test/clang-tidy/bugprone-too-small-loop-variable.cpp
index f11dd499..5a633559 100644
--- a/test/clang-tidy/bugprone-too-small-loop-variable.cpp
+++ b/test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -1,4 +1,8 @@
-// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- -- --target=x86_64-linux
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit, \
+// RUN: value: 1024}]}" \
+// RUN: -- --target=x86_64-linux
long size() { return 294967296l; }
diff --git a/test/clang-tidy/check_clang_tidy.py b/test/clang-tidy/check_clang_tidy.py
index 9768011a..5d808f40 100755
--- a/test/clang-tidy/check_clang_tidy.py
+++ b/test/clang-tidy/check_clang_tidy.py
@@ -2,10 +2,9 @@
#
#===- check_clang_tidy.py - ClangTidy Test Helper ------------*- python -*--===#
#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
+# 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
#
#===------------------------------------------------------------------------===#
diff --git a/test/clang-tidy/clang-tidy-diff.cpp b/test/clang-tidy/clang-tidy-diff.cpp
index 146287bf..2e18a43c 100644
--- a/test/clang-tidy/clang-tidy-diff.cpp
+++ b/test/clang-tidy/clang-tidy-diff.cpp
@@ -23,5 +23,4 @@ struct B : public A {
// CHECK-QUIET-NOT: warning:
};
// CHECK-SANITY-NOT: Suppressed
-// CHECK: Suppressed 1 warnings (1 due to line filter).
// CHECK-QUIET-NOT: Suppressed
diff --git a/test/clang-tidy/clang-tidy-mac-libcxx.cpp b/test/clang-tidy/clang-tidy-mac-libcxx.cpp
index 153a5d6e..d124a344 100644
--- a/test/clang-tidy/clang-tidy-mac-libcxx.cpp
+++ b/test/clang-tidy/clang-tidy-mac-libcxx.cpp
@@ -8,7 +8,7 @@
// RUN: cp -r %S/Inputs/mock-libcxx %t/
//
// Pretend clang is installed beside the mock library that we provided.
-// RUN: echo '[{"directory":"%t","command":"%t/mock-libcxx/bin/clang++ -stdlib=libc++ -target x86_64-apple-darwin -c test.cpp","file":"test.cpp"}]' | sed -e 's/\\/\//g' > %t/compile_commands.json
+// RUN: echo '[{"directory":"%t","command":"%t/mock-libcxx/bin/clang++ -stdlib=libc++ -std=c++11 -target x86_64-apple-darwin -c test.cpp","file":"test.cpp"}]' | sed -e 's/\\/\//g' > %t/compile_commands.json
// RUN: cp "%s" "%t/test.cpp"
// RUN: clang-tidy -header-filter='.*' -system-headers -checks='-*,modernize-use-using' "%t/test.cpp" | FileCheck %s
// CHECK: mock_vector:{{[0-9]+}}:{{[0-9]+}}: warning: use 'using' instead of 'typedef'
diff --git a/test/clang-tidy/cppcoreguidelines-macro-usage.cpp b/test/clang-tidy/cppcoreguidelines-macro-usage.cpp
index a4948f5b..edce328e 100644
--- a/test/clang-tidy/cppcoreguidelines-macro-usage.cpp
+++ b/test/clang-tidy/cppcoreguidelines-macro-usage.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s cppcoreguidelines-macro-usage %t
+// RUN: %check_clang_tidy %s cppcoreguidelines-macro-usage %t -- -header-filter=.* -system-headers --
#ifndef INCLUDE_GUARD
#define INCLUDE_GUARD
diff --git a/test/clang-tidy/expand-modular-headers-ppcallbacks.cpp b/test/clang-tidy/expand-modular-headers-ppcallbacks.cpp
new file mode 100644
index 00000000..d191922d
--- /dev/null
+++ b/test/clang-tidy/expand-modular-headers-ppcallbacks.cpp
@@ -0,0 +1,35 @@
+// Sanity-check. Run without modules:
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: cp %S/Inputs/expand-modular-headers-ppcallbacks/* %t/
+// RUN: %check_clang_tidy %s readability-identifier-naming %t/without-modules -- \
+// RUN: -config="CheckOptions: [{ \
+// RUN: key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE }]" \
+// RUN: -header-filter=.* \
+// RUN: -- -x c++ -std=c++11 -I%t/
+//
+// Run clang-tidy on a file with modular includes:
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: cp %S/Inputs/expand-modular-headers-ppcallbacks/* %t/
+// RUN: %check_clang_tidy %s readability-identifier-naming %t/with-modules -- \
+// RUN: -config="CheckOptions: [{ \
+// RUN: key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE }]" \
+// RUN: -header-filter=.* \
+// RUN: -- -x c++ -std=c++11 -I%t/ \
+// RUN: -fmodules -fimplicit-modules -fno-implicit-module-maps \
+// RUN: -fmodule-map-file=%t/module.modulemap \
+// RUN: -fmodules-cache-path=%t/module-cache/
+#include "c.h"
+
+// CHECK-MESSAGES: a.h:1:9: warning: invalid case style for macro definition 'a' [readability-identifier-naming]
+// CHECK-MESSAGES: a.h:1:9: note: FIX-IT applied suggested code changes
+// CHECK-MESSAGES: b.h:2:9: warning: invalid case style for macro definition 'b'
+// CHECK-MESSAGES: b.h:2:9: note: FIX-IT applied suggested code changes
+// CHECK-MESSAGES: c.h:2:9: warning: invalid case style for macro definition 'c'
+// CHECK-MESSAGES: c.h:2:9: note: FIX-IT applied suggested code changes
+
+#define m
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for macro definition 'm'
+// CHECK-MESSAGES: :[[@LINE-2]]:9: note: FIX-IT applied suggested code changes
diff --git a/test/clang-tidy/export-diagnostics.cpp b/test/clang-tidy/export-diagnostics.cpp
index 5eda2042..14a6a40d 100644
--- a/test/clang-tidy/export-diagnostics.cpp
+++ b/test/clang-tidy/export-diagnostics.cpp
@@ -13,16 +13,19 @@ X(f)
// CHECK-YAML-NEXT: MainSourceFile: '{{.*}}-input.cpp'
// CHECK-YAML-NEXT: Diagnostics:
// CHECK-YAML-NEXT: - DiagnosticName: clang-diagnostic-missing-prototypes
-// CHECK-YAML-NEXT: Message: 'no previous prototype for function ''ff'''
-// CHECK-YAML-NEXT: FileOffset: 30
-// CHECK-YAML-NEXT: FilePath: '{{.*}}-input.cpp'
+// CHECK-YAML-NEXT: DiagnosticMessage:
+// CHECK-YAML-NEXT: Message: 'no previous prototype for function
+// ''ff'''
+// CHECK-YAML-NEXT: FilePath: '{{.*}}-input.cpp'
+// CHECK-YAML-NEXT: FileOffset: 30
+// CHECK-YAML-NEXT: Replacements: []
// CHECK-YAML-NEXT: Notes:
// CHECK-YAML-NEXT: - Message: 'expanded from macro ''X'''
// CHECK-YAML-NEXT: FilePath: '{{.*}}-input.cpp'
// CHECK-YAML-NEXT: FileOffset: 18
+// CHECK-YAML-NEXT: Replacements: []
// CHECK-YAML-NEXT: - Message: expanded from here
// CHECK-YAML-NEXT: FilePath: ''
// CHECK-YAML-NEXT: FileOffset: 0
-// CHECK-YAML-NEXT: Replacements: []
+// CHECK-YAML-NEXT: Replacements: []
// CHECK-YAML-NEXT: ...
-
diff --git a/test/clang-tidy/google-objc-function-naming.m b/test/clang-tidy/google-objc-function-naming.m
index d0336d26..01433d9f 100644
--- a/test/clang-tidy/google-objc-function-naming.m
+++ b/test/clang-tidy/google-objc-function-naming.m
@@ -1,4 +1,12 @@
-// RUN: %check_clang_tidy %s google-objc-function-naming %t
+// RUN: %check_clang_tidy %s google-objc-function-naming %t -- -- -isystem %S/Inputs/Headers
+
+#include <stdio.h>
+
+static void TestImplicitFunctionDeclaration(int a) {
+ // Call a builtin function so that the compiler generates an implicit
+ // function declaration.
+ printf("%d", a);
+}
typedef _Bool bool;
diff --git a/test/clang-tidy/google-objc-global-variable-declaration.mm b/test/clang-tidy/google-objc-global-variable-declaration.mm
new file mode 100644
index 00000000..a6b0f6ee
--- /dev/null
+++ b/test/clang-tidy/google-objc-global-variable-declaration.mm
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s google-objc-global-variable-declaration %t
+
+@class NSString;
+static NSString* const myConstString = @"hello";
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: const global variable 'myConstString' must have a name which starts with an appropriate prefix [google-objc-global-variable-declaration]
+// CHECK-FIXES: static NSString* const kMyConstString = @"hello";
+
+class MyTest {
+ static int not_objc_style;
+};
diff --git a/test/clang-tidy/google-runtime-int.m b/test/clang-tidy/google-runtime-int.m
new file mode 100644
index 00000000..dd1225c9
--- /dev/null
+++ b/test/clang-tidy/google-runtime-int.m
@@ -0,0 +1,32 @@
+// RUN: clang-tidy -checks=-*,google-runtime-int %s 2>&1 -- | count 0
+// RUN: clang-tidy -checks=-*,google-runtime-int %s 2>&1 -- -x objective-c++ | count 0
+
+typedef long NSInteger;
+typedef unsigned long NSUInteger;
+
+@interface NSString
+@property(readonly) NSInteger integerValue;
+@property(readonly) long long longLongValue;
+@property(readonly) NSUInteger length;
+@end
+
+NSInteger Foo(NSString *s) {
+ return [s integerValue];
+}
+
+long long Bar(NSString *s) {
+ return [s longLongValue];
+}
+
+NSUInteger Baz(NSString *s) {
+ return [s length];
+}
+
+unsigned short NSSwapShort(unsigned short inv);
+
+long DoSomeMath(long a, short b) {
+ short c = NSSwapShort(b);
+ long a2 = a * 5L;
+ return a2 + c;
+}
+
diff --git a/test/clang-tidy/llvm-prefer-isa-or-dyn-cast-in-conditionals.cpp b/test/clang-tidy/llvm-prefer-isa-or-dyn-cast-in-conditionals.cpp
new file mode 100644
index 00000000..48652d52
--- /dev/null
+++ b/test/clang-tidy/llvm-prefer-isa-or-dyn-cast-in-conditionals.cpp
@@ -0,0 +1,132 @@
+// RUN: %check_clang_tidy %s llvm-prefer-isa-or-dyn-cast-in-conditionals %t
+
+struct X;
+struct Y;
+struct Z {
+ int foo();
+ X *bar();
+ X *cast(Y*);
+ bool baz(Y*);
+};
+
+template <class X, class Y>
+bool isa(Y *);
+template <class X, class Y>
+X *cast(Y *);
+template <class X, class Y>
+X *dyn_cast(Y *);
+template <class X, class Y>
+X *dyn_cast_or_null(Y *);
+
+bool foo(Y *y, Z *z) {
+ if (auto x = cast<X>(y))
+ return true;
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: cast<> in conditional will assert rather than return a null pointer [llvm-prefer-isa-or-dyn-cast-in-conditionals]
+ // CHECK-FIXES: if (auto x = dyn_cast<X>(y))
+
+ while (auto x = cast<X>(y))
+ break;
+ // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: cast<> in conditional
+ // CHECK-FIXES: while (auto x = dyn_cast<X>(y))
+
+ if (cast<X>(y))
+ return true;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: cast<> in conditional
+ // CHECK-FIXES: if (isa<X>(y))
+
+ while (cast<X>(y))
+ break;
+ // CHECK-MESSAGES: :[[@LINE-2]]:10: warning: cast<> in conditional
+ // CHECK-FIXES: while (isa<X>(y))
+
+ do {
+ break;
+ } while (cast<X>(y));
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: cast<> in conditional
+ // CHECK-FIXES: while (isa<X>(y));
+
+ if (dyn_cast<X>(y))
+ return true;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: return value from dyn_cast<> not used [llvm-prefer-isa-or-dyn-cast-in-conditionals]
+ // CHECK-FIXES: if (isa<X>(y))
+
+ while (dyn_cast<X>(y))
+ break;
+ // CHECK-MESSAGES: :[[@LINE-2]]:10: warning: return value from dyn_cast<> not used
+ // CHECK-FIXES: while (isa<X>(y))
+
+ do {
+ break;
+ } while (dyn_cast<X>(y));
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: return value from dyn_cast<> not used
+ // CHECK-FIXES: while (isa<X>(y));
+
+ if (y && isa<X>(y))
+ return true;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred over an explicit test for null followed by calling isa<> [llvm-prefer-isa-or-dyn-cast-in-conditionals]
+ // CHECK-FIXES: if (isa_and_nonnull<X>(y))
+
+ if (z->bar() && isa<Y>(z->bar()))
+ return true;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred
+ // CHECK-FIXES: if (isa_and_nonnull<Y>(z->bar()))
+
+ if (z->bar() && cast<Y>(z->bar()))
+ return true;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred
+ // CHECK-FIXES: if (isa_and_nonnull<Y>(z->bar()))
+
+ if (z->bar() && dyn_cast<Y>(z->bar()))
+ return true;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred
+ // CHECK-FIXES: if (isa_and_nonnull<Y>(z->bar()))
+
+ if (z->bar() && dyn_cast_or_null<Y>(z->bar()))
+ return true;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred
+ // CHECK-FIXES: if (isa_and_nonnull<Y>(z->bar()))
+
+ bool b = z->bar() && cast<Y>(z->bar());
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: isa_and_nonnull<> is preferred
+ // CHECK-FIXES: bool b = isa_and_nonnull<Y>(z->bar());
+
+ // These don't trigger a warning.
+ if (auto x = cast<Z>(y)->foo())
+ return true;
+ if (auto x = z->cast(y))
+ return true;
+ while (auto x = cast<Z>(y)->foo())
+ break;
+ if (cast<Z>(y)->foo())
+ return true;
+ if (z->cast(y))
+ return true;
+ while (cast<Z>(y)->foo())
+ break;
+ if (y && cast<X>(z->bar()))
+ return true;
+ if (z && cast<Z>(y)->foo())
+ return true;
+ bool b2 = y && cast<X>(z);
+ if(z->cast(y))
+ return true;
+ if (z->baz(cast<Y>(z)))
+ return true;
+
+#define CAST(T, Obj) cast<T>(Obj)
+#define AUTO_VAR_CAST(X, Y, Z) auto X = cast<Y>(Z)
+#define ISA(T, Obj) isa<T>(Obj)
+#define ISA_OR_NULL(T, Obj) Obj &&isa<T>(Obj)
+
+ // Macros don't trigger warning.
+ if (auto x = CAST(X, y))
+ return true;
+ if (AUTO_VAR_CAST(x, X, z))
+ return true;
+ if (z->bar() && ISA(Y, z->bar()))
+ return true;
+ if (ISA_OR_NULL(Y, z->bar()))
+ return true;
+
+ return false;
+}
diff --git a/test/clang-tidy/misc-non-private-member-variables-in-classes.cpp b/test/clang-tidy/misc-non-private-member-variables-in-classes.cpp
index 31052716..2a93ff6a 100644
--- a/test/clang-tidy/misc-non-private-member-variables-in-classes.cpp
+++ b/test/clang-tidy/misc-non-private-member-variables-in-classes.cpp
@@ -35,6 +35,23 @@ private:
int S1_v3;
};
+// Only data and implicit or static methods, do not warn
+
+class C {
+public:
+ C() {}
+ ~C() {}
+};
+
+struct S1Implicit {
+ C S1Implicit_v0;
+};
+
+struct S1ImplicitAndStatic {
+ C S1Implicit_v0;
+ static void s() {}
+};
+
//----------------------------------------------------------------------------//
// All functions are static, do not warn.
diff --git a/test/clang-tidy/modernize-avoid-bind.cpp b/test/clang-tidy/modernize-avoid-bind.cpp
index 1c78b9e6..721801be 100644
--- a/test/clang-tidy/modernize-avoid-bind.cpp
+++ b/test/clang-tidy/modernize-avoid-bind.cpp
@@ -77,3 +77,47 @@ void n() {
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind
// CHECK-FIXES: auto clj = [] { return C::add(1, 1); };
}
+
+// Let's fake a minimal std::function-like facility.
+namespace std {
+template <typename _Tp>
+_Tp declval();
+
+template <typename _Functor, typename... _ArgTypes>
+struct __res {
+ template <typename... _Args>
+ static decltype(declval<_Functor>()(_Args()...)) _S_test(int);
+
+ template <typename...>
+ static void _S_test(...);
+
+ using type = decltype(_S_test<_ArgTypes...>(0));
+};
+
+template <typename>
+struct function;
+
+template <typename... _ArgTypes>
+struct function<void(_ArgTypes...)> {
+ template <typename _Functor,
+ typename = typename __res<_Functor, _ArgTypes...>::type>
+ function(_Functor) {}
+};
+} // namespace std
+
+struct Thing {};
+void UseThing(Thing *);
+
+struct Callback {
+ Callback();
+ Callback(std::function<void()>);
+ void Reset(std::function<void()>);
+};
+
+void test(Thing *t) {
+ Callback cb;
+ if (t)
+ cb.Reset(std::bind(UseThing, t));
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: prefer a lambda to std::bind
+ // CHECK-FIXES: cb.Reset([=] { return UseThing(t); });
+}
diff --git a/test/clang-tidy/modernize-avoid-c-arrays-ignores-main.cpp b/test/clang-tidy/modernize-avoid-c-arrays-ignores-main.cpp
new file mode 100644
index 00000000..6549422f
--- /dev/null
+++ b/test/clang-tidy/modernize-avoid-c-arrays-ignores-main.cpp
@@ -0,0 +1,18 @@
+// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t
+
+int not_main(int argc, char *argv[]) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not declare C-style arrays, use std::array<> instead
+ int f4[] = {1, 2};
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+}
+
+int main(int argc, char *argv[]) {
+ int f5[] = {1, 2};
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+
+ auto not_main = [](int argc, char *argv[]) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: do not declare C-style arrays, use std::array<> instead
+ int f6[] = {1, 2};
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not declare C-style arrays, use std::array<> instead
+ };
+}
diff --git a/test/clang-tidy/modernize-avoid-c-arrays-ignores-three-arg-main.cpp b/test/clang-tidy/modernize-avoid-c-arrays-ignores-three-arg-main.cpp
new file mode 100644
index 00000000..22a4016f
--- /dev/null
+++ b/test/clang-tidy/modernize-avoid-c-arrays-ignores-three-arg-main.cpp
@@ -0,0 +1,20 @@
+// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t
+
+int not_main(int argc, char *argv[], char *argw[]) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not declare C-style arrays, use std::array<> instead
+ // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: do not declare C-style arrays, use std::array<> instead
+ int f4[] = {1, 2};
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+}
+
+int main(int argc, char *argv[], char *argw[]) {
+ int f5[] = {1, 2};
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
+
+ auto not_main = [](int argc, char *argv[], char *argw[]) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: do not declare C-style arrays, use std::array<> instead
+ // CHECK-MESSAGES: :[[@LINE-2]]:46: warning: do not declare C-style arrays, use std::array<> instead
+ int f6[] = {1, 2};
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not declare C-style arrays, use std::array<> instead
+ };
+}
diff --git a/test/clang-tidy/modernize-redundant-void-arg.cpp b/test/clang-tidy/modernize-redundant-void-arg.cpp
index 44a726b5..0fad5d55 100644
--- a/test/clang-tidy/modernize-redundant-void-arg.cpp
+++ b/test/clang-tidy/modernize-redundant-void-arg.cpp
@@ -489,6 +489,13 @@ void lambda_expression_with_macro_test(){
// CHECK-FIXES: []() BODY;
}
+namespace qqq {
+void foo() BODY
+void bar(void) BODY;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: redundant void argument list in function definition
+// CHECK-FIXES: void bar() BODY;
+}
+
struct S_1 {
void g_1(void) const {
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant void argument list in function definition [modernize-redundant-void-arg]
diff --git a/test/clang-tidy/modernize-use-default-member-init-assignment.cpp b/test/clang-tidy/modernize-use-default-member-init-assignment.cpp
index fdc0db18..b98055c9 100644
--- a/test/clang-tidy/modernize-use-default-member-init-assignment.cpp
+++ b/test/clang-tidy/modernize-use-default-member-init-assignment.cpp
@@ -166,6 +166,14 @@ struct PositiveEnum {
// CHECK-FIXES: Enum e = Foo;
};
+struct PositiveValueEnum {
+ PositiveValueEnum() : e() {}
+ // CHECK-FIXES: PositiveValueEnum() {}
+ Enum e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'e'
+ // CHECK-FIXES: Enum e{};
+};
+
struct PositiveString {
PositiveString() : s("foo") {}
// CHECK-FIXES: PositiveString() {}
diff --git a/test/clang-tidy/modernize-use-default-member-init.cpp b/test/clang-tidy/modernize-use-default-member-init.cpp
index 0ed65df3..825bfa0b 100644
--- a/test/clang-tidy/modernize-use-default-member-init.cpp
+++ b/test/clang-tidy/modernize-use-default-member-init.cpp
@@ -165,6 +165,14 @@ struct PositiveEnum {
// CHECK-FIXES: Enum e{Foo};
};
+struct PositiveValueEnum {
+ PositiveValueEnum() : e() {}
+ // CHECK-FIXES: PositiveValueEnum() {}
+ Enum e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'e'
+ // CHECK-FIXES: Enum e{};
+};
+
struct PositiveString {
PositiveString() : s("foo") {}
// CHECK-FIXES: PositiveString() {}
@@ -382,6 +390,16 @@ struct ExistingString {
const char *e4 = "bar";
};
+struct UnionExisting {
+ UnionExisting() : e(5.0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: member initializer for 'e' is redundant
+ // CHECK-FIXES: UnionExisting() {}
+ union {
+ int i;
+ double e = 5.0;
+ };
+};
+
template <typename T>
struct NegativeTemplateExisting {
NegativeTemplateExisting(int) : t(0) {}
diff --git a/test/clang-tidy/modernize-use-override-no-destructors.cpp b/test/clang-tidy/modernize-use-override-no-destructors.cpp
new file mode 100644
index 00000000..eaadb07b
--- /dev/null
+++ b/test/clang-tidy/modernize-use-override-no-destructors.cpp
@@ -0,0 +1,16 @@
+// RUN: %check_clang_tidy %s modernize-use-override %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-override.IgnoreDestructors, value: 1}]}" \
+// RUN: -- -std=c++11
+
+struct Base {
+ virtual ~Base();
+ virtual void f();
+};
+
+struct Simple : public Base {
+ virtual ~Simple();
+ // CHECK-MESSAGES-NOT: warning:
+ virtual void f();
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void f() override;
+};
diff --git a/test/clang-tidy/modernize-use-override-with-macro.cpp b/test/clang-tidy/modernize-use-override-with-macro.cpp
new file mode 100644
index 00000000..ad682f15
--- /dev/null
+++ b/test/clang-tidy/modernize-use-override-with-macro.cpp
@@ -0,0 +1,70 @@
+// RUN: %check_clang_tidy %s modernize-use-override %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-override.OverrideSpelling, value: 'OVERRIDE'},{key: modernize-use-override.FinalSpelling, value: 'FINAL'}]}" \
+// RUN: -- -std=c++11
+
+#define ABSTRACT = 0
+
+#define OVERRIDE override
+#define FINAL final
+#define VIRTUAL virtual
+#define NOT_VIRTUAL
+#define NOT_OVERRIDE
+
+#define MUST_USE_RESULT __attribute__((warn_unused_result))
+#define UNUSED __attribute__((unused))
+
+struct Base {
+ virtual ~Base() {}
+ virtual void a();
+ virtual void b();
+ virtual void c();
+ virtual void e() = 0;
+ virtual void f2() const = 0;
+ virtual void g() = 0;
+ virtual void j() const;
+ virtual void k() = 0;
+ virtual void l() const;
+};
+
+struct SimpleCases : public Base {
+public:
+ virtual ~SimpleCases();
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: prefer using 'OVERRIDE' or (rarely) 'FINAL' instead of 'virtual' [modernize-use-override]
+ // CHECK-FIXES: {{^}} ~SimpleCases() OVERRIDE;
+
+ void a();
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: annotate this function with 'OVERRIDE' or (rarely) 'FINAL' [modernize-use-override]
+ // CHECK-FIXES: {{^}} void a() OVERRIDE;
+
+ virtual void b();
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using 'OVERRIDE' or (rarely) 'FINAL' instead of 'virtual' [modernize-use-override]
+ // CHECK-FIXES: {{^}} void b() OVERRIDE;
+
+ virtual void c();
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void c() OVERRIDE;
+
+ virtual void e() = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void e() OVERRIDE = 0;
+
+ virtual void f2() const = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void f2() const OVERRIDE = 0;
+
+ virtual void g() ABSTRACT;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void g() OVERRIDE ABSTRACT;
+
+ virtual void j() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+ // CHECK-FIXES: {{^}} void j() const OVERRIDE;
+
+ virtual void k() OVERRIDE;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant since the function is already declared 'OVERRIDE' [modernize-use-override]
+ // CHECK-FIXES: {{^}} void k() OVERRIDE;
+
+ virtual void l() const OVERRIDE;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant since the function is already declared 'OVERRIDE' [modernize-use-override]
+ // CHECK-FIXES: {{^}} void l() const OVERRIDE;
+};
diff --git a/test/clang-tidy/modernize-use-override-with-no-macro-inscope.cpp b/test/clang-tidy/modernize-use-override-with-no-macro-inscope.cpp
new file mode 100644
index 00000000..97b71053
--- /dev/null
+++ b/test/clang-tidy/modernize-use-override-with-no-macro-inscope.cpp
@@ -0,0 +1,28 @@
+// RUN: %check_clang_tidy %s modernize-use-override %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-override.OverrideSpelling, value: 'CUSTOM_OVERRIDE'},{key: modernize-use-override.FinalSpelling, value: 'CUSTOM_FINAL'}]}" \
+// RUN: -- -std=c++11
+
+// As if the macro was not defined.
+//#define CUSTOM_OVERRIDE override
+//#define CUSTOM_FINAL override
+
+struct Base {
+ virtual ~Base() {}
+ virtual void a();
+ virtual void b();
+};
+
+struct SimpleCases : public Base {
+public:
+ virtual ~SimpleCases();
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: prefer using 'CUSTOM_OVERRIDE' or (rarely) 'CUSTOM_FINAL' instead of 'virtual' [modernize-use-override]
+ // CHECK-FIXES: {{^}} virtual ~SimpleCases();
+
+ void a();
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: annotate this function with 'CUSTOM_OVERRIDE' or (rarely) 'CUSTOM_FINAL' [modernize-use-override]
+ // CHECK-FIXES: {{^}} void a();
+
+ virtual void b();
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using 'CUSTOM_OVERRIDE' or (rarely) 'CUSTOM_FINAL' instead of 'virtual' [modernize-use-override]
+ // CHECK-FIXES: {{^}} virtual void b();
+};
diff --git a/test/clang-tidy/nolint.cpp b/test/clang-tidy/nolint.cpp
index 24c37228..a2d2c10a 100644
--- a/test/clang-tidy/nolint.cpp
+++ b/test/clang-tidy/nolint.cpp
@@ -31,6 +31,7 @@ void f() {
int i;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: unused variable 'i' [clang-diagnostic-unused-variable]
int j; // NOLINT
+ int k; // NOLINT(clang-diagnostic-unused-variable)
}
#define MACRO(X) class X { X(int i); };
@@ -47,4 +48,4 @@ MACRO_NOLINT
#define DOUBLE_MACRO MACRO(H) // NOLINT
DOUBLE_MACRO
-// CHECK-MESSAGES: Suppressed 12 warnings (12 NOLINT)
+// CHECK-MESSAGES: Suppressed 13 warnings (13 NOLINT)
diff --git a/test/clang-tidy/objc-property-declaration.m b/test/clang-tidy/objc-property-declaration.m
index 07a06205..b56bdcd1 100644
--- a/test/clang-tidy/objc-property-declaration.m
+++ b/test/clang-tidy/objc-property-declaration.m
@@ -46,6 +46,7 @@ typedef void *CGColorRef;
@property(strong, nonatomic) NSString *URLStr;
@property(assign, nonatomic) int abc_camelCase;
@property(strong, nonatomic) NSString *abc_URL;
+@property(strong, nonatomic) NSString *opac2_sourceComponent;
@end
@interface Foo ()
diff --git a/test/clang-tidy/objc-super-self.m b/test/clang-tidy/objc-super-self.m
new file mode 100644
index 00000000..9653cd22
--- /dev/null
+++ b/test/clang-tidy/objc-super-self.m
@@ -0,0 +1,86 @@
+// RUN: %check_clang_tidy %s objc-super-self %t
+
+@interface NSObject
+- (instancetype)init;
+- (instancetype)self;
+@end
+
+@interface NSObjectDerivedClass : NSObject
+@end
+
+@implementation NSObjectDerivedClass
+
+- (instancetype)init {
+ return [super self];
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious invocation of 'self' in initializer; did you mean to invoke a superclass initializer? [objc-super-self]
+// CHECK-FIXES: return [super init];
+}
+
+- (instancetype)initWithObject:(NSObject *)obj {
+ self = [super self];
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious invocation of 'self' in initializer; did you mean to invoke a superclass initializer? [objc-super-self]
+// CHECK-FIXES: self = [super init];
+ if (self) {
+ // ...
+ }
+ return self;
+}
+
+#define INITIALIZE() [super self]
+
+- (instancetype)initWithObject:(NSObject *)objc a:(int)a {
+ return INITIALIZE();
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious invocation of 'self' in initializer; did you mean to invoke a superclass initializer? [objc-super-self]
+// CHECK-FIXES: return INITIALIZE();
+}
+
+#define INITIALIZER_IMPL() return [super self]
+
+- (instancetype)initWithObject:(NSObject *)objc b:(int)b {
+ INITIALIZER_IMPL();
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: suspicious invocation of 'self' in initializer; did you mean to invoke a superclass initializer? [objc-super-self]
+// CHECK-FIXES: INITIALIZER_IMPL();
+}
+
+#define INITIALIZER_METHOD self
+
+- (instancetype)initWithObject:(NSObject *)objc c:(int)c {
+ return [super INITIALIZER_METHOD];
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious invocation of 'self' in initializer; did you mean to invoke a superclass initializer? [objc-super-self]
+// CHECK-FIXES: return [super INITIALIZER_METHOD];
+}
+
+#define RECEIVER super
+
+- (instancetype)initWithObject:(NSObject *)objc d:(int)d {
+ return [RECEIVER self];
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious invocation of 'self' in initializer; did you mean to invoke a superclass initializer? [objc-super-self]
+// CHECK-FIXES: return [RECEIVER self];
+}
+
+- (instancetype)foo {
+ return [super self];
+}
+
+- (instancetype)bar {
+ return [self self];
+}
+
+@end
+
+@interface RootClass
+- (instancetype)init;
+- (instancetype)self;
+@end
+
+@interface NotNSObjectDerivedClass : RootClass
+@end
+
+@implementation NotNSObjectDerivedClass
+
+- (instancetype)init {
+ return [super self];
+}
+
+@end
+
diff --git a/test/clang-tidy/openmp-exception-escape.cpp b/test/clang-tidy/openmp-exception-escape.cpp
new file mode 100644
index 00000000..73345836
--- /dev/null
+++ b/test/clang-tidy/openmp-exception-escape.cpp
@@ -0,0 +1,132 @@
+// RUN: %check_clang_tidy %s openmp-exception-escape %t -- -extra-arg=-fopenmp=libomp -extra-arg=-fexceptions -config="{CheckOptions: [{key: openmp-exception-escape.IgnoredExceptions, value: 'ignored, ignored2'}]}" --
+
+int thrower() {
+ throw 42;
+}
+
+class ignored {};
+class ignored2 {};
+namespace std {
+class bad_alloc {};
+} // namespace std
+
+void parallel() {
+#pragma omp parallel
+ thrower();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception thrown inside of the OpenMP 'parallel' region is not caught in that same region
+}
+
+void ignore() {
+#pragma omp parallel
+ throw ignored();
+}
+
+void ignore2() {
+#pragma omp parallel
+ throw ignored2();
+}
+
+void standalone_directive() {
+#pragma omp taskwait
+ throw ignored(); // not structured block
+}
+
+void ignore_alloc() {
+#pragma omp parallel
+ throw std::bad_alloc();
+}
+
+void parallel_caught() {
+#pragma omp parallel
+ {
+ try {
+ thrower();
+ } catch (...) {
+ }
+ }
+}
+
+void for_header(const int a) {
+ // Only the body of the loop counts.
+#pragma omp for
+ for (int i = 0; i < thrower(); i++)
+ ;
+}
+
+void forloop(const int a) {
+#pragma omp for
+ for (int i = 0; i < a; i++)
+ thrower();
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception thrown inside of the OpenMP 'for' region is not caught in that same region
+}
+
+void parallel_forloop(const int a) {
+#pragma omp parallel
+ {
+#pragma omp for
+ for (int i = 0; i < a; i++)
+ thrower();
+ thrower();
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: an exception thrown inside of the OpenMP 'parallel' region is not caught in that same region
+ // CHECK-MESSAGES: :[[@LINE-3]]:7: warning: an exception thrown inside of the OpenMP 'for' region is not caught in that same region
+ }
+}
+
+void parallel_forloop_caught(const int a) {
+#pragma omp parallel
+ {
+#pragma omp for
+ for (int i = 0; i < a; i++) {
+ try {
+ thrower();
+ } catch (...) {
+ }
+ }
+ thrower();
+ // CHECK-MESSAGES: :[[@LINE-9]]:3: warning: an exception thrown inside of the OpenMP 'parallel' region is not caught in that same region
+ }
+}
+
+void parallel_caught_forloop(const int a) {
+#pragma omp parallel
+ {
+#pragma omp for
+ for (int i = 0; i < a; i++)
+ thrower();
+ try {
+ thrower();
+ } catch (...) {
+ }
+ // CHECK-MESSAGES: :[[@LINE-5]]:7: warning: an exception thrown inside of the OpenMP 'for' region is not caught in that same region
+ }
+}
+
+void parallel_outercaught_forloop(const int a) {
+#pragma omp parallel
+ {
+ try {
+#pragma omp for
+ for (int i = 0; i < a; i++)
+ thrower();
+ thrower();
+ } catch (...) {
+ }
+ // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: an exception thrown inside of the OpenMP 'for' region is not caught in that same region
+ }
+}
+
+void parallel_outercaught_forloop_caught(const int a) {
+#pragma omp parallel
+ {
+ try {
+#pragma omp for
+ for (int i = 0; i < a; i++) {
+ try {
+ thrower();
+ } catch (...) {
+ }
+ }
+ } catch (...) {
+ }
+ }
+}
diff --git a/test/clang-tidy/openmp-use-default-none.cpp b/test/clang-tidy/openmp-use-default-none.cpp
new file mode 100644
index 00000000..1a374bde
--- /dev/null
+++ b/test/clang-tidy/openmp-use-default-none.cpp
@@ -0,0 +1,160 @@
+// RUN: %check_clang_tidy %s openmp-use-default-none %t -- -- -x c++ -fopenmp=libomp -fopenmp-version=40
+// RUN: %check_clang_tidy %s openmp-use-default-none %t -- -- -x c -fopenmp=libomp -fopenmp-version=40
+
+//----------------------------------------------------------------------------//
+// Null cases.
+//----------------------------------------------------------------------------//
+
+// 'for' directive can not have 'default' clause, no diagnostics.
+void n0(const int a) {
+#pragma omp for
+ for (int b = 0; b < a; b++)
+ ;
+}
+
+//----------------------------------------------------------------------------//
+// Single-directive positive cases.
+//----------------------------------------------------------------------------//
+
+// 'parallel' directive.
+
+// 'parallel' directive can have 'default' clause, but said clause is not
+// specified, diagnosed.
+void p0_0() {
+#pragma omp parallel
+ ;
+ // CHECK-NOTES: :[[@LINE-2]]:9: warning: OpenMP directive 'parallel' does not specify 'default' clause, consider specifying 'default(none)' clause
+}
+
+// 'parallel' directive can have 'default' clause, and said clause specified,
+// with 'none' kind, all good.
+void p0_1() {
+#pragma omp parallel default(none)
+ ;
+}
+
+// 'parallel' directive can have 'default' clause, and said clause specified,
+// but with 'shared' kind, which is not 'none', diagnose.
+void p0_2() {
+#pragma omp parallel default(shared)
+ ;
+ // CHECK-NOTES: :[[@LINE-2]]:9: warning: OpenMP directive 'parallel' specifies 'default(shared)' clause, consider using 'default(none)' clause instead
+ // CHECK-NOTES: :[[@LINE-3]]:22: note: existing 'default' clause specified here
+}
+
+// 'task' directive.
+
+// 'task' directive can have 'default' clause, but said clause is not
+// specified, diagnosed.
+void p1_0() {
+#pragma omp task
+ ;
+ // CHECK-NOTES: :[[@LINE-2]]:9: warning: OpenMP directive 'task' does not specify 'default' clause, consider specifying 'default(none)' clause
+}
+
+// 'task' directive can have 'default' clause, and said clause specified,
+// with 'none' kind, all good.
+void p1_1() {
+#pragma omp task default(none)
+ ;
+}
+
+// 'task' directive can have 'default' clause, and said clause specified,
+// but with 'shared' kind, which is not 'none', diagnose.
+void p1_2() {
+#pragma omp task default(shared)
+ ;
+ // CHECK-NOTES: :[[@LINE-2]]:9: warning: OpenMP directive 'task' specifies 'default(shared)' clause, consider using 'default(none)' clause instead
+ // CHECK-NOTES: :[[@LINE-3]]:18: note: existing 'default' clause specified here
+}
+
+// 'teams' directive. (has to be inside of 'target' directive)
+
+// 'teams' directive can have 'default' clause, but said clause is not
+// specified, diagnosed.
+void p2_0() {
+#pragma omp target
+#pragma omp teams
+ ;
+ // CHECK-NOTES: :[[@LINE-2]]:9: warning: OpenMP directive 'teams' does not specify 'default' clause, consider specifying 'default(none)' clause
+}
+
+// 'teams' directive can have 'default' clause, and said clause specified,
+// with 'none' kind, all good.
+void p2_1() {
+#pragma omp target
+#pragma omp teams default(none)
+ ;
+}
+
+// 'teams' directive can have 'default' clause, and said clause specified,
+// but with 'shared' kind, which is not 'none', diagnose.
+void p2_2() {
+#pragma omp target
+#pragma omp teams default(shared)
+ ;
+ // CHECK-NOTES: :[[@LINE-2]]:9: warning: OpenMP directive 'teams' specifies 'default(shared)' clause, consider using 'default(none)' clause instead
+ // CHECK-NOTES: :[[@LINE-3]]:19: note: existing 'default' clause specified here
+}
+
+// 'taskloop' directive.
+
+// 'taskloop' directive can have 'default' clause, but said clause is not
+// specified, diagnosed.
+void p3_0(const int a) {
+#pragma omp taskloop
+ for (int b = 0; b < a; b++)
+ ;
+ // CHECK-NOTES: :[[@LINE-3]]:9: warning: OpenMP directive 'taskloop' does not specify 'default' clause, consider specifying 'default(none)' clause
+}
+
+// 'taskloop' directive can have 'default' clause, and said clause specified,
+// with 'none' kind, all good.
+void p3_1(const int a) {
+#pragma omp taskloop default(none) shared(a)
+ for (int b = 0; b < a; b++)
+ ;
+}
+
+// 'taskloop' directive can have 'default' clause, and said clause specified,
+// but with 'shared' kind, which is not 'none', diagnose.
+void p3_2(const int a) {
+#pragma omp taskloop default(shared)
+ for (int b = 0; b < a; b++)
+ ;
+ // CHECK-NOTES: :[[@LINE-3]]:9: warning: OpenMP directive 'taskloop' specifies 'default(shared)' clause, consider using 'default(none)' clause instead
+ // CHECK-NOTES: :[[@LINE-4]]:22: note: existing 'default' clause specified here
+}
+
+//----------------------------------------------------------------------------//
+// Combined directives.
+// Let's not test every single possible permutation/combination of directives,
+// but just *one* combined directive. The rest will be the same.
+//----------------------------------------------------------------------------//
+
+// 'parallel' directive can have 'default' clause, but said clause is not
+// specified, diagnosed.
+void p4_0(const int a) {
+#pragma omp parallel for
+ for (int b = 0; b < a; b++)
+ ;
+ // CHECK-NOTES: :[[@LINE-3]]:9: warning: OpenMP directive 'parallel for' does not specify 'default' clause, consider specifying 'default(none)' clause
+}
+
+// 'parallel' directive can have 'default' clause, and said clause specified,
+// with 'none' kind, all good.
+void p4_1(const int a) {
+#pragma omp parallel for default(none) shared(a)
+ for (int b = 0; b < a; b++)
+ ;
+}
+
+// 'parallel' directive can have 'default' clause, and said clause specified,
+// but with 'shared' kind, which is not 'none', diagnose.
+void p4_2(const int a) {
+#pragma omp parallel for default(shared)
+ for (int b = 0; b < a; b++)
+ ;
+ // CHECK-NOTES: :[[@LINE-3]]:9: warning: OpenMP directive 'parallel for' specifies 'default(shared)' clause, consider using 'default(none)' clause instead
+ // CHECK-NOTES: :[[@LINE-4]]:26: note: existing 'default' clause specified here
+}
diff --git a/test/clang-tidy/readability-avoid-underscore-in-googletest-name.cpp b/test/clang-tidy/readability-avoid-underscore-in-googletest-name.cpp
new file mode 100644
index 00000000..6e8a5c2d
--- /dev/null
+++ b/test/clang-tidy/readability-avoid-underscore-in-googletest-name.cpp
@@ -0,0 +1,108 @@
+// RUN: %check_clang_tidy %s google-readability-avoid-underscore-in-googletest-name %t
+
+#define TEST(test_case_name, test_name) void test_case_name##test_name()
+#define TEST_F(test_case_name, test_name) void test_case_name##test_name()
+#define TEST_P(test_case_name, test_name) void test_case_name##test_name()
+#define TYPED_TEST(test_case_name, test_name) void test_case_name##test_name()
+#define TYPED_TEST_P(test_case_name, test_name) void test_case_name##test_name()
+#define FRIEND_TEST(test_case_name, test_name) void test_case_name##test_name()
+
+TEST(TestCaseName, Illegal_TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+
+TEST(TestCaseName, DISABLED_Illegal_TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TEST(TestCaseName, Illegal_Test_Name) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: avoid using "_" in test name "Illegal_Test_Name" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TEST(Illegal_TestCaseName, TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: avoid using "_" in test case name "Illegal_TestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TEST(Illegal_Test_CaseName, TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: avoid using "_" in test case name "Illegal_Test_CaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TEST(Illegal_TestCaseName, Illegal_TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: avoid using "_" in test case name "Illegal_TestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+// CHECK-MESSAGES: :[[@LINE-2]]:28: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+
+TEST_F(TestCaseFixtureName, Illegal_TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TEST_F(TestCaseFixtureName, DISABLED_Illegal_Test_Name) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: avoid using "_" in test name "Illegal_Test_Name" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TEST_F(TestCaseFixtureName, Illegal_Test_Name) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: avoid using "_" in test name "Illegal_Test_Name" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+
+TEST_F(Illegal_TestCaseFixtureName, TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: avoid using "_" in test case name "Illegal_TestCaseFixtureName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TEST_F(Illegal_TestCaseFixtureName, Illegal_TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: avoid using "_" in test case name "Illegal_TestCaseFixtureName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+// CHECK-MESSAGES: :[[@LINE-2]]:37: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+
+TEST_F(Illegal_Test_CaseFixtureName, TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: avoid using "_" in test case name "Illegal_Test_CaseFixtureName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+
+TEST_P(ParameterizedTestCaseFixtureName, Illegal_TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TEST_P(ParameterizedTestCaseFixtureName, DISABLED_Illegal_TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TEST_P(ParameterizedTestCaseFixtureName, Illegal_Test_Name) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: avoid using "_" in test name "Illegal_Test_Name" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+
+TEST_P(Illegal_ParameterizedTestCaseFixtureName, TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: avoid using "_" in test case name "Illegal_ParameterizedTestCaseFixtureName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TEST_P(Illegal_ParameterizedTestCaseFixtureName, Illegal_TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: avoid using "_" in test case name "Illegal_ParameterizedTestCaseFixtureName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+// CHECK-MESSAGES: :[[@LINE-2]]:50: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+
+TEST_P(Illegal_Parameterized_TestCaseFixtureName, TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: avoid using "_" in test case name "Illegal_Parameterized_TestCaseFixtureName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+
+TYPED_TEST(TypedTestCaseName, Illegal_TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TYPED_TEST(TypedTestCaseName, DISABLED_Illegal_TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TYPED_TEST(TypedTestCaseName, Illegal_Test_Name) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: avoid using "_" in test name "Illegal_Test_Name" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+
+TYPED_TEST(Illegal_TypedTestCaseName, TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: avoid using "_" in test case name "Illegal_TypedTestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TYPED_TEST(Illegal_TypedTestCaseName, Illegal_TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: avoid using "_" in test case name "Illegal_TypedTestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+// CHECK-MESSAGES: :[[@LINE-2]]:39: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+
+TYPED_TEST(Illegal_Typed_TestCaseName, TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: avoid using "_" in test case name "Illegal_Typed_TestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+
+TYPED_TEST_P(TypeParameterizedTestCaseName, Illegal_TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TYPED_TEST_P(TypeParameterizedTestCaseName, DISABLED_Illegal_TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TYPED_TEST_P(TypeParameterizedTestCaseName, Illegal_Test_Name) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: avoid using "_" in test name "Illegal_Test_Name" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+
+TYPED_TEST_P(Illegal_TypeParameterizedTestCaseName, TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: avoid using "_" in test case name "Illegal_TypeParameterizedTestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+TYPED_TEST_P(Illegal_TypeParameterizedTestCaseName, Illegal_TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: avoid using "_" in test case name "Illegal_TypeParameterizedTestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+// CHECK-MESSAGES: :[[@LINE-2]]:53: warning: avoid using "_" in test name "Illegal_TestName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+
+TYPED_TEST_P(Illegal_Type_ParameterizedTestCaseName, TestName) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: avoid using "_" in test case name "Illegal_Type_ParameterizedTestCaseName" according to Googletest FAQ [google-readability-avoid-underscore-in-googletest-name]
+
+// Underscores are allowed to disable a test with the DISABLED_ prefix.
+// https://github.com/google/googletest/blob/master/googletest/docs/faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore
+TEST(TestCaseName, TestName) {}
+TEST(TestCaseName, DISABLED_TestName) {}
+
+TEST_F(TestCaseFixtureName, TestName) {}
+TEST_F(TestCaseFixtureName, DISABLED_TestName) {}
+
+TEST_P(ParameterizedTestCaseFixtureName, TestName) {}
+TEST_P(ParameterizedTestCaseFixtureName, DISABLED_TestName) {}
+
+TYPED_TEST(TypedTestName, TestName) {}
+TYPED_TEST(TypedTestName, DISABLED_TestName) {}
+
+TYPED_TEST_P(TypeParameterizedTestName, TestName) {}
+TYPED_TEST_P(TypeParameterizedTestName, DISABLED_TestName) {}
+
+FRIEND_TEST(FriendTest, Is_NotChecked) {}
+FRIEND_TEST(Friend_Test, IsNotChecked) {}
+FRIEND_TEST(Friend_Test, Is_NotChecked) {}
diff --git a/test/clang-tidy/readability-else-after-return.cpp b/test/clang-tidy/readability-else-after-return.cpp
index 7e950928..b06c02c9 100644
--- a/test/clang-tidy/readability-else-after-return.cpp
+++ b/test/clang-tidy/readability-else-after-return.cpp
@@ -105,3 +105,15 @@ void foo() {
}
}
}
+
+extern int *g();
+extern void h(int **x);
+
+int *decl_in_condition() {
+ if (int *x = g()) {
+ return x;
+ } else {
+ h(&x);
+ return x;
+ }
+}
diff --git a/test/clang-tidy/readability-misleading-indentation.cpp b/test/clang-tidy/readability-misleading-indentation.cpp
index 59d5f406..40399492 100644
--- a/test/clang-tidy/readability-misleading-indentation.cpp
+++ b/test/clang-tidy/readability-misleading-indentation.cpp
@@ -8,7 +8,7 @@ void foo2();
foo1(); \
foo2();
-int main()
+void f()
{
bool cond1 = true;
bool cond2 = true;
@@ -90,7 +90,7 @@ int main()
else {
}
// CHECK-MESSAGES: :[[@LINE-2]]:8: warning: different indentation for 'if' and corresponding 'else' [readability-misleading-indentation]
-
+
if (cond1) {
if (cond1) {
}
@@ -109,3 +109,12 @@ int main()
BLOCK
}
+
+void g(bool x) {
+ if (x)
+ #pragma unroll
+ for (int k = 0; k < 1; ++k) {}
+
+ #pragma unroll
+ for (int k = 0; k < 1; ++k) {}
+}
diff --git a/test/clang-tidy/readability-redundant-smartptr-get-msvc.cpp b/test/clang-tidy/readability-redundant-smartptr-get-msvc.cpp
new file mode 100644
index 00000000..bd8990a2
--- /dev/null
+++ b/test/clang-tidy/readability-redundant-smartptr-get-msvc.cpp
@@ -0,0 +1,94 @@
+// RUN: %check_clang_tidy %s readability-redundant-smartptr-get %t
+
+#define NULL __null
+
+namespace std {
+
+// MSVC headers define operator templates instead of plain operators.
+
+template <typename T>
+struct unique_ptr {
+ template <typename T2 = T>
+ T2& operator*() const;
+ template <typename T2 = T>
+ T2* operator->() const;
+ T* get() const;
+ explicit operator bool() const noexcept;
+};
+
+template <typename T>
+struct shared_ptr {
+ template <typename T2 = T>
+ T2& operator*() const;
+ template <typename T2 = T>
+ T2* operator->() const;
+ T* get() const;
+ explicit operator bool() const noexcept;
+};
+
+} // namespace std
+
+struct Bar {
+ void Do();
+ void ConstDo() const;
+};
+
+void Positive() {
+ std::unique_ptr<Bar>* up;
+ (*up->get()).Do();
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call
+ // CHECK-MESSAGES: (*up->get()).Do();
+ // CHECK-FIXES: (**up).Do();
+
+ std::unique_ptr<int> uu;
+ std::shared_ptr<double> *ss;
+ bool bb = uu.get() == nullptr;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant get() call
+ // CHECK-MESSAGES: uu.get() == nullptr;
+ // CHECK-FIXES: bool bb = uu == nullptr;
+
+ if (up->get());
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call
+ // CHECK-MESSAGES: if (up->get());
+ // CHECK-FIXES: if (*up);
+ if ((uu.get()));
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+ // CHECK-MESSAGES: if ((uu.get()));
+ // CHECK-FIXES: if ((uu));
+ bb = !ss->get();
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant get() call
+ // CHECK-MESSAGES: bb = !ss->get();
+ // CHECK-FIXES: bb = !*ss;
+
+ bb = nullptr != ss->get();
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: redundant get() call
+ // CHECK-MESSAGES: nullptr != ss->get();
+ // CHECK-FIXES: bb = nullptr != *ss;
+
+ bb = std::unique_ptr<int>().get() == NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+ // CHECK-MESSAGES: bb = std::unique_ptr<int>().get() == NULL;
+ // CHECK-FIXES: bb = std::unique_ptr<int>() == NULL;
+ bb = ss->get() == NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+ // CHECK-MESSAGES: bb = ss->get() == NULL;
+ // CHECK-FIXES: bb = *ss == NULL;
+
+ std::unique_ptr<int> x, y;
+ if (x.get() == nullptr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call
+ // CHECK-MESSAGES: if (x.get() == nullptr);
+ // CHECK-FIXES: if (x == nullptr);
+ if (nullptr == y.get());
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: redundant get() call
+ // CHECK-MESSAGES: if (nullptr == y.get());
+ // CHECK-FIXES: if (nullptr == y);
+ if (x.get() == NULL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call
+ // CHECK-MESSAGES: if (x.get() == NULL);
+ // CHECK-FIXES: if (x == NULL);
+ if (NULL == x.get());
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: redundant get() call
+ // CHECK-MESSAGES: if (NULL == x.get());
+ // CHECK-FIXES: if (NULL == x);
+}
diff --git a/test/clang-tidy/readability-uppercase-literal-suffix-float16.cpp b/test/clang-tidy/readability-uppercase-literal-suffix-float16.cpp
new file mode 100644
index 00000000..b2b858f9
--- /dev/null
+++ b/test/clang-tidy/readability-uppercase-literal-suffix-float16.cpp
@@ -0,0 +1,51 @@
+// RUN: %check_clang_tidy %s readability-uppercase-literal-suffix %t -- -- -target aarch64-linux-gnu -I %S
+
+#include "readability-uppercase-literal-suffix.h"
+
+void float16_normal_literals() {
+ // _Float16
+
+ static constexpr auto v14 = 1.f16;
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase
+ // CHECK-MESSAGES-NEXT: static constexpr auto v14 = 1.f16;
+ // CHECK-MESSAGES-NEXT: ^ ~
+ // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}}
+ // CHECK-FIXES: static constexpr auto v14 = 1.F16;
+ static_assert(is_same<decltype(v14), const _Float16>::value, "");
+ static_assert(v14 == 1.F16, "");
+
+ static constexpr auto v15 = 1.e0f16;
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase
+ // CHECK-MESSAGES-NEXT: static constexpr auto v15 = 1.e0f16;
+ // CHECK-MESSAGES-NEXT: ^ ~
+ // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}}
+ // CHECK-FIXES: static constexpr auto v15 = 1.e0F16;
+ static_assert(is_same<decltype(v15), const _Float16>::value, "");
+ static_assert(v15 == 1.F16, "");
+
+ static constexpr auto v16 = 1.F16; // OK.
+ static_assert(is_same<decltype(v16), const _Float16>::value, "");
+ static_assert(v16 == 1.F16, "");
+
+ static constexpr auto v17 = 1.e0F16; // OK.
+ static_assert(is_same<decltype(v17), const _Float16>::value, "");
+ static_assert(v17 == 1.F16, "");
+}
+
+void float16_hexadecimal_literals() {
+// _Float16
+
+ static constexpr auto v13 = 0xfp0f16;
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase
+ // CHECK-MESSAGES-NEXT: static constexpr auto v13 = 0xfp0f16;
+ // CHECK-MESSAGES-NEXT: ^ ~
+ // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}}
+ // CHECK-FIXES: static constexpr auto v13 = 0xfp0F16;
+ static_assert(is_same<decltype(v13), const _Float16>::value, "");
+ static_assert(v13 == 0xfp0F16, "");
+
+ static constexpr auto v14 = 0xfp0F16; // OK.
+ static_assert(is_same<decltype(v14), const _Float16>::value, "");
+ static_assert(v14 == 0xfp0F16, "");
+
+}
diff --git a/test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp b/test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp
index 4d41db7a..50e75fae 100644
--- a/test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp
+++ b/test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp
@@ -97,34 +97,6 @@ void floating_point_suffix() {
static constexpr auto v13 = 1.e0Q; // OK.
static_assert(is_same<decltype(v13), const __float128>::value, "");
static_assert(v13 == 1., "");
-
- // _Float16
-
- static constexpr auto v14 = 1.f16;
- // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase
- // CHECK-MESSAGES-NEXT: static constexpr auto v14 = 1.f16;
- // CHECK-MESSAGES-NEXT: ^ ~
- // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}}
- // CHECK-FIXES: static constexpr auto v14 = 1.F16;
- static_assert(is_same<decltype(v14), const _Float16>::value, "");
- static_assert(v14 == 1.F16, "");
-
- static constexpr auto v15 = 1.e0f16;
- // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase
- // CHECK-MESSAGES-NEXT: static constexpr auto v15 = 1.e0f16;
- // CHECK-MESSAGES-NEXT: ^ ~
- // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}}
- // CHECK-FIXES: static constexpr auto v15 = 1.e0F16;
- static_assert(is_same<decltype(v15), const _Float16>::value, "");
- static_assert(v15 == 1.F16, "");
-
- static constexpr auto v16 = 1.F16; // OK.
- static_assert(is_same<decltype(v16), const _Float16>::value, "");
- static_assert(v16 == 1.F16, "");
-
- static constexpr auto v17 = 1.e0F16; // OK.
- static_assert(is_same<decltype(v17), const _Float16>::value, "");
- static_assert(v17 == 1.F16, "");
}
void floating_point_complex_suffix() {
diff --git a/test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp b/test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp
index 4cc9d6d2..415c6d8e 100644
--- a/test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp
+++ b/test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp
@@ -93,21 +93,6 @@ void floating_point_suffix() {
static constexpr auto v12 = 0xfp0Q; // OK.
static_assert(is_same<decltype(v12), const __float128>::value, "");
static_assert(v12 == 0xfp0, "");
-
- // _Float16
-
- static constexpr auto v13 = 0xfp0f16;
- // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase
- // CHECK-MESSAGES-NEXT: static constexpr auto v13 = 0xfp0f16;
- // CHECK-MESSAGES-NEXT: ^ ~
- // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}}
- // CHECK-FIXES: static constexpr auto v13 = 0xfp0F16;
- static_assert(is_same<decltype(v13), const _Float16>::value, "");
- static_assert(v13 == 0xfp0F16, "");
-
- static constexpr auto v14 = 0xfp0F16; // OK.
- static_assert(is_same<decltype(v14), const _Float16>::value, "");
- static_assert(v14 == 0xfp0F16, "");
}
void floating_point_complex_suffix() {
diff --git a/test/clang-tidy/run-clang-tidy.cpp b/test/clang-tidy/run-clang-tidy.cpp
index 2207e430..31c4d681 100644
--- a/test/clang-tidy/run-clang-tidy.cpp
+++ b/test/clang-tidy/run-clang-tidy.cpp
@@ -1,3 +1,4 @@
+// RUN: %run_clang_tidy --help
// RUN: rm -rf %t
// RUN: mkdir %t
// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -c %/t/test.cpp\",\"file\":\"%/t/test.cpp\"}]" | sed -e 's/\\/\\\\/g' > %t/compile_commands.json
diff --git a/test/clang-tidy/static-analyzer-config.cpp b/test/clang-tidy/static-analyzer-config.cpp
index 9ca87cf8..d07c0c3a 100644
--- a/test/clang-tidy/static-analyzer-config.cpp
+++ b/test/clang-tidy/static-analyzer-config.cpp
@@ -1,5 +1,5 @@
// REQUIRES: static-analyzer
-// RUN: clang-tidy %s -checks='-*,clang-analyzer-unix.Malloc' -config='{CheckOptions: [{ key: "clang-analyzer-unix.Malloc:Optimistic", value: true}]}' -- | FileCheck %s
+// RUN: clang-tidy %s -checks='-*,clang-analyzer-unix.Malloc' -config='{CheckOptions: [{ key: "clang-analyzer-unix.DynamicMemoryModeling:Optimistic", value: true}]}' -- | FileCheck %s
typedef __typeof(sizeof(int)) size_t;
void *malloc(size_t);
void free(void *);
diff --git a/test/clangd/diagnostics.test b/test/clangd/diagnostics.test
deleted file mode 100644
index a191c082..00000000
--- a/test/clangd/diagnostics.test
+++ /dev/null
@@ -1,28 +0,0 @@
-# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
-{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
----
-{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","version":1,"text":"void main() {}"}}}
-# CHECK: "method": "textDocument/publishDiagnostics",
-# CHECK-NEXT: "params": {
-# CHECK-NEXT: "diagnostics": [
-# CHECK-NEXT: {
-# CHECK-NEXT: "message": "Return type of 'main' is not 'int'",
-# CHECK-NEXT: "range": {
-# CHECK-NEXT: "end": {
-# CHECK-NEXT: "character": 4,
-# CHECK-NEXT: "line": 0
-# CHECK-NEXT: },
-# CHECK-NEXT: "start": {
-# CHECK-NEXT: "character": 0,
-# CHECK-NEXT: "line": 0
-# CHECK-NEXT: }
-# CHECK-NEXT: },
-# CHECK-NEXT: "severity": 2
-# CHECK-NEXT: }
-# CHECK-NEXT: ],
-# CHECK-NEXT: "uri": "file://{{.*}}/foo.c"
-# CHECK-NEXT: }
----
-{"jsonrpc":"2.0","id":5,"method":"shutdown"}
----
-{"jsonrpc":"2.0","method":"exit"}
diff --git a/test/include-fixer/include_path.cpp b/test/include-fixer/include_path.cpp
deleted file mode 100644
index 28b6ace5..00000000
--- a/test/include-fixer/include_path.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: mkdir -p %T/include-fixer/include
-// RUN: mkdir -p %T/include-fixer/symbols
-// RUN: mkdir -p %T/include-fixer/build
-// RUN: mkdir -p %T/include-fixer/src
-// RUN: sed 's|test_dir|%/T/include-fixer|g' %S/Inputs/database_template.json > %T/include-fixer/build/compile_commands.json
-// RUN: echo -e '#include "bar.h"\nb::a::bar f;' > %T/include-fixer/src/bar.cpp
-// RUN: echo 'namespace b { namespace a { class bar {}; } }' > %T/include-fixer/include/bar.h
-// RUN: cd %T/include-fixer/build
-// RUN: find-all-symbols -output-dir=%T/include-fixer/symbols -p=. %T/include-fixer/src/bar.cpp
-// RUN: find-all-symbols -merge-dir=%T/include-fixer/symbols %T/include-fixer/build/find_all_symbols.yaml
-// RUN: FileCheck -input-file=%T/include-fixer/build/find_all_symbols.yaml -check-prefix=CHECK-YAML %s
-//
-// RUN: echo 'b::a::bar f;' > %T/include-fixer/src/bar.cpp
-// RUN: clang-include-fixer -db=yaml -input=%T/include-fixer/build/find_all_symbols.yaml -minimize-paths=true -p=. %T/include-fixer/src/bar.cpp
-// RUN: FileCheck -input-file=%T/include-fixer/src/bar.cpp %s
-
-// CHECK-YAML: ..{{[/\\]}}include{{[/\\]}}bar.h
-// CHECK: #include "bar.h"
-// CHECK: b::a::bar f;
diff --git a/test/include-fixer/multiple_fixes.cpp b/test/include-fixer/multiple_fixes.cpp
deleted file mode 100644
index 35a73b4a..00000000
--- a/test/include-fixer/multiple_fixes.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// REQUIRES: shell
-// RUN: sed -e 's#//.*$##' %s > %t.cpp
-// RUN: mkdir -p %T/include-fixer/multiple-fixes
-// RUN: echo 'foo f;' > %T/include-fixer/multiple-fixes/foo.cpp
-// RUN: echo 'bar b;' > %T/include-fixer/multiple-fixes/bar.cpp
-// RUN: clang-include-fixer -db=fixed -input='foo= "foo.h";bar= "bar.h"' %T/include-fixer/multiple-fixes/*.cpp --
-// RUN: FileCheck -input-file=%T/include-fixer/multiple-fixes/bar.cpp %s -check-prefix=CHECK-BAR
-// RUN: FileCheck -input-file=%T/include-fixer/multiple-fixes/foo.cpp %s -check-prefix=CHECK-FOO
-//
-// CHECK-FOO: #include "foo.h"
-// CHECK-FOO: foo f;
-// CHECK-BAR: #include "bar.h"
-// CHECK-BAR: bar b;
diff --git a/test/lit.cfg b/test/lit.cfg.py
index 7fe56f7f..eaf0778e 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg.py
@@ -99,11 +99,9 @@ config.environment['LD_LIBRARY_PATH'] = path
if lit_config.useValgrind:
config.target_triple += '-vg'
+config.available_features.add('crash-recovery')
# Set available features we allow tests to conditionalize on.
#
-# As of 2011.08, crash-recovery tests still do not pass on FreeBSD.
-if platform.system() not in ['FreeBSD']:
- config.available_features.add('crash-recovery')
# Shell execution
if execute_external:
@@ -117,10 +115,6 @@ if not platform.system() in ['Windows'] or not execute_external:
if platform.system() not in ['Windows']:
config.available_features.add('ansi-escape-sequences')
-# XPC support for Clangd.
-if config.clangd_xpc_support:
- config.available_features.add('clangd-xpc-support')
-
if config.clang_staticanalyzer:
config.available_features.add('static-analyzer')
diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.py.in
index d71ca188..a970e7fa 100644
--- a/test/lit.site.cfg.in
+++ b/test/lit.site.cfg.py.in
@@ -11,7 +11,6 @@ config.clang_libs_dir = "@SHLIBDIR@"
config.python_executable = "@PYTHON_EXECUTABLE@"
config.target_triple = "@TARGET_TRIPLE@"
config.clang_staticanalyzer = @CLANG_ENABLE_STATIC_ANALYZER@
-config.clangd_xpc_support = @CLANGD_BUILD_XPC_SUPPORT@
# Support substitution of the tools and libs dirs with user parameters. This is
# used when we can't determine the tool dir at configuration time.
@@ -28,4 +27,4 @@ import lit.llvm
lit.llvm.initialize(lit_config, config)
# Let the main config do the real work.
-lit_config.load_config(config, "@CLANG_TOOLS_SOURCE_DIR@/test/lit.cfg")
+lit_config.load_config(config, "@CLANG_TOOLS_SOURCE_DIR@/test/lit.cfg.py")
diff --git a/test/modularize/ProblemsInconsistent.modularize b/test/modularize/ProblemsInconsistent.modularize
index 04d0b013..713bfe90 100644
--- a/test/modularize/ProblemsInconsistent.modularize
+++ b/test/modularize/ProblemsInconsistent.modularize
@@ -60,16 +60,6 @@ Inputs/InconsistentHeader2.h
# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h
# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
# CHECK-NEXT: (no macro definition)
-# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:11:2
-# CHECK-NEXT: #if SYMBOL == 1
-# CHECK-NEXT: ^
-# CHECK-NEXT: error: Conditional expression instance 'SYMBOL == 1' has different values in this header, depending on how it was included.
-# CHECK-NEXT: 'SYMBOL == 1' expanded to: 'true' with respect to these inclusion paths:
-# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h
-# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
-# CHECK-NEXT: 'SYMBOL == 1' expanded to: 'false' with respect to these inclusion paths:
-# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h
-# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h
# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:2:2
# CHECK-NEXT: #ifdef SYMBOL1
# CHECK-NEXT: ^
diff --git a/test/pp-trace/pp-trace-conditional.cpp b/test/pp-trace/pp-trace-conditional.cpp
index ac5d3b37..0ad6c593 100644
--- a/test/pp-trace/pp-trace-conditional.cpp
+++ b/test/pp-trace/pp-trace-conditional.cpp
@@ -1,4 +1,4 @@
-// RUN: pp-trace -ignore FileChanged %s -undef -target x86_64 -std=c++11 | FileCheck --strict-whitespace %s
+// RUN: pp-trace -callbacks '*,-FileChanged' %s -- -undef -target x86_64 -std=c++11 | FileCheck --strict-whitespace %s
#if 1
#endif
@@ -79,14 +79,14 @@
// CHECK-NEXT: MacroDirective: MD_Define
// CHECK: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:3:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:3:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:4:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:3:5", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:3:5"]
// CHECK-NEXT: ConditionValue: CVK_True
// CHECK-NEXT: - Callback: Endif
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:4:2"
// CHECK-NEXT: IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:3:2"
// CHECK-NEXT: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:6:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:6:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:7:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:6:5", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:6:5"]
// CHECK-NEXT: ConditionValue: CVK_False
// CHECK-NEXT: - Callback: Endif
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:7:2"
@@ -95,7 +95,7 @@
// CHECK-NEXT: Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:6:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:7:2"]
// CHECK-NEXT: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:9:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:9:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:10:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:9:5", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:9:5"]
// CHECK-NEXT: ConditionValue: CVK_True
// CHECK-NEXT: - Callback: Else
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:10:2"
@@ -107,7 +107,7 @@
// CHECK-NEXT: Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:10:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:11:2"]
// CHECK-NEXT: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:14:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:5", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:5"]
// CHECK-NEXT: ConditionValue: CVK_False
// CHECK-NEXT: - Callback: Else
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:14:2"
@@ -119,11 +119,11 @@
// CHECK-NEXT: IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:2"
// CHECK-NEXT: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:17:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:17:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:18:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:17:5", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:17:5"]
// CHECK-NEXT: ConditionValue: CVK_True
// CHECK-NEXT: - Callback: Elif
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:18:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:18:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:19:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:18:7", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:18:8"]
// CHECK-NEXT: ConditionValue: CVK_NotEvaluated
// CHECK-NEXT: IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:17:2"
// CHECK-NEXT: - Callback: Endif
@@ -133,11 +133,11 @@
// CHECK-NEXT: Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:18:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:19:2"]
// CHECK-NEXT: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:20:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:20:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:21:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:20:5", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:20:5"]
// CHECK-NEXT: ConditionValue: CVK_True
// CHECK-NEXT: - Callback: Elif
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:21:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:21:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:22:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:21:7", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:21:8"]
// CHECK-NEXT: ConditionValue: CVK_NotEvaluated
// CHECK-NEXT: IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:20:2"
// CHECK-NEXT: - Callback: Endif
@@ -147,11 +147,11 @@
// CHECK-NEXT: Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:21:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:22:2"]
// CHECK-NEXT: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:25:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:5", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:5"]
// CHECK-NEXT: ConditionValue: CVK_False
// CHECK-NEXT: - Callback: Elif
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:25:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:25:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:26:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:25:7", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:25:7"]
// CHECK-NEXT: ConditionValue: CVK_True
// CHECK-NEXT: IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:2"
// CHECK-NEXT: - Callback: SourceRangeSkipped
@@ -161,11 +161,11 @@
// CHECK-NEXT: IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:2"
// CHECK-NEXT: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:27:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:27:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:28:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:27:5", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:27:5"]
// CHECK-NEXT: ConditionValue: CVK_False
// CHECK-NEXT: - Callback: Elif
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:28:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:28:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:29:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:28:7", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:28:7"]
// CHECK-NEXT: ConditionValue: CVK_False
// CHECK-NEXT: IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:27:2"
// CHECK-NEXT: - Callback: Endif
@@ -175,11 +175,11 @@
// CHECK-NEXT: Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:27:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:29:2"]
// CHECK-NEXT: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:30:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:30:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:31:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:30:5", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:30:5"]
// CHECK-NEXT: ConditionValue: CVK_True
// CHECK-NEXT: - Callback: Elif
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:31:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:31:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:32:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:31:7", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:31:8"]
// CHECK-NEXT: ConditionValue: CVK_NotEvaluated
// CHECK-NEXT: IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:30:2"
// CHECK-NEXT: - Callback: Endif
@@ -189,11 +189,11 @@
// CHECK-NEXT: Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:31:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:32:2"]
// CHECK-NEXT: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:33:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:33:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:34:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:33:5", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:33:5"]
// CHECK-NEXT: ConditionValue: CVK_True
// CHECK-NEXT: - Callback: Elif
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:34:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:34:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:35:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:34:7", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:34:8"]
// CHECK-NEXT: ConditionValue: CVK_NotEvaluated
// CHECK-NEXT: IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:33:2"
// CHECK-NEXT: - Callback: Endif
@@ -203,11 +203,11 @@
// CHECK-NEXT: Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:34:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:35:2"]
// CHECK-NEXT: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:38:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:5", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:5"]
// CHECK-NEXT: ConditionValue: CVK_False
// CHECK-NEXT: - Callback: Elif
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:38:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:38:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:39:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:38:7", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:38:7"]
// CHECK-NEXT: ConditionValue: CVK_True
// CHECK-NEXT: IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:2"
// CHECK-NEXT: - Callback: SourceRangeSkipped
@@ -222,11 +222,11 @@
// CHECK-NEXT: Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:39:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:40:2"]
// CHECK-NEXT: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:42:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:5", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:5"]
// CHECK-NEXT: ConditionValue: CVK_False
// CHECK-NEXT: - Callback: Elif
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:42:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:42:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:43:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:42:7", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:42:7"]
// CHECK-NEXT: ConditionValue: CVK_False
// CHECK-NEXT: IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:2"
// CHECK-NEXT: - Callback: Else
@@ -239,11 +239,11 @@
// CHECK-NEXT: IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:2"
// CHECK-NEXT: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:45:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:45:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:46:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:45:5", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:45:5"]
// CHECK-NEXT: ConditionValue: CVK_True
// CHECK-NEXT: - Callback: Elif
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:46:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:46:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:47:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:46:7", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:46:8"]
// CHECK-NEXT: ConditionValue: CVK_NotEvaluated
// CHECK-NEXT: IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:45:2"
// CHECK-NEXT: - Callback: Endif
@@ -253,11 +253,11 @@
// CHECK-NEXT: Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:46:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:48:2"]
// CHECK-NEXT: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:49:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:49:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:50:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:49:5", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:49:5"]
// CHECK-NEXT: ConditionValue: CVK_True
// CHECK-NEXT: - Callback: Elif
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:50:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:50:6", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:51:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:50:7", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:50:8"]
// CHECK-NEXT: ConditionValue: CVK_NotEvaluated
// CHECK-NEXT: IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:49:2"
// CHECK-NEXT: - Callback: Endif
diff --git a/test/pp-trace/pp-trace-filter.cpp b/test/pp-trace/pp-trace-filter.cpp
new file mode 100644
index 00000000..1cd2ce7e
--- /dev/null
+++ b/test/pp-trace/pp-trace-filter.cpp
@@ -0,0 +1,17 @@
+// RUN: pp-trace -callbacks 'File*,Macro*,-MacroUndefined' %s -- | FileCheck %s
+// RUN: pp-trace -callbacks ' File* , Macro* , -MacroUndefined ' %s -- | FileCheck %s
+// RUN: not pp-trace -callbacks '[' %s -- 2>&1 | FileCheck --check-prefix=INVALID %s
+
+#define M 1
+int i = M;
+#undef M
+
+// CHECK: ---
+// CHECK: - Callback: FileChanged
+// CHECK: - Callback: MacroDefined
+// CHECK: - Callback: MacroExpands
+// CHECK-NOT: - Callback: MacroUndefined
+// CHECK-NOT: - Callback: EndOfMainFile
+// CHECK: ...
+
+// INVALID: error: invalid glob pattern: [
diff --git a/test/pp-trace/pp-trace-ident.cpp b/test/pp-trace/pp-trace-ident.cpp
index 9981c39e..cdd9fd38 100644
--- a/test/pp-trace/pp-trace-ident.cpp
+++ b/test/pp-trace/pp-trace-ident.cpp
@@ -1,4 +1,4 @@
-// RUN: pp-trace -ignore FileChanged,MacroDefined %s -undef -target x86_64 -std=c++11 | FileCheck --strict-whitespace %s
+// RUN: pp-trace -callbacks '*,-FileChanged,-MacroDefined' %s -- -undef -target x86_64 -std=c++11 | FileCheck --strict-whitespace %s
#ident "$Id$"
diff --git a/test/pp-trace/pp-trace-include.cpp b/test/pp-trace/pp-trace-include.cpp
index 7d925d84..ba6ad112 100644
--- a/test/pp-trace/pp-trace-include.cpp
+++ b/test/pp-trace/pp-trace-include.cpp
@@ -1,4 +1,4 @@
-// RUN: pp-trace %s -undef -target x86_64 -std=c++11 | FileCheck --strict-whitespace %s
+// RUN: pp-trace %s -- -undef -target x86_64 -std=c++11 | FileCheck --strict-whitespace %s
#include "Inputs/Level1A.h"
#include "Inputs/Level1B.h"
diff --git a/test/pp-trace/pp-trace-macro.cpp b/test/pp-trace/pp-trace-macro.cpp
index e6ba761d..47f9e1c4 100644
--- a/test/pp-trace/pp-trace-macro.cpp
+++ b/test/pp-trace/pp-trace-macro.cpp
@@ -1,4 +1,4 @@
-// RUN: pp-trace -ignore FileChanged %s -undef -target x86_64 -std=c++11 | FileCheck --strict-whitespace %s
+// RUN: pp-trace -callbacks '*,-FileChanged' %s -- -undef -target x86_64 -std=c++11 | FileCheck --strict-whitespace %s
#define MACRO 1
int i = MACRO;
@@ -44,7 +44,7 @@ X
// CHECK-NEXT: Range: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:5:5", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:5:19"]
// CHECK-NEXT: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-macro.cpp:5:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:5:4", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:6:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:5:5", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:5:19"]
// CHECK-NEXT: ConditionValue: CVK_True
// CHECK-NEXT: - Callback: Endif
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-macro.cpp:6:2"
@@ -58,7 +58,7 @@ X
// CHECK-NEXT: Range: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:8:5", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:8:19"]
// CHECK-NEXT: - Callback: If
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-macro.cpp:8:2"
-// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:8:4", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:9:1"]
+// CHECK-NEXT: ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:8:5", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:8:19"]
// CHECK-NEXT: ConditionValue: CVK_False
// CHECK-NEXT: - Callback: Endif
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-macro.cpp:9:2"
diff --git a/test/pp-trace/pp-trace-modules.cpp b/test/pp-trace/pp-trace-modules.cpp
index 5e9e1de3..32d6c48e 100644
--- a/test/pp-trace/pp-trace-modules.cpp
+++ b/test/pp-trace/pp-trace-modules.cpp
@@ -1,5 +1,5 @@
// RUN: rm -rf %t
-// RUN: pp-trace -ignore FileChanged,MacroDefined %s -x objective-c++ -undef -target x86_64 -std=c++11 -fmodules -fcxx-modules -fmodules-cache-path=%t -I%S -I%S/Input | FileCheck --strict-whitespace %s
+// RUN: pp-trace -callbacks '*,-FileChanged,-MacroDefined' %s -- -x objective-c++ -undef -target x86_64 -std=c++11 -fmodules -fcxx-modules -fmodules-cache-path=%t -I%S -I%S/Input | FileCheck --strict-whitespace %s
// CHECK: ---
diff --git a/test/pp-trace/pp-trace-pragma-general.cpp b/test/pp-trace/pp-trace-pragma-general.cpp
index 6caef0b6..f01ebd1e 100644
--- a/test/pp-trace/pp-trace-pragma-general.cpp
+++ b/test/pp-trace/pp-trace-pragma-general.cpp
@@ -1,4 +1,4 @@
-// RUN: pp-trace -ignore FileChanged,MacroDefined %s | FileCheck --strict-whitespace %s
+// RUN: pp-trace -callbacks '*,-FileChanged,-MacroDefined' %s -- | FileCheck --strict-whitespace %s
#pragma clang diagnostic push
#pragma clang diagnostic pop
diff --git a/test/pp-trace/pp-trace-pragma-ms.cpp b/test/pp-trace/pp-trace-pragma-ms.cpp
index 33c9f7fa..5df30ad8 100644
--- a/test/pp-trace/pp-trace-pragma-ms.cpp
+++ b/test/pp-trace/pp-trace-pragma-ms.cpp
@@ -1,4 +1,4 @@
-// RUN: pp-trace -ignore FileChanged,MacroDefined %s -target x86_64-unknown-windows-msvc -fms-extensions -w | FileCheck --strict-whitespace %s
+// RUN: pp-trace -callbacks '*,-FileChanged,-MacroDefined' %s -- -target x86_64-unknown-windows-msvc -fms-extensions -w | FileCheck --strict-whitespace %s
#pragma comment(compiler, "compiler comment")
#pragma comment(exestr, "exestr comment")
diff --git a/test/pp-trace/pp-trace-pragma-opencl.cpp b/test/pp-trace/pp-trace-pragma-opencl.cpp
index cfd72c0d..8ba26c3b 100644
--- a/test/pp-trace/pp-trace-pragma-opencl.cpp
+++ b/test/pp-trace/pp-trace-pragma-opencl.cpp
@@ -1,4 +1,4 @@
-// RUN: pp-trace -ignore FileChanged,MacroDefined %s -x cl | FileCheck --strict-whitespace %s
+// RUN: pp-trace -callbacks '*,-FileChanged,-MacroDefined' %s -- -x cl | FileCheck --strict-whitespace %s
#pragma OPENCL EXTENSION all : disable
#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : disable
diff --git a/tool-template/ToolTemplate.cpp b/tool-template/ToolTemplate.cpp
index 66ec2e84..3220eb33 100644
--- a/tool-template/ToolTemplate.cpp
+++ b/tool-template/ToolTemplate.cpp
@@ -1,9 +1,8 @@
//===---- tools/extra/ToolTemplate.cpp - Template for refactoring tool ----===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt
index 9e01473d..086a68e6 100644
--- a/unittests/CMakeLists.txt
+++ b/unittests/CMakeLists.txt
@@ -5,20 +5,10 @@ function(add_extra_unittest test_dirname)
add_unittest(ExtraToolsUnitTests ${test_dirname} ${ARGN})
endfunction()
-if(CLANG_BUILT_STANDALONE)
- # LLVMTestingSupport library is needed for clangd tests.
- if (EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Testing/Support
- AND NOT TARGET LLVMTestingSupport)
- add_subdirectory(${LLVM_MAIN_SRC_DIR}/lib/Testing/Support
- lib/Testing/Support)
- endif()
-endif()
-
-add_subdirectory(change-namespace)
add_subdirectory(clang-apply-replacements)
+add_subdirectory(clang-change-namespace)
add_subdirectory(clang-doc)
+add_subdirectory(clang-include-fixer)
add_subdirectory(clang-move)
add_subdirectory(clang-query)
add_subdirectory(clang-tidy)
-add_subdirectory(clangd)
-add_subdirectory(include-fixer)
diff --git a/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp b/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp
index 85aaebf7..0a2a6779 100644
--- a/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp
+++ b/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp
@@ -1,10 +1,9 @@
//===- clang-apply-replacements/ApplyReplacementsTest.cpp
//----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -27,7 +26,6 @@ makeTUDiagnostics(const std::string &MainSourceFile, StringRef DiagnosticName,
TUs.push_back({MainSourceFile,
{{DiagnosticName,
Message,
- Replacements,
{},
Diagnostic::Warning,
BuildDirectory}}});
diff --git a/unittests/change-namespace/CMakeLists.txt b/unittests/clang-change-namespace/CMakeLists.txt
index dc5f59d9..9c949723 100644
--- a/unittests/change-namespace/CMakeLists.txt
+++ b/unittests/clang-change-namespace/CMakeLists.txt
@@ -3,7 +3,7 @@ set(LLVM_LINK_COMPONENTS
)
get_filename_component(CHANGE_NAMESPACE_SOURCE_DIR
- ${CMAKE_CURRENT_SOURCE_DIR}/../../change-namespace REALPATH)
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../clang-change-namespace REALPATH)
include_directories(
${CHANGE_NAMESPACE_SOURCE_DIR}
)
@@ -11,11 +11,11 @@ include_directories(
# We'd like clang/unittests/Tooling/RewriterTestContext.h in the test.
include_directories(${CLANG_SOURCE_DIR})
-add_extra_unittest(ChangeNamespaceTests
+add_extra_unittest(ClangChangeNamespaceTests
ChangeNamespaceTests.cpp
)
-target_link_libraries(ChangeNamespaceTests
+target_link_libraries(ClangChangeNamespaceTests
PRIVATE
clangAST
clangASTMatchers
diff --git a/unittests/change-namespace/ChangeNamespaceTests.cpp b/unittests/clang-change-namespace/ChangeNamespaceTests.cpp
index 4008600b..d66fede2 100644
--- a/unittests/change-namespace/ChangeNamespaceTests.cpp
+++ b/unittests/clang-change-namespace/ChangeNamespaceTests.cpp
@@ -1,9 +1,8 @@
//===-- ChangeNamespaceTests.cpp - Change namespace unit tests ---*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clang-doc/BitcodeTest.cpp b/unittests/clang-doc/BitcodeTest.cpp
index 26bdf9ec..c89a6491 100644
--- a/unittests/clang-doc/BitcodeTest.cpp
+++ b/unittests/clang-doc/BitcodeTest.cpp
@@ -1,9 +1,8 @@
//===-- clang-doc/BitcodeTest.cpp -----------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clang-doc/ClangDocTest.cpp b/unittests/clang-doc/ClangDocTest.cpp
index e763d354..99ea76b7 100644
--- a/unittests/clang-doc/ClangDocTest.cpp
+++ b/unittests/clang-doc/ClangDocTest.cpp
@@ -1,9 +1,8 @@
//===-- clang-doc/ClangDocTest.cpp ----------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clang-doc/ClangDocTest.h b/unittests/clang-doc/ClangDocTest.h
index 1cc06191..d9f3a65b 100644
--- a/unittests/clang-doc/ClangDocTest.h
+++ b/unittests/clang-doc/ClangDocTest.h
@@ -1,9 +1,8 @@
//===-- clang-doc/ClangDocTest.h ------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clang-doc/MDGeneratorTest.cpp b/unittests/clang-doc/MDGeneratorTest.cpp
index aa624baa..233ec6ec 100644
--- a/unittests/clang-doc/MDGeneratorTest.cpp
+++ b/unittests/clang-doc/MDGeneratorTest.cpp
@@ -1,9 +1,8 @@
//===-- clang-doc/MDGeneratorTest.cpp -------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clang-doc/MergeTest.cpp b/unittests/clang-doc/MergeTest.cpp
index ab3afa86..7adc1f3d 100644
--- a/unittests/clang-doc/MergeTest.cpp
+++ b/unittests/clang-doc/MergeTest.cpp
@@ -1,9 +1,8 @@
//===-- clang-doc/MergeTest.cpp -------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clang-doc/SerializeTest.cpp b/unittests/clang-doc/SerializeTest.cpp
index d5bf8f11..1c044f7d 100644
--- a/unittests/clang-doc/SerializeTest.cpp
+++ b/unittests/clang-doc/SerializeTest.cpp
@@ -1,9 +1,8 @@
//===-- clang-doc/SerializeTest.cpp ---------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clang-doc/YAMLGeneratorTest.cpp b/unittests/clang-doc/YAMLGeneratorTest.cpp
index a4ac5dfb..8a1ba465 100644
--- a/unittests/clang-doc/YAMLGeneratorTest.cpp
+++ b/unittests/clang-doc/YAMLGeneratorTest.cpp
@@ -1,10 +1,9 @@
//===-- clang-doc/YAMLGeneratorTest.cpp
//------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/include-fixer/CMakeLists.txt b/unittests/clang-include-fixer/CMakeLists.txt
index c084a4df..997aa145 100644
--- a/unittests/include-fixer/CMakeLists.txt
+++ b/unittests/clang-include-fixer/CMakeLists.txt
@@ -3,7 +3,7 @@ set(LLVM_LINK_COMPONENTS
)
get_filename_component(INCLUDE_FIXER_SOURCE_DIR
- ${CMAKE_CURRENT_SOURCE_DIR}/../../include-fixer REALPATH)
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../clang-include-fixer REALPATH)
include_directories(
${INCLUDE_FIXER_SOURCE_DIR}
)
@@ -11,12 +11,12 @@ include_directories(
# We'd like to clang/unittests/Tooling/RewriterTestContext.h in the test.
include_directories(${CLANG_SOURCE_DIR})
-add_extra_unittest(IncludeFixerTests
+add_extra_unittest(ClangIncludeFixerTests
IncludeFixerTest.cpp
FuzzySymbolIndexTests.cpp
)
-target_link_libraries(IncludeFixerTests
+target_link_libraries(ClangIncludeFixerTests
PRIVATE
clangBasic
clangFormat
diff --git a/unittests/include-fixer/FuzzySymbolIndexTests.cpp b/unittests/clang-include-fixer/FuzzySymbolIndexTests.cpp
index 17679c5d..3886269f 100644
--- a/unittests/include-fixer/FuzzySymbolIndexTests.cpp
+++ b/unittests/clang-include-fixer/FuzzySymbolIndexTests.cpp
@@ -1,9 +1,8 @@
//===-- FuzzySymbolIndexTests.cpp - Fuzzy symbol index unit tests ---------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/include-fixer/IncludeFixerTest.cpp b/unittests/clang-include-fixer/IncludeFixerTest.cpp
index 519c0837..ab7ef797 100644
--- a/unittests/include-fixer/IncludeFixerTest.cpp
+++ b/unittests/clang-include-fixer/IncludeFixerTest.cpp
@@ -1,9 +1,8 @@
//===-- IncludeFixerTest.cpp - Include fixer unit tests -------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -179,7 +178,7 @@ TEST(IncludeFixer, NestedName) {
EXPECT_EQ("#define FOO(x) a::##x\nint x = FOO(b::foo);\n",
runIncludeFixer("#define FOO(x) a::##x\nint x = FOO(b::foo);\n"));
- // The empty namespace is cleaned up by clang-format after include-fixer
+ // The empty namespace is cleaned up by clang-format after clang-include-fixer
// finishes.
EXPECT_EQ("#include \"dir/otherdir/qux.h\"\n"
"\nint a = a::b::foo(0);\n",
@@ -228,7 +227,7 @@ TEST(IncludeFixer, IgnoreSymbolFromHeader) {
}
// FIXME: add test cases for inserting and sorting multiple headers when
-// include-fixer supports multiple headers insertion.
+// clang-include-fixer supports multiple headers insertion.
TEST(IncludeFixer, InsertAndSortSingleHeader) {
// Insert one header.
std::string Code = "#include \"a.h\"\n"
diff --git a/unittests/include-fixer/find-all-symbols/CMakeLists.txt b/unittests/clang-include-fixer/find-all-symbols/CMakeLists.txt
index 6a5472ee..427aa8ed 100644
--- a/unittests/include-fixer/find-all-symbols/CMakeLists.txt
+++ b/unittests/clang-include-fixer/find-all-symbols/CMakeLists.txt
@@ -3,7 +3,7 @@ set(LLVM_LINK_COMPONENTS
)
get_filename_component(INCLUDE_FIXER_SOURCE_DIR
- ${CMAKE_CURRENT_SOURCE_DIR}/../../../include-fixer/find-all-symbols REALPATH)
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../clang-include-fixer/find-all-symbols REALPATH)
include_directories(
${INCLUDE_FIXER_SOURCE_DIR}
)
diff --git a/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp b/unittests/clang-include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
index 1ad9e7f0..179ad258 100644
--- a/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
+++ b/unittests/clang-include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
@@ -1,9 +1,8 @@
//===-- FindAllSymbolsTests.cpp - find all symbols unit tests ---*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clang-move/ClangMoveTests.cpp b/unittests/clang-move/ClangMoveTests.cpp
index 97c7ce07..721ffd95 100644
--- a/unittests/clang-move/ClangMoveTests.cpp
+++ b/unittests/clang-move/ClangMoveTests.cpp
@@ -1,13 +1,12 @@
-//===-- ClangMoveTest.cpp - clang-move unit tests -------------------------===//
+//===-- ClangMoveTests.cpp - clang-move unit tests ------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 "ClangMove.h"
+#include "Move.h"
#include "unittests/Tooling/RewriterTestContext.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/FrontendActions.h"
diff --git a/unittests/clang-query/QueryEngineTest.cpp b/unittests/clang-query/QueryEngineTest.cpp
index c1d67a17..6d728cee 100644
--- a/unittests/clang-query/QueryEngineTest.cpp
+++ b/unittests/clang-query/QueryEngineTest.cpp
@@ -1,9 +1,8 @@
-//===---- QueryTest.cpp - clang-query test --------------------------------===//
+//===-- QueryEngineTest.cpp - clang-query test ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clang-query/QueryParserTest.cpp b/unittests/clang-query/QueryParserTest.cpp
index d4c384c4..01c65452 100644
--- a/unittests/clang-query/QueryParserTest.cpp
+++ b/unittests/clang-query/QueryParserTest.cpp
@@ -1,9 +1,8 @@
//===---- QueryParserTest.cpp - clang-query test --------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clang-tidy/CMakeLists.txt b/unittests/clang-tidy/CMakeLists.txt
index 648f0c57..614f84c9 100644
--- a/unittests/clang-tidy/CMakeLists.txt
+++ b/unittests/clang-tidy/CMakeLists.txt
@@ -16,7 +16,8 @@ add_extra_unittest(ClangTidyTests
ObjCModuleTest.cpp
OverlappingReplacementsTest.cpp
UsingInserterTest.cpp
- ReadabilityModuleTest.cpp)
+ ReadabilityModuleTest.cpp
+ )
target_link_libraries(ClangTidyTests
PRIVATE
diff --git a/unittests/clang-tidy/ClangTidyTest.h b/unittests/clang-tidy/ClangTidyTest.h
index 32bb53c1..560b0ff8 100644
--- a/unittests/clang-tidy/ClangTidyTest.h
+++ b/unittests/clang-tidy/ClangTidyTest.h
@@ -1,9 +1,8 @@
//===--- ClangTidyTest.h - clang-tidy ---------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -15,6 +14,8 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
+#include "clang/Tooling/Core/Diagnostic.h"
+#include "clang/Tooling/Core/Replacement.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/Optional.h"
@@ -40,9 +41,10 @@ private:
Context.setCurrentFile(File);
Context.setASTContext(&Compiler.getASTContext());
+ Preprocessor *PP = &Compiler.getPreprocessor();
for (auto &Check : Checks) {
Check->registerMatchers(&Finder);
- Check->registerPPCallbacks(Compiler);
+ Check->registerPPCallbacks(Compiler.getSourceManager(), PP, PP);
}
return Finder.newASTConsumer();
}
@@ -130,16 +132,17 @@ runCheckOnCode(StringRef Code, std::vector<ClangTidyError> *Errors = nullptr,
tooling::Replacements Fixes;
std::vector<ClangTidyError> Diags = DiagConsumer.take();
for (const ClangTidyError &Error : Diags) {
- for (const auto &FileAndFixes : Error.Fix) {
- for (const auto &Fix : FileAndFixes.second) {
- auto Err = Fixes.add(Fix);
- // FIXME: better error handling. Keep the behavior for now.
- if (Err) {
- llvm::errs() << llvm::toString(std::move(Err)) << "\n";
- return "";
+ if (const auto *ChosenFix = tooling::selectFirstFix(Error))
+ for (const auto &FileAndFixes : *ChosenFix) {
+ for (const auto &Fix : FileAndFixes.second) {
+ auto Err = Fixes.add(Fix);
+ // FIXME: better error handling. Keep the behavior for now.
+ if (Err) {
+ llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ return "";
+ }
}
}
- }
}
if (Errors)
*Errors = std::move(Diags);
diff --git a/unittests/clang-tidy/IncludeInserterTest.cpp b/unittests/clang-tidy/IncludeInserterTest.cpp
index 7a70f66a..89b25671 100644
--- a/unittests/clang-tidy/IncludeInserterTest.cpp
+++ b/unittests/clang-tidy/IncludeInserterTest.cpp
@@ -1,9 +1,8 @@
//===---- IncludeInserterTest.cpp - clang-tidy ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -32,12 +31,11 @@ public:
IncludeInserterCheckBase(StringRef CheckName, ClangTidyContext *Context)
: ClangTidyCheck(CheckName, Context) {}
- void registerPPCallbacks(CompilerInstance &Compiler) override {
- Inserter.reset(new utils::IncludeInserter(
- Compiler.getSourceManager(),
- Compiler.getLangOpts(),
- utils::IncludeSorter::IS_Google));
- Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override {
+ Inserter = llvm::make_unique<utils::IncludeInserter>(
+ SM, getLangOpts(), utils::IncludeSorter::IS_Google);
+ PP->addPPCallbacks(Inserter->CreatePPCallbacks());
}
void registerMatchers(ast_matchers::MatchFinder *Finder) override {
diff --git a/unittests/clang-tidy/NamespaceAliaserTest.cpp b/unittests/clang-tidy/NamespaceAliaserTest.cpp
index e4f8ebce..e4cd74ed 100644
--- a/unittests/clang-tidy/NamespaceAliaserTest.cpp
+++ b/unittests/clang-tidy/NamespaceAliaserTest.cpp
@@ -1,10 +1,9 @@
//===---- NamespaceAliaserTest.cpp - clang-tidy
//----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clang-tidy/ObjCModuleTest.cpp b/unittests/clang-tidy/ObjCModuleTest.cpp
index 92ae8e10..826978b0 100644
--- a/unittests/clang-tidy/ObjCModuleTest.cpp
+++ b/unittests/clang-tidy/ObjCModuleTest.cpp
@@ -1,9 +1,8 @@
//===---- ObjCModuleTest.cpp - clang-tidy ---------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clang-tidy/OverlappingReplacementsTest.cpp b/unittests/clang-tidy/OverlappingReplacementsTest.cpp
index 87213b17..3aaf5491 100644
--- a/unittests/clang-tidy/OverlappingReplacementsTest.cpp
+++ b/unittests/clang-tidy/OverlappingReplacementsTest.cpp
@@ -1,9 +1,8 @@
//===---- OverlappingReplacementsTest.cpp - clang-tidy --------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clang-tidy/UsingInserterTest.cpp b/unittests/clang-tidy/UsingInserterTest.cpp
index 16d25192..71c71596 100644
--- a/unittests/clang-tidy/UsingInserterTest.cpp
+++ b/unittests/clang-tidy/UsingInserterTest.cpp
@@ -1,9 +1,8 @@
//===---- UsingInserterTest.cpp - clang-tidy ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clangd/Annotations.cpp b/unittests/clangd/Annotations.cpp
deleted file mode 100644
index 474ba05d..00000000
--- a/unittests/clangd/Annotations.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-//===--- Annotations.cpp - Annotated source code for unit tests --*- C++-*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Annotations.h"
-#include "SourceCode.h"
-
-namespace clang {
-namespace clangd {
-
-// Crash if the assertion fails, printing the message and testcase.
-// More elegant error handling isn't needed for unit tests.
-static void require(bool Assertion, const char *Msg, llvm::StringRef Code) {
- if (!Assertion) {
- llvm::errs() << "Annotated testcase: " << Msg << "\n" << Code << "\n";
- llvm_unreachable("Annotated testcase assertion failed!");
- }
-}
-
-Annotations::Annotations(llvm::StringRef Text) {
- auto Here = [this] { return offsetToPosition(Code, Code.size()); };
- auto Require = [Text](bool Assertion, const char *Msg) {
- require(Assertion, Msg, Text);
- };
- llvm::Optional<llvm::StringRef> Name;
- llvm::SmallVector<std::pair<llvm::StringRef, Position>, 8> OpenRanges;
-
- Code.reserve(Text.size());
- while (!Text.empty()) {
- if (Text.consume_front("^")) {
- Points[Name.getValueOr("")].push_back(Here());
- Name = None;
- continue;
- }
- if (Text.consume_front("[[")) {
- OpenRanges.emplace_back(Name.getValueOr(""), Here());
- Name = None;
- continue;
- }
- Require(!Name, "$name should be followed by ^ or [[");
- if (Text.consume_front("]]")) {
- Require(!OpenRanges.empty(), "unmatched ]]");
- Ranges[OpenRanges.back().first].push_back(
- {OpenRanges.back().second, Here()});
- OpenRanges.pop_back();
- continue;
- }
- if (Text.consume_front("$")) {
- Name = Text.take_while(llvm::isAlnum);
- Text = Text.drop_front(Name->size());
- continue;
- }
- Code.push_back(Text.front());
- Text = Text.drop_front();
- }
- Require(!Name, "unterminated $name");
- Require(OpenRanges.empty(), "unmatched [[");
-}
-
-Position Annotations::point(llvm::StringRef Name) const {
- auto I = Points.find(Name);
- require(I != Points.end() && I->getValue().size() == 1,
- "expected exactly one point", Code);
- return I->getValue()[0];
-}
-std::vector<Position> Annotations::points(llvm::StringRef Name) const {
- auto P = Points.lookup(Name);
- return {P.begin(), P.end()};
-}
-Range Annotations::range(llvm::StringRef Name) const {
- auto I = Ranges.find(Name);
- require(I != Ranges.end() && I->getValue().size() == 1,
- "expected exactly one range", Code);
- return I->getValue()[0];
-}
-std::vector<Range> Annotations::ranges(llvm::StringRef Name) const {
- auto R = Ranges.lookup(Name);
- return {R.begin(), R.end()};
-}
-
-} // namespace clangd
-} // namespace clang
diff --git a/unittests/clangd/Annotations.h b/unittests/clangd/Annotations.h
deleted file mode 100644
index 4d787c25..00000000
--- a/unittests/clangd/Annotations.h
+++ /dev/null
@@ -1,72 +0,0 @@
-//===--- Annotations.h - Annotated source code for tests ---------*- C++-*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Annotations lets you mark points and ranges inside source code, for tests:
-//
-// Annotations Example(R"cpp(
-// int complete() { x.pri^ } // ^ indicates a point
-// void err() { [["hello" == 42]]; } // [[this is a range]]
-// $definition^class Foo{}; // points can be named: "definition"
-// $fail[[static_assert(false, "")]] // ranges can be named too: "fail"
-// )cpp");
-//
-// StringRef Code = Example.code(); // annotations stripped.
-// std::vector<Position> PP = Example.points(); // all unnamed points
-// Position P = Example.point(); // there must be exactly one
-// Range R = Example.range("fail"); // find named ranges
-//
-// Points/ranges are coordinates into `code()` which is stripped of annotations.
-//
-// Ranges may be nested (and points can be inside ranges), but there's no way
-// to define general overlapping ranges.
-//
-//===---------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_ANNOTATIONS_H
-#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_ANNOTATIONS_H
-
-#include "Protocol.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-
-namespace clang {
-namespace clangd {
-
-class Annotations {
-public:
- // Parses the annotations from Text. Crashes if it's malformed.
- Annotations(llvm::StringRef Text);
-
- // The input text with all annotations stripped.
- // All points and ranges are relative to this stripped text.
- llvm::StringRef code() const { return Code; }
-
- // Returns the position of the point marked by ^ (or $name^) in the text.
- // Crashes if there isn't exactly one.
- Position point(llvm::StringRef Name = "") const;
- // Returns the position of all points marked by ^ (or $name^) in the text.
- std::vector<Position> points(llvm::StringRef Name = "") const;
-
- // Returns the location of the range marked by [[ ]] (or $name[[ ]]).
- // Crashes if there isn't exactly one.
- Range range(llvm::StringRef Name = "") const;
- // Returns the location of all ranges marked by [[ ]] (or $name[[ ]]).
- std::vector<Range> ranges(llvm::StringRef Name = "") const;
-
-private:
- std::string Code;
- llvm::StringMap<llvm::SmallVector<Position, 1>> Points;
- llvm::StringMap<llvm::SmallVector<Range, 1>> Ranges;
-};
-
-} // namespace clangd
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_ANNOTATIONS_H
diff --git a/unittests/clangd/ClangdUnitTests.cpp b/unittests/clangd/ClangdUnitTests.cpp
deleted file mode 100644
index d0b85fd4..00000000
--- a/unittests/clangd/ClangdUnitTests.cpp
+++ /dev/null
@@ -1,341 +0,0 @@
-//===-- ClangdUnitTests.cpp - ClangdUnit tests ------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Annotations.h"
-#include "ClangdUnit.h"
-#include "SourceCode.h"
-#include "TestTU.h"
-#include "llvm/Support/ScopedPrinter.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-namespace clang {
-namespace clangd {
-namespace {
-
-using testing::ElementsAre;
-using testing::Field;
-using testing::IsEmpty;
-using testing::Pair;
-using testing::UnorderedElementsAre;
-
-testing::Matcher<const Diag &> WithFix(testing::Matcher<Fix> FixMatcher) {
- return Field(&Diag::Fixes, ElementsAre(FixMatcher));
-}
-
-testing::Matcher<const Diag &> WithNote(testing::Matcher<Note> NoteMatcher) {
- return Field(&Diag::Notes, ElementsAre(NoteMatcher));
-}
-
-MATCHER_P2(Diag, Range, Message,
- "Diag at " + llvm::to_string(Range) + " = [" + Message + "]") {
- return arg.Range == Range && arg.Message == Message;
-}
-
-MATCHER_P3(Fix, Range, Replacement, Message,
- "Fix " + llvm::to_string(Range) + " => " +
- testing::PrintToString(Replacement) + " = [" + Message + "]") {
- return arg.Message == Message && arg.Edits.size() == 1 &&
- arg.Edits[0].range == Range && arg.Edits[0].newText == Replacement;
-}
-
-MATCHER_P(EqualToLSPDiag, LSPDiag,
- "LSP diagnostic " + llvm::to_string(LSPDiag)) {
- return std::tie(arg.range, arg.severity, arg.message) ==
- std::tie(LSPDiag.range, LSPDiag.severity, LSPDiag.message);
-}
-
-MATCHER_P(EqualToFix, Fix, "LSP fix " + llvm::to_string(Fix)) {
- if (arg.Message != Fix.Message)
- return false;
- if (arg.Edits.size() != Fix.Edits.size())
- return false;
- for (std::size_t I = 0; I < arg.Edits.size(); ++I) {
- if (arg.Edits[I].range != Fix.Edits[I].range ||
- arg.Edits[I].newText != Fix.Edits[I].newText)
- return false;
- }
- return true;
-}
-
-// Helper function to make tests shorter.
-Position pos(int line, int character) {
- Position Res;
- Res.line = line;
- Res.character = character;
- return Res;
-}
-
-TEST(DiagnosticsTest, DiagnosticRanges) {
- // Check we report correct ranges, including various edge-cases.
- Annotations Test(R"cpp(
- namespace test{};
- void $decl[[foo]]();
- int main() {
- $typo[[go\
-o]]();
- foo()$semicolon[[]]//with comments
- $unk[[unknown]]();
- double $type[[bar]] = "foo";
- struct Foo { int x; }; Foo a;
- a.$nomember[[y]];
- test::$nomembernamespace[[test]];
- }
- )cpp");
- EXPECT_THAT(
- TestTU::withCode(Test.code()).build().getDiagnostics(),
- ElementsAre(
- // This range spans lines.
- AllOf(Diag(Test.range("typo"),
- "use of undeclared identifier 'goo'; did you mean 'foo'?"),
- WithFix(
- Fix(Test.range("typo"), "foo", "change 'go\\ o' to 'foo'")),
- // This is a pretty normal range.
- WithNote(Diag(Test.range("decl"), "'foo' declared here"))),
- // This range is zero-width and insertion. Therefore make sure we are
- // not expanding it into other tokens. Since we are not going to
- // replace those.
- AllOf(Diag(Test.range("semicolon"), "expected ';' after expression"),
- WithFix(Fix(Test.range("semicolon"), ";", "insert ';'"))),
- // This range isn't provided by clang, we expand to the token.
- Diag(Test.range("unk"), "use of undeclared identifier 'unknown'"),
- Diag(Test.range("type"),
- "cannot initialize a variable of type 'double' with an lvalue "
- "of type 'const char [4]'"),
- Diag(Test.range("nomember"), "no member named 'y' in 'Foo'"),
- Diag(Test.range("nomembernamespace"),
- "no member named 'test' in namespace 'test'")));
-}
-
-TEST(DiagnosticsTest, FlagsMatter) {
- Annotations Test("[[void]] main() {}");
- auto TU = TestTU::withCode(Test.code());
- EXPECT_THAT(TU.build().getDiagnostics(),
- ElementsAre(AllOf(Diag(Test.range(), "'main' must return 'int'"),
- WithFix(Fix(Test.range(), "int",
- "change 'void' to 'int'")))));
- // Same code built as C gets different diagnostics.
- TU.Filename = "Plain.c";
- EXPECT_THAT(
- TU.build().getDiagnostics(),
- ElementsAre(AllOf(
- Diag(Test.range(), "return type of 'main' is not 'int'"),
- WithFix(Fix(Test.range(), "int", "change return type to 'int'")))));
-}
-
-TEST(DiagnosticsTest, ClangTidy) {
- Annotations Test(R"cpp(
- #include $deprecated[["assert.h"]]
-
- #define $macrodef[[SQUARE]](X) (X)*(X)
- int main() {
- return $doubled[[sizeof]](sizeof(int));
- int y = 4;
- return SQUARE($macroarg[[++]]y);
- }
- )cpp");
- auto TU = TestTU::withCode(Test.code());
- TU.HeaderFilename = "assert.h"; // Suppress "not found" error.
- EXPECT_THAT(
- TU.build().getDiagnostics(),
- UnorderedElementsAre(
- AllOf(Diag(Test.range("deprecated"),
- "inclusion of deprecated C++ header 'assert.h'; consider "
- "using 'cassert' instead [modernize-deprecated-headers]"),
- WithFix(Fix(Test.range("deprecated"), "<cassert>",
- "change '\"assert.h\"' to '<cassert>'"))),
- Diag(Test.range("doubled"),
- "suspicious usage of 'sizeof(sizeof(...))' "
- "[bugprone-sizeof-expression]"),
- AllOf(
- Diag(Test.range("macroarg"),
- "side effects in the 1st macro argument 'X' are repeated in "
- "macro expansion [bugprone-macro-repeated-side-effects]"),
- WithNote(Diag(Test.range("macrodef"),
- "macro 'SQUARE' defined here "
- "[bugprone-macro-repeated-side-effects]"))),
- Diag(Test.range("macroarg"),
- "multiple unsequenced modifications to 'y'")));
-}
-
-TEST(DiagnosticsTest, Preprocessor) {
- // This looks like a preamble, but there's an #else in the middle!
- // Check that:
- // - the #else doesn't generate diagnostics (we had this bug)
- // - we get diagnostics from the taken branch
- // - we get no diagnostics from the not taken branch
- Annotations Test(R"cpp(
- #ifndef FOO
- #define FOO
- int a = [[b]];
- #else
- int x = y;
- #endif
- )cpp");
- EXPECT_THAT(
- TestTU::withCode(Test.code()).build().getDiagnostics(),
- ElementsAre(Diag(Test.range(), "use of undeclared identifier 'b'")));
-}
-
-TEST(DiagnosticsTest, InsideMacros) {
- Annotations Test(R"cpp(
- #define TEN 10
- #define RET(x) return x + 10
-
- int* foo() {
- RET($foo[[0]]);
- }
- int* bar() {
- return $bar[[TEN]];
- }
- )cpp");
- EXPECT_THAT(TestTU::withCode(Test.code()).build().getDiagnostics(),
- ElementsAre(Diag(Test.range("foo"),
- "cannot initialize return object of type "
- "'int *' with an rvalue of type 'int'"),
- Diag(Test.range("bar"),
- "cannot initialize return object of type "
- "'int *' with an rvalue of type 'int'")));
-}
-
-TEST(DiagnosticsTest, ToLSP) {
- clangd::Diag D;
- D.Message = "something terrible happened";
- D.Range = {pos(1, 2), pos(3, 4)};
- D.InsideMainFile = true;
- D.Severity = DiagnosticsEngine::Error;
- D.File = "foo/bar/main.cpp";
-
- clangd::Note NoteInMain;
- NoteInMain.Message = "declared somewhere in the main file";
- NoteInMain.Range = {pos(5, 6), pos(7, 8)};
- NoteInMain.Severity = DiagnosticsEngine::Remark;
- NoteInMain.File = "../foo/bar/main.cpp";
- NoteInMain.InsideMainFile = true;
- D.Notes.push_back(NoteInMain);
-
- clangd::Note NoteInHeader;
- NoteInHeader.Message = "declared somewhere in the header file";
- NoteInHeader.Range = {pos(9, 10), pos(11, 12)};
- NoteInHeader.Severity = DiagnosticsEngine::Note;
- NoteInHeader.File = "../foo/baz/header.h";
- NoteInHeader.InsideMainFile = false;
- D.Notes.push_back(NoteInHeader);
-
- clangd::Fix F;
- F.Message = "do something";
- D.Fixes.push_back(F);
-
- auto MatchingLSP = [](const DiagBase &D, StringRef Message) {
- clangd::Diagnostic Res;
- Res.range = D.Range;
- Res.severity = getSeverity(D.Severity);
- Res.message = Message;
- return Res;
- };
-
- // Diagnostics should turn into these:
- clangd::Diagnostic MainLSP = MatchingLSP(D, R"(Something terrible happened
-
-main.cpp:6:7: remark: declared somewhere in the main file
-
-../foo/baz/header.h:10:11:
-note: declared somewhere in the header file)");
-
- clangd::Diagnostic NoteInMainLSP =
- MatchingLSP(NoteInMain, R"(Declared somewhere in the main file
-
-main.cpp:2:3: error: something terrible happened)");
-
- // Transform dianostics and check the results.
- std::vector<std::pair<clangd::Diagnostic, std::vector<clangd::Fix>>> LSPDiags;
- toLSPDiags(D,
-#ifdef _WIN32
- URIForFile::canonicalize("c:\\path\\to\\foo\\bar\\main.cpp",
- /*TUPath=*/""),
-#else
- URIForFile::canonicalize("/path/to/foo/bar/main.cpp", /*TUPath=*/""),
-#endif
- ClangdDiagnosticOptions(),
- [&](clangd::Diagnostic LSPDiag, ArrayRef<clangd::Fix> Fixes) {
- LSPDiags.push_back(
- {std::move(LSPDiag),
- std::vector<clangd::Fix>(Fixes.begin(), Fixes.end())});
- });
-
- EXPECT_THAT(
- LSPDiags,
- ElementsAre(Pair(EqualToLSPDiag(MainLSP), ElementsAre(EqualToFix(F))),
- Pair(EqualToLSPDiag(NoteInMainLSP), IsEmpty())));
-}
-
-TEST(ClangdUnitTest, GetBeginningOfIdentifier) {
- std::string Preamble = R"cpp(
-struct Bar { int func(); };
-#define MACRO(X) void f() { X; }
-Bar* bar;
- )cpp";
- // First ^ is the expected beginning, last is the search position.
- for (std::string Text : std::vector<std::string>{
- "int ^f^oo();", // inside identifier
- "int ^foo();", // beginning of identifier
- "int ^foo^();", // end of identifier
- "int foo(^);", // non-identifier
- "^int foo();", // beginning of file (can't back up)
- "int ^f0^0();", // after a digit (lexing at N-1 is wrong)
- "int ^λλ^λ();", // UTF-8 handled properly when backing up
-
- // identifier in macro arg
- "MACRO(bar->^func())", // beginning of identifier
- "MACRO(bar->^fun^c())", // inside identifier
- "MACRO(bar->^func^())", // end of identifier
- "MACRO(^bar->func())", // begin identifier
- "MACRO(^bar^->func())", // end identifier
- "^MACRO(bar->func())", // beginning of macro name
- "^MAC^RO(bar->func())", // inside macro name
- "^MACRO^(bar->func())", // end of macro name
- }) {
- std::string WithPreamble = Preamble + Text;
- Annotations TestCase(WithPreamble);
- auto AST = TestTU::withCode(TestCase.code()).build();
- const auto &SourceMgr = AST.getASTContext().getSourceManager();
- SourceLocation Actual = getBeginningOfIdentifier(
- AST, TestCase.points().back(), SourceMgr.getMainFileID());
- Position ActualPos = offsetToPosition(
- TestCase.code(),
- SourceMgr.getFileOffset(SourceMgr.getSpellingLoc(Actual)));
- EXPECT_EQ(TestCase.points().front(), ActualPos) << Text;
- }
-}
-
-MATCHER_P(DeclNamed, Name, "") {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(arg))
- if (ND->getName() == Name)
- return true;
- if (auto *Stream = result_listener->stream()) {
- llvm::raw_os_ostream OS(*Stream);
- arg->dump(OS);
- }
- return false;
-}
-
-TEST(ClangdUnitTest, TopLevelDecls) {
- TestTU TU;
- TU.HeaderCode = R"(
- int header1();
- int header2;
- )";
- TU.Code = "int main();";
- auto AST = TU.build();
- EXPECT_THAT(AST.getLocalTopLevelDecls(), ElementsAre(DeclNamed("main")));
-}
-
-} // namespace
-} // namespace clangd
-} // namespace clang
diff --git a/unittests/clangd/SourceCodeTests.cpp b/unittests/clangd/SourceCodeTests.cpp
deleted file mode 100644
index b170c130..00000000
--- a/unittests/clangd/SourceCodeTests.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-//===-- SourceCodeTests.cpp ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "SourceCode.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/raw_os_ostream.h"
-#include "llvm/Testing/Support/Error.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-namespace clang {
-namespace clangd {
-namespace {
-
-MATCHER_P2(Pos, Line, Col, "") {
- return arg.line == Line && arg.character == Col;
-}
-
-// The = → 🡆 below are ASCII (1 byte), BMP (3 bytes), and astral (4 bytes).
-const char File[] = R"(0:0 = 0
-1:0 → 8
-2:0 🡆 18)";
-
-/// A helper to make tests easier to read.
-Position position(int line, int character) {
- Position Pos;
- Pos.line = line;
- Pos.character = character;
- return Pos;
-}
-
-Range range(const std::pair<int, int> p1, const std::pair<int, int> p2) {
- Range range;
- range.start = position(p1.first, p1.second);
- range.end = position(p2.first, p2.second);
- return range;
-}
-
-TEST(SourceCodeTests, lspLength) {
- EXPECT_EQ(lspLength(""), 0UL);
- EXPECT_EQ(lspLength("ascii"), 5UL);
- // BMP
- EXPECT_EQ(lspLength("↓"), 1UL);
- EXPECT_EQ(lspLength("¥"), 1UL);
- // astral
- EXPECT_EQ(lspLength("😂"), 2UL);
-}
-
-TEST(SourceCodeTests, PositionToOffset) {
- // line out of bounds
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), llvm::Failed());
- // first line
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, -1)),
- llvm::Failed()); // out of range
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 0)),
- llvm::HasValue(0)); // first character
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 3)),
- llvm::HasValue(3)); // middle character
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 6)),
- llvm::HasValue(6)); // last character
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7)),
- llvm::HasValue(7)); // the newline itself
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7), false),
- llvm::HasValue(7));
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8)),
- llvm::HasValue(7)); // out of range
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8), false),
- llvm::Failed()); // out of range
- // middle line
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, -1)),
- llvm::Failed()); // out of range
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 0)),
- llvm::HasValue(8)); // first character
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3)),
- llvm::HasValue(11)); // middle character
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3), false),
- llvm::HasValue(11));
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 6)),
- llvm::HasValue(16)); // last character
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 7)),
- llvm::HasValue(17)); // the newline itself
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8)),
- llvm::HasValue(17)); // out of range
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8), false),
- llvm::Failed()); // out of range
- // last line
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, -1)),
- llvm::Failed()); // out of range
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 0)),
- llvm::HasValue(18)); // first character
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 3)),
- llvm::HasValue(21)); // middle character
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5), false),
- llvm::Failed()); // middle of surrogate pair
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5)),
- llvm::HasValue(26)); // middle of surrogate pair
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 6), false),
- llvm::HasValue(26)); // end of surrogate pair
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 8)),
- llvm::HasValue(28)); // last character
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 9)),
- llvm::HasValue(29)); // EOF
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 10), false),
- llvm::Failed()); // out of range
- // line out of bounds
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), llvm::Failed());
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 1)), llvm::Failed());
-}
-
-TEST(SourceCodeTests, OffsetToPosition) {
- EXPECT_THAT(offsetToPosition(File, 0), Pos(0, 0)) << "start of file";
- EXPECT_THAT(offsetToPosition(File, 3), Pos(0, 3)) << "in first line";
- EXPECT_THAT(offsetToPosition(File, 6), Pos(0, 6)) << "end of first line";
- EXPECT_THAT(offsetToPosition(File, 7), Pos(0, 7)) << "first newline";
- EXPECT_THAT(offsetToPosition(File, 8), Pos(1, 0)) << "start of second line";
- EXPECT_THAT(offsetToPosition(File, 12), Pos(1, 4)) << "before BMP char";
- EXPECT_THAT(offsetToPosition(File, 13), Pos(1, 5)) << "in BMP char";
- EXPECT_THAT(offsetToPosition(File, 15), Pos(1, 5)) << "after BMP char";
- EXPECT_THAT(offsetToPosition(File, 16), Pos(1, 6)) << "end of second line";
- EXPECT_THAT(offsetToPosition(File, 17), Pos(1, 7)) << "second newline";
- EXPECT_THAT(offsetToPosition(File, 18), Pos(2, 0)) << "start of last line";
- EXPECT_THAT(offsetToPosition(File, 21), Pos(2, 3)) << "in last line";
- EXPECT_THAT(offsetToPosition(File, 22), Pos(2, 4)) << "before astral char";
- EXPECT_THAT(offsetToPosition(File, 24), Pos(2, 6)) << "in astral char";
- EXPECT_THAT(offsetToPosition(File, 26), Pos(2, 6)) << "after astral char";
- EXPECT_THAT(offsetToPosition(File, 28), Pos(2, 8)) << "end of last line";
- EXPECT_THAT(offsetToPosition(File, 29), Pos(2, 9)) << "EOF";
- EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 9)) << "out of bounds";
-}
-
-TEST(SourceCodeTests, IsRangeConsecutive) {
- EXPECT_TRUE(IsRangeConsecutive(range({2, 2}, {2, 3}), range({2, 3}, {2, 4})));
- EXPECT_FALSE(
- IsRangeConsecutive(range({0, 2}, {0, 3}), range({2, 3}, {2, 4})));
- EXPECT_FALSE(
- IsRangeConsecutive(range({2, 2}, {2, 3}), range({2, 4}, {2, 5})));
-}
-
-} // namespace
-} // namespace clangd
-} // namespace clang
diff --git a/unittests/clangd/TestIndex.cpp b/unittests/clangd/TestIndex.cpp
deleted file mode 100644
index 714d3a68..00000000
--- a/unittests/clangd/TestIndex.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-//===-- IndexHelpers.cpp ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "TestIndex.h"
-
-namespace clang {
-namespace clangd {
-
-Symbol symbol(llvm::StringRef QName) {
- Symbol Sym;
- Sym.ID = SymbolID(QName.str());
- size_t Pos = QName.rfind("::");
- if (Pos == llvm::StringRef::npos) {
- Sym.Name = QName;
- Sym.Scope = "";
- } else {
- Sym.Name = QName.substr(Pos + 2);
- Sym.Scope = QName.substr(0, Pos + 2);
- }
- return Sym;
-}
-
-SymbolSlab generateSymbols(std::vector<std::string> QualifiedNames) {
- SymbolSlab::Builder Slab;
- for (llvm::StringRef QName : QualifiedNames)
- Slab.insert(symbol(QName));
- return std::move(Slab).build();
-}
-
-SymbolSlab generateNumSymbols(int Begin, int End) {
- std::vector<std::string> Names;
- for (int i = Begin; i <= End; i++)
- Names.push_back(std::to_string(i));
- return generateSymbols(Names);
-}
-
-std::string getQualifiedName(const Symbol &Sym) {
- return (Sym.Scope + Sym.Name).str();
-}
-
-std::vector<std::string> match(const SymbolIndex &I,
- const FuzzyFindRequest &Req, bool *Incomplete) {
- std::vector<std::string> Matches;
- bool IsIncomplete = I.fuzzyFind(Req, [&](const Symbol &Sym) {
- Matches.push_back(clang::clangd::getQualifiedName(Sym));
- });
- if (Incomplete)
- *Incomplete = IsIncomplete;
- return Matches;
-}
-
-// Returns qualified names of symbols with any of IDs in the index.
-std::vector<std::string> lookup(const SymbolIndex &I,
- llvm::ArrayRef<SymbolID> IDs) {
- LookupRequest Req;
- Req.IDs.insert(IDs.begin(), IDs.end());
- std::vector<std::string> Results;
- I.lookup(Req, [&](const Symbol &Sym) {
- Results.push_back(getQualifiedName(Sym));
- });
- return Results;
-}
-
-} // namespace clangd
-} // namespace clang
diff --git a/unittests/include/common/VirtualFileHelper.h b/unittests/include/common/VirtualFileHelper.h
index 5fa4d53a..03eddb87 100644
--- a/unittests/include/common/VirtualFileHelper.h
+++ b/unittests/include/common/VirtualFileHelper.h
@@ -1,9 +1,8 @@
//===--- VirtualFileHelper.h ------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///