aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt5
-rw-r--r--LICENSE.TXT259
-rw-r--r--change-namespace/ChangeNamespace.cpp7
-rw-r--r--change-namespace/ChangeNamespace.h7
-rw-r--r--change-namespace/tool/ClangChangeNamespace.cpp7
-rw-r--r--clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h7
-rw-r--r--clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp7
-rw-r--r--clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp7
-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.cpp7
-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.cpp7
-rw-r--r--clang-doc/Serialize.h7
-rw-r--r--clang-doc/YAMLGenerator.cpp7
-rw-r--r--clang-doc/tool/ClangDocMain.cpp7
-rw-r--r--clang-move/ClangMove.cpp12
-rw-r--r--clang-move/ClangMove.h7
-rw-r--r--clang-move/HelperDeclRefGraph.cpp7
-rw-r--r--clang-move/HelperDeclRefGraph.h7
-rw-r--r--clang-move/tool/ClangMoveMain.cpp7
-rw-r--r--clang-query/Query.cpp7
-rw-r--r--clang-query/Query.h7
-rw-r--r--clang-query/QueryParser.cpp50
-rw-r--r--clang-query/QueryParser.h12
-rw-r--r--clang-query/QuerySession.h8
-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/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/ClangTidy.cpp25
-rw-r--r--clang-tidy/ClangTidy.h7
-rw-r--r--clang-tidy/ClangTidyDiagnosticConsumer.cpp13
-rw-r--r--clang-tidy/ClangTidyDiagnosticConsumer.h7
-rw-r--r--clang-tidy/ClangTidyForceLinker.h7
-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/abseil/AbseilMatcher.h7
-rw-r--r--clang-tidy/abseil/AbseilTidyModule.cpp16
-rw-r--r--clang-tidy/abseil/CMakeLists.txt3
-rw-r--r--clang-tidy/abseil/DurationAdditionCheck.cpp73
-rw-r--r--clang-tidy/abseil/DurationAdditionCheck.h35
-rw-r--r--clang-tidy/abseil/DurationComparisonCheck.cpp27
-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.cpp15
-rw-r--r--clang-tidy/abseil/DurationFactoryScaleCheck.h7
-rw-r--r--clang-tidy/abseil/DurationRewriter.cpp105
-rw-r--r--clang-tidy/abseil/DurationRewriter.h39
-rw-r--r--clang-tidy/abseil/DurationSubtractionCheck.cpp16
-rw-r--r--clang-tidy/abseil/DurationSubtractionCheck.h7
-rw-r--r--clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp58
-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.cpp7
-rw-r--r--clang-tidy/abseil/StringFindStartswithCheck.h7
-rw-r--r--clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp7
-rw-r--r--clang-tidy/abseil/UpgradeDurationConversionsCheck.h7
-rwxr-xr-xclang-tidy/add_new_check.py21
-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.h7
-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.h7
-rw-r--r--clang-tidy/boost/BoostTidyModule.cpp7
-rw-r--r--clang-tidy/boost/UseToStringCheck.cpp7
-rw-r--r--clang-tidy/boost/UseToStringCheck.h7
-rw-r--r--clang-tidy/bugprone/ArgumentCommentCheck.cpp74
-rw-r--r--clang-tidy/bugprone/ArgumentCommentCheck.h21
-rw-r--r--clang-tidy/bugprone/AssertSideEffectCheck.cpp7
-rw-r--r--clang-tidy/bugprone/AssertSideEffectCheck.h7
-rw-r--r--clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp7
-rw-r--r--clang-tidy/bugprone/BoolPointerImplicitConversionCheck.h7
-rw-r--r--clang-tidy/bugprone/BugproneTidyModule.cpp7
-rw-r--r--clang-tidy/bugprone/CopyConstructorInitCheck.cpp7
-rw-r--r--clang-tidy/bugprone/CopyConstructorInitCheck.h7
-rw-r--r--clang-tidy/bugprone/DanglingHandleCheck.cpp7
-rw-r--r--clang-tidy/bugprone/DanglingHandleCheck.h7
-rw-r--r--clang-tidy/bugprone/ExceptionEscapeCheck.cpp172
-rw-r--r--clang-tidy/bugprone/ExceptionEscapeCheck.h13
-rw-r--r--clang-tidy/bugprone/FoldInitTypeCheck.cpp7
-rw-r--r--clang-tidy/bugprone/FoldInitTypeCheck.h7
-rw-r--r--clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp7
-rw-r--r--clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.h7
-rw-r--r--clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp7
-rw-r--r--clang-tidy/bugprone/ForwardingReferenceOverloadCheck.h7
-rw-r--r--clang-tidy/bugprone/InaccurateEraseCheck.cpp7
-rw-r--r--clang-tidy/bugprone/InaccurateEraseCheck.h7
-rw-r--r--clang-tidy/bugprone/IncorrectRoundingsCheck.cpp7
-rw-r--r--clang-tidy/bugprone/IncorrectRoundingsCheck.h7
-rw-r--r--clang-tidy/bugprone/IntegerDivisionCheck.cpp7
-rw-r--r--clang-tidy/bugprone/IntegerDivisionCheck.h7
-rw-r--r--clang-tidy/bugprone/LambdaFunctionNameCheck.cpp7
-rw-r--r--clang-tidy/bugprone/LambdaFunctionNameCheck.h7
-rw-r--r--clang-tidy/bugprone/MacroParenthesesCheck.cpp7
-rw-r--r--clang-tidy/bugprone/MacroParenthesesCheck.h7
-rw-r--r--clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.cpp7
-rw-r--r--clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.h7
-rw-r--r--clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp7
-rw-r--r--clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h7
-rw-r--r--clang-tidy/bugprone/MisplacedWideningCastCheck.cpp7
-rw-r--r--clang-tidy/bugprone/MisplacedWideningCastCheck.h7
-rw-r--r--clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp7
-rw-r--r--clang-tidy/bugprone/MoveForwardingReferenceCheck.h7
-rw-r--r--clang-tidy/bugprone/MultipleStatementMacroCheck.cpp7
-rw-r--r--clang-tidy/bugprone/MultipleStatementMacroCheck.h7
-rwxr-xr-xclang-tidy/bugprone/ParentVirtualCallCheck.cpp11
-rwxr-xr-xclang-tidy/bugprone/ParentVirtualCallCheck.h7
-rw-r--r--clang-tidy/bugprone/SizeofContainerCheck.cpp7
-rw-r--r--clang-tidy/bugprone/SizeofContainerCheck.h7
-rw-r--r--clang-tidy/bugprone/SizeofExpressionCheck.cpp7
-rw-r--r--clang-tidy/bugprone/SizeofExpressionCheck.h7
-rw-r--r--clang-tidy/bugprone/StringConstructorCheck.cpp23
-rw-r--r--clang-tidy/bugprone/StringConstructorCheck.h7
-rw-r--r--clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp7
-rw-r--r--clang-tidy/bugprone/StringIntegerAssignmentCheck.h7
-rw-r--r--clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.cpp7
-rw-r--r--clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.h7
-rw-r--r--clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp7
-rw-r--r--clang-tidy/bugprone/SuspiciousEnumUsageCheck.h7
-rw-r--r--clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp7
-rw-r--r--clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h7
-rw-r--r--clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp7
-rw-r--r--clang-tidy/bugprone/SuspiciousMissingCommaCheck.h7
-rw-r--r--clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp7
-rw-r--r--clang-tidy/bugprone/SuspiciousSemicolonCheck.h7
-rw-r--r--clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp7
-rw-r--r--clang-tidy/bugprone/SuspiciousStringCompareCheck.h7
-rw-r--r--clang-tidy/bugprone/SwappedArgumentsCheck.cpp7
-rw-r--r--clang-tidy/bugprone/SwappedArgumentsCheck.h7
-rw-r--r--clang-tidy/bugprone/TerminatingContinueCheck.cpp7
-rw-r--r--clang-tidy/bugprone/TerminatingContinueCheck.h7
-rw-r--r--clang-tidy/bugprone/ThrowKeywordMissingCheck.cpp7
-rw-r--r--clang-tidy/bugprone/ThrowKeywordMissingCheck.h7
-rw-r--r--clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp7
-rw-r--r--clang-tidy/bugprone/TooSmallLoopVariableCheck.h7
-rw-r--r--clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp7
-rw-r--r--clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h7
-rw-r--r--clang-tidy/bugprone/UndelegatedConstructorCheck.cpp7
-rw-r--r--clang-tidy/bugprone/UndelegatedConstructorCheck.h7
-rw-r--r--clang-tidy/bugprone/UnusedRaiiCheck.cpp7
-rw-r--r--clang-tidy/bugprone/UnusedRaiiCheck.h7
-rw-r--r--clang-tidy/bugprone/UnusedReturnValueCheck.cpp7
-rw-r--r--clang-tidy/bugprone/UnusedReturnValueCheck.h7
-rw-r--r--clang-tidy/bugprone/UseAfterMoveCheck.cpp9
-rw-r--r--clang-tidy/bugprone/UseAfterMoveCheck.h7
-rw-r--r--clang-tidy/bugprone/VirtualNearMissCheck.cpp7
-rw-r--r--clang-tidy/bugprone/VirtualNearMissCheck.h7
-rw-r--r--clang-tidy/cert/CERTTidyModule.cpp7
-rw-r--r--clang-tidy/cert/CommandProcessorCheck.cpp7
-rw-r--r--clang-tidy/cert/CommandProcessorCheck.h7
-rw-r--r--clang-tidy/cert/DontModifyStdNamespaceCheck.cpp7
-rw-r--r--clang-tidy/cert/DontModifyStdNamespaceCheck.h7
-rw-r--r--clang-tidy/cert/FloatLoopCounter.cpp7
-rw-r--r--clang-tidy/cert/FloatLoopCounter.h7
-rw-r--r--clang-tidy/cert/LICENSE.TXT4
-rw-r--r--clang-tidy/cert/LimitedRandomnessCheck.cpp7
-rw-r--r--clang-tidy/cert/LimitedRandomnessCheck.h7
-rw-r--r--clang-tidy/cert/PostfixOperatorCheck.cpp7
-rw-r--r--clang-tidy/cert/PostfixOperatorCheck.h7
-rw-r--r--clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp7
-rw-r--r--clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h7
-rw-r--r--clang-tidy/cert/SetLongJmpCheck.cpp7
-rw-r--r--clang-tidy/cert/SetLongJmpCheck.h7
-rw-r--r--clang-tidy/cert/StaticObjectExceptionCheck.cpp7
-rw-r--r--clang-tidy/cert/StaticObjectExceptionCheck.h7
-rw-r--r--clang-tidy/cert/StrToNumCheck.cpp7
-rw-r--r--clang-tidy/cert/StrToNumCheck.h7
-rw-r--r--clang-tidy/cert/ThrownExceptionTypeCheck.cpp7
-rw-r--r--clang-tidy/cert/ThrownExceptionTypeCheck.h7
-rw-r--r--clang-tidy/cert/VariadicFunctionDefCheck.cpp7
-rw-r--r--clang-tidy/cert/VariadicFunctionDefCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/AvoidGotoCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/AvoidGotoCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.h7
-rw-r--r--clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/MacroUsageCheck.h7
-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.cpp7
-rw-r--r--clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h7
-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.h7
-rw-r--r--clang-tidy/fuchsia/FuchsiaTidyModule.cpp7
-rw-r--r--clang-tidy/fuchsia/MultipleInheritanceCheck.cpp7
-rw-r--r--clang-tidy/fuchsia/MultipleInheritanceCheck.h7
-rw-r--r--clang-tidy/fuchsia/OverloadedOperatorCheck.cpp9
-rw-r--r--clang-tidy/fuchsia/OverloadedOperatorCheck.h7
-rw-r--r--clang-tidy/fuchsia/RestrictSystemIncludesCheck.cpp7
-rw-r--r--clang-tidy/fuchsia/RestrictSystemIncludesCheck.h7
-rw-r--r--clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp7
-rw-r--r--clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.h7
-rw-r--r--clang-tidy/fuchsia/TrailingReturnCheck.cpp7
-rw-r--r--clang-tidy/fuchsia/TrailingReturnCheck.h7
-rw-r--r--clang-tidy/fuchsia/VirtualInheritanceCheck.cpp7
-rw-r--r--clang-tidy/fuchsia/VirtualInheritanceCheck.h7
-rw-r--r--clang-tidy/google/AvoidCStyleCastsCheck.cpp7
-rw-r--r--clang-tidy/google/AvoidCStyleCastsCheck.h7
-rw-r--r--clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp7
-rw-r--r--clang-tidy/google/AvoidThrowingObjCExceptionCheck.h7
-rw-r--r--clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp89
-rw-r--r--clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h33
-rw-r--r--clang-tidy/google/CMakeLists.txt1
-rw-r--r--clang-tidy/google/DefaultArgumentsCheck.cpp7
-rw-r--r--clang-tidy/google/DefaultArgumentsCheck.h7
-rw-r--r--clang-tidy/google/ExplicitConstructorCheck.cpp7
-rw-r--r--clang-tidy/google/ExplicitConstructorCheck.h7
-rw-r--r--clang-tidy/google/ExplicitMakePairCheck.cpp7
-rw-r--r--clang-tidy/google/ExplicitMakePairCheck.h7
-rw-r--r--clang-tidy/google/FunctionNamingCheck.cpp7
-rw-r--r--clang-tidy/google/FunctionNamingCheck.h7
-rw-r--r--clang-tidy/google/GlobalNamesInHeadersCheck.cpp7
-rw-r--r--clang-tidy/google/GlobalNamesInHeadersCheck.h7
-rw-r--r--clang-tidy/google/GlobalVariableDeclarationCheck.cpp7
-rw-r--r--clang-tidy/google/GlobalVariableDeclarationCheck.h7
-rw-r--r--clang-tidy/google/GoogleTidyModule.cpp11
-rw-r--r--clang-tidy/google/IntegerTypesCheck.cpp7
-rw-r--r--clang-tidy/google/IntegerTypesCheck.h7
-rw-r--r--clang-tidy/google/NonConstReferences.cpp7
-rw-r--r--clang-tidy/google/NonConstReferences.h7
-rw-r--r--clang-tidy/google/OverloadedUnaryAndCheck.cpp7
-rw-r--r--clang-tidy/google/OverloadedUnaryAndCheck.h7
-rw-r--r--clang-tidy/google/TodoCommentCheck.cpp7
-rw-r--r--clang-tidy/google/TodoCommentCheck.h7
-rw-r--r--clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp7
-rw-r--r--clang-tidy/google/UnnamedNamespaceInHeaderCheck.h7
-rw-r--r--clang-tidy/google/UsingNamespaceDirectiveCheck.cpp7
-rw-r--r--clang-tidy/google/UsingNamespaceDirectiveCheck.h7
-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/HeaderGuardCheck.cpp7
-rw-r--r--clang-tidy/llvm/HeaderGuardCheck.h7
-rw-r--r--clang-tidy/llvm/IncludeOrderCheck.cpp7
-rw-r--r--clang-tidy/llvm/IncludeOrderCheck.h7
-rw-r--r--clang-tidy/llvm/LLVMTidyModule.cpp7
-rw-r--r--clang-tidy/llvm/TwineLocalCheck.cpp7
-rw-r--r--clang-tidy/llvm/TwineLocalCheck.h7
-rw-r--r--clang-tidy/misc/DefinitionsInHeadersCheck.cpp7
-rw-r--r--clang-tidy/misc/DefinitionsInHeadersCheck.h7
-rw-r--r--clang-tidy/misc/MiscTidyModule.cpp7
-rw-r--r--clang-tidy/misc/MisplacedConstCheck.cpp7
-rw-r--r--clang-tidy/misc/MisplacedConstCheck.h7
-rw-r--r--clang-tidy/misc/NewDeleteOverloadsCheck.cpp7
-rw-r--r--clang-tidy/misc/NewDeleteOverloadsCheck.h7
-rw-r--r--clang-tidy/misc/NonCopyableObjects.cpp7
-rw-r--r--clang-tidy/misc/NonCopyableObjects.h7
-rw-r--r--clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.cpp18
-rw-r--r--clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.h7
-rw-r--r--clang-tidy/misc/RedundantExpressionCheck.cpp7
-rw-r--r--clang-tidy/misc/RedundantExpressionCheck.h7
-rw-r--r--clang-tidy/misc/StaticAssertCheck.cpp7
-rw-r--r--clang-tidy/misc/StaticAssertCheck.h7
-rw-r--r--clang-tidy/misc/ThrowByValueCatchByReferenceCheck.cpp7
-rw-r--r--clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h7
-rw-r--r--clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp7
-rw-r--r--clang-tidy/misc/UnconventionalAssignOperatorCheck.h7
-rw-r--r--clang-tidy/misc/UniqueptrResetReleaseCheck.cpp7
-rw-r--r--clang-tidy/misc/UniqueptrResetReleaseCheck.h7
-rw-r--r--clang-tidy/misc/UnusedAliasDeclsCheck.cpp7
-rw-r--r--clang-tidy/misc/UnusedAliasDeclsCheck.h7
-rw-r--r--clang-tidy/misc/UnusedParametersCheck.cpp7
-rw-r--r--clang-tidy/misc/UnusedParametersCheck.h7
-rw-r--r--clang-tidy/misc/UnusedUsingDeclsCheck.cpp7
-rw-r--r--clang-tidy/misc/UnusedUsingDeclsCheck.h7
-rw-r--r--clang-tidy/modernize/AvoidBindCheck.cpp9
-rw-r--r--clang-tidy/modernize/AvoidBindCheck.h7
-rw-r--r--clang-tidy/modernize/AvoidCArraysCheck.cpp16
-rw-r--r--clang-tidy/modernize/AvoidCArraysCheck.h7
-rw-r--r--clang-tidy/modernize/CMakeLists.txt1
-rw-r--r--clang-tidy/modernize/ConcatNestedNamespacesCheck.cpp7
-rw-r--r--clang-tidy/modernize/ConcatNestedNamespacesCheck.h7
-rw-r--r--clang-tidy/modernize/DeprecatedHeadersCheck.cpp7
-rw-r--r--clang-tidy/modernize/DeprecatedHeadersCheck.h7
-rw-r--r--clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp7
-rw-r--r--clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.h7
-rw-r--r--clang-tidy/modernize/LoopConvertCheck.cpp7
-rw-r--r--clang-tidy/modernize/LoopConvertCheck.h7
-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.cpp7
-rw-r--r--clang-tidy/modernize/MakeSmartPtrCheck.h7
-rw-r--r--clang-tidy/modernize/MakeUniqueCheck.cpp7
-rw-r--r--clang-tidy/modernize/MakeUniqueCheck.h7
-rw-r--r--clang-tidy/modernize/ModernizeTidyModule.cpp10
-rw-r--r--clang-tidy/modernize/PassByValueCheck.cpp7
-rw-r--r--clang-tidy/modernize/PassByValueCheck.h7
-rw-r--r--clang-tidy/modernize/RawStringLiteralCheck.cpp7
-rw-r--r--clang-tidy/modernize/RawStringLiteralCheck.h7
-rw-r--r--clang-tidy/modernize/RedundantVoidArgCheck.cpp7
-rw-r--r--clang-tidy/modernize/RedundantVoidArgCheck.h7
-rw-r--r--clang-tidy/modernize/ReplaceAutoPtrCheck.cpp7
-rw-r--r--clang-tidy/modernize/ReplaceAutoPtrCheck.h7
-rw-r--r--clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp7
-rw-r--r--clang-tidy/modernize/ReplaceRandomShuffleCheck.h7
-rw-r--r--clang-tidy/modernize/ReturnBracedInitListCheck.cpp7
-rw-r--r--clang-tidy/modernize/ReturnBracedInitListCheck.h7
-rw-r--r--clang-tidy/modernize/ShrinkToFitCheck.cpp7
-rw-r--r--clang-tidy/modernize/ShrinkToFitCheck.h7
-rw-r--r--clang-tidy/modernize/UnaryStaticAssertCheck.cpp7
-rw-r--r--clang-tidy/modernize/UnaryStaticAssertCheck.h7
-rw-r--r--clang-tidy/modernize/UseAutoCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseAutoCheck.h7
-rw-r--r--clang-tidy/modernize/UseBoolLiteralsCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseBoolLiteralsCheck.h7
-rw-r--r--clang-tidy/modernize/UseDefaultMemberInitCheck.cpp18
-rw-r--r--clang-tidy/modernize/UseDefaultMemberInitCheck.h7
-rw-r--r--clang-tidy/modernize/UseEmplaceCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseEmplaceCheck.h7
-rw-r--r--clang-tidy/modernize/UseEqualsDefaultCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseEqualsDefaultCheck.h7
-rw-r--r--clang-tidy/modernize/UseEqualsDeleteCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseEqualsDeleteCheck.h7
-rw-r--r--clang-tidy/modernize/UseNodiscardCheck.cpp144
-rw-r--r--clang-tidy/modernize/UseNodiscardCheck.h49
-rw-r--r--clang-tidy/modernize/UseNoexceptCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseNoexceptCheck.h7
-rw-r--r--clang-tidy/modernize/UseNullptrCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseNullptrCheck.h7
-rw-r--r--clang-tidy/modernize/UseOverrideCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseOverrideCheck.h7
-rw-r--r--clang-tidy/modernize/UseTransparentFunctorsCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseTransparentFunctorsCheck.h7
-rw-r--r--clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseUncaughtExceptionsCheck.h7
-rw-r--r--clang-tidy/modernize/UseUsingCheck.cpp7
-rw-r--r--clang-tidy/modernize/UseUsingCheck.h7
-rw-r--r--clang-tidy/mpi/BufferDerefCheck.cpp7
-rw-r--r--clang-tidy/mpi/BufferDerefCheck.h7
-rw-r--r--clang-tidy/mpi/MPITidyModule.cpp7
-rw-r--r--clang-tidy/mpi/TypeMismatchCheck.cpp7
-rw-r--r--clang-tidy/mpi/TypeMismatchCheck.h7
-rw-r--r--clang-tidy/objc/AvoidNSErrorInitCheck.cpp7
-rw-r--r--clang-tidy/objc/AvoidNSErrorInitCheck.h7
-rw-r--r--clang-tidy/objc/AvoidSpinlockCheck.cpp7
-rw-r--r--clang-tidy/objc/AvoidSpinlockCheck.h7
-rw-r--r--clang-tidy/objc/ForbiddenSubclassingCheck.cpp7
-rw-r--r--clang-tidy/objc/ForbiddenSubclassingCheck.h7
-rw-r--r--clang-tidy/objc/ObjCTidyModule.cpp7
-rw-r--r--clang-tidy/objc/PropertyDeclarationCheck.cpp7
-rw-r--r--clang-tidy/objc/PropertyDeclarationCheck.h7
-rw-r--r--clang-tidy/performance/FasterStringFindCheck.cpp7
-rw-r--r--clang-tidy/performance/FasterStringFindCheck.h7
-rw-r--r--clang-tidy/performance/ForRangeCopyCheck.cpp7
-rw-r--r--clang-tidy/performance/ForRangeCopyCheck.h7
-rw-r--r--clang-tidy/performance/ImplicitConversionInLoopCheck.cpp7
-rw-r--r--clang-tidy/performance/ImplicitConversionInLoopCheck.h7
-rw-r--r--clang-tidy/performance/InefficientAlgorithmCheck.cpp7
-rw-r--r--clang-tidy/performance/InefficientAlgorithmCheck.h7
-rw-r--r--clang-tidy/performance/InefficientStringConcatenationCheck.cpp7
-rw-r--r--clang-tidy/performance/InefficientStringConcatenationCheck.h7
-rw-r--r--clang-tidy/performance/InefficientVectorOperationCheck.cpp7
-rw-r--r--clang-tidy/performance/InefficientVectorOperationCheck.h7
-rw-r--r--clang-tidy/performance/MoveConstArgCheck.cpp7
-rw-r--r--clang-tidy/performance/MoveConstArgCheck.h7
-rw-r--r--clang-tidy/performance/MoveConstructorInitCheck.cpp7
-rw-r--r--clang-tidy/performance/MoveConstructorInitCheck.h7
-rw-r--r--clang-tidy/performance/NoexceptMoveConstructorCheck.cpp7
-rw-r--r--clang-tidy/performance/NoexceptMoveConstructorCheck.h7
-rw-r--r--clang-tidy/performance/PerformanceTidyModule.cpp7
-rw-r--r--clang-tidy/performance/TypePromotionInMathFnCheck.cpp7
-rw-r--r--clang-tidy/performance/TypePromotionInMathFnCheck.h7
-rw-r--r--clang-tidy/performance/UnnecessaryCopyInitialization.cpp7
-rw-r--r--clang-tidy/performance/UnnecessaryCopyInitialization.h7
-rw-r--r--clang-tidy/performance/UnnecessaryValueParamCheck.cpp7
-rw-r--r--clang-tidy/performance/UnnecessaryValueParamCheck.h7
-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.h7
-rw-r--r--clang-tidy/readability/AvoidConstParamsInDecls.cpp7
-rw-r--r--clang-tidy/readability/AvoidConstParamsInDecls.h7
-rw-r--r--clang-tidy/readability/BracesAroundStatementsCheck.cpp7
-rw-r--r--clang-tidy/readability/BracesAroundStatementsCheck.h7
-rw-r--r--clang-tidy/readability/CMakeLists.txt1
-rw-r--r--clang-tidy/readability/ConstReturnTypeCheck.cpp11
-rw-r--r--clang-tidy/readability/ConstReturnTypeCheck.h7
-rw-r--r--clang-tidy/readability/ContainerSizeEmptyCheck.cpp7
-rw-r--r--clang-tidy/readability/ContainerSizeEmptyCheck.h7
-rw-r--r--clang-tidy/readability/DeleteNullPointerCheck.cpp7
-rw-r--r--clang-tidy/readability/DeleteNullPointerCheck.h7
-rw-r--r--clang-tidy/readability/DeletedDefaultCheck.cpp7
-rw-r--r--clang-tidy/readability/DeletedDefaultCheck.h7
-rw-r--r--clang-tidy/readability/ElseAfterReturnCheck.cpp121
-rw-r--r--clang-tidy/readability/ElseAfterReturnCheck.h7
-rw-r--r--clang-tidy/readability/FunctionSizeCheck.cpp14
-rw-r--r--clang-tidy/readability/FunctionSizeCheck.h7
-rw-r--r--clang-tidy/readability/IdentifierNamingCheck.cpp7
-rw-r--r--clang-tidy/readability/IdentifierNamingCheck.h7
-rw-r--r--clang-tidy/readability/ImplicitBoolConversionCheck.cpp7
-rw-r--r--clang-tidy/readability/ImplicitBoolConversionCheck.h7
-rw-r--r--clang-tidy/readability/InconsistentDeclarationParameterNameCheck.cpp7
-rw-r--r--clang-tidy/readability/InconsistentDeclarationParameterNameCheck.h7
-rw-r--r--clang-tidy/readability/IsolateDeclarationCheck.cpp7
-rw-r--r--clang-tidy/readability/IsolateDeclarationCheck.h7
-rw-r--r--clang-tidy/readability/MagicNumbersCheck.cpp7
-rw-r--r--clang-tidy/readability/MagicNumbersCheck.h7
-rw-r--r--clang-tidy/readability/MisleadingIndentationCheck.cpp7
-rw-r--r--clang-tidy/readability/MisleadingIndentationCheck.h7
-rw-r--r--clang-tidy/readability/MisplacedArrayIndexCheck.cpp7
-rw-r--r--clang-tidy/readability/MisplacedArrayIndexCheck.h7
-rw-r--r--clang-tidy/readability/NamedParameterCheck.cpp7
-rw-r--r--clang-tidy/readability/NamedParameterCheck.h7
-rw-r--r--clang-tidy/readability/NamespaceCommentCheck.cpp7
-rw-r--r--clang-tidy/readability/NamespaceCommentCheck.h7
-rw-r--r--clang-tidy/readability/NonConstParameterCheck.cpp7
-rw-r--r--clang-tidy/readability/NonConstParameterCheck.h7
-rw-r--r--clang-tidy/readability/ReadabilityTidyModule.cpp10
-rw-r--r--clang-tidy/readability/RedundantControlFlowCheck.cpp7
-rw-r--r--clang-tidy/readability/RedundantControlFlowCheck.h7
-rw-r--r--clang-tidy/readability/RedundantDeclarationCheck.cpp7
-rw-r--r--clang-tidy/readability/RedundantDeclarationCheck.h7
-rw-r--r--clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp7
-rw-r--r--clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.h7
-rw-r--r--clang-tidy/readability/RedundantMemberInitCheck.cpp7
-rw-r--r--clang-tidy/readability/RedundantMemberInitCheck.h7
-rw-r--r--clang-tidy/readability/RedundantPreprocessorCheck.cpp108
-rw-r--r--clang-tidy/readability/RedundantPreprocessorCheck.h34
-rw-r--r--clang-tidy/readability/RedundantSmartptrGetCheck.cpp7
-rw-r--r--clang-tidy/readability/RedundantSmartptrGetCheck.h7
-rw-r--r--clang-tidy/readability/RedundantStringCStrCheck.cpp7
-rw-r--r--clang-tidy/readability/RedundantStringCStrCheck.h7
-rw-r--r--clang-tidy/readability/RedundantStringInitCheck.cpp7
-rw-r--r--clang-tidy/readability/RedundantStringInitCheck.h7
-rw-r--r--clang-tidy/readability/SimplifyBooleanExprCheck.cpp29
-rw-r--r--clang-tidy/readability/SimplifyBooleanExprCheck.h8
-rw-r--r--clang-tidy/readability/SimplifySubscriptExprCheck.cpp7
-rw-r--r--clang-tidy/readability/SimplifySubscriptExprCheck.h7
-rw-r--r--clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp7
-rw-r--r--clang-tidy/readability/StaticAccessedThroughInstanceCheck.h7
-rw-r--r--clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.cpp7
-rw-r--r--clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h7
-rw-r--r--clang-tidy/readability/StringCompareCheck.cpp7
-rw-r--r--clang-tidy/readability/StringCompareCheck.h7
-rw-r--r--clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp7
-rw-r--r--clang-tidy/readability/UniqueptrDeleteReleaseCheck.h7
-rw-r--r--clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp13
-rw-r--r--clang-tidy/readability/UppercaseLiteralSuffixCheck.h8
-rwxr-xr-xclang-tidy/rename_check.py7
-rw-r--r--clang-tidy/tool/ClangTidyMain.cpp7
-rwxr-xr-xclang-tidy/tool/clang-tidy-diff.py12
-rwxr-xr-xclang-tidy/tool/run-clang-tidy.py7
-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.cpp154
-rw-r--r--clang-tidy/utils/ExceptionAnalyzer.h48
-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.cpp7
-rw-r--r--clang-tidy/utils/HeaderGuard.h7
-rw-r--r--clang-tidy/utils/IncludeInserter.cpp7
-rw-r--r--clang-tidy/utils/IncludeInserter.h7
-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.cpp7
-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.h7
-rw-r--r--clang-tidy/zircon/ZirconTidyModule.cpp7
-rw-r--r--clangd/AST.cpp27
-rw-r--r--clangd/AST.h9
-rw-r--r--clangd/CMakeLists.txt21
-rw-r--r--clangd/Cancellation.cpp7
-rw-r--r--clangd/Cancellation.h7
-rw-r--r--clangd/ClangdLSPServer.cpp401
-rw-r--r--clangd/ClangdLSPServer.h29
-rw-r--r--clangd/ClangdServer.cpp224
-rw-r--r--clangd/ClangdServer.h47
-rw-r--r--clangd/ClangdUnit.cpp180
-rw-r--r--clangd/ClangdUnit.h39
-rw-r--r--clangd/CodeComplete.cpp336
-rw-r--r--clangd/CodeComplete.h7
-rw-r--r--clangd/CodeCompletionStrings.cpp27
-rw-r--r--clangd/CodeCompletionStrings.h7
-rw-r--r--clangd/Compiler.cpp54
-rw-r--r--clangd/Compiler.h30
-rw-r--r--clangd/Context.cpp7
-rw-r--r--clangd/Context.h7
-rw-r--r--clangd/Diagnostics.cpp55
-rw-r--r--clangd/Diagnostics.h13
-rw-r--r--clangd/DraftStore.cpp39
-rw-r--r--clangd/DraftStore.h7
-rw-r--r--clangd/ExpectedTypes.cpp18
-rw-r--r--clangd/ExpectedTypes.h7
-rw-r--r--clangd/FS.cpp51
-rw-r--r--clangd/FS.h7
-rw-r--r--clangd/FSProvider.cpp36
-rw-r--r--clangd/FSProvider.h7
-rw-r--r--clangd/Features.inc.in1
-rw-r--r--clangd/FileDistance.cpp78
-rw-r--r--clangd/FileDistance.h13
-rw-r--r--clangd/FindSymbols.cpp18
-rw-r--r--clangd/FindSymbols.h7
-rw-r--r--clangd/Function.h8
-rw-r--r--clangd/FuzzyMatch.cpp53
-rw-r--r--clangd/FuzzyMatch.h7
-rw-r--r--clangd/GlobalCompilationDatabase.cpp77
-rw-r--r--clangd/GlobalCompilationDatabase.h12
-rw-r--r--clangd/Headers.cpp74
-rw-r--r--clangd/Headers.h18
-rw-r--r--clangd/IncludeFixer.cpp304
-rw-r--r--clangd/IncludeFixer.h87
-rw-r--r--clangd/JSONTransport.cpp125
-rw-r--r--clangd/Logger.cpp21
-rw-r--r--clangd/Logger.h7
-rw-r--r--clangd/Path.h7
-rw-r--r--clangd/Protocol.cpp406
-rw-r--r--clangd/Protocol.h66
-rw-r--r--clangd/Quality.cpp116
-rw-r--r--clangd/Quality.h7
-rw-r--r--clangd/RIFF.cpp28
-rw-r--r--clangd/RIFF.h7
-rw-r--r--clangd/Selection.cpp301
-rw-r--r--clangd/Selection.h123
-rw-r--r--clangd/SourceCode.cpp229
-rw-r--r--clangd/SourceCode.h78
-rw-r--r--clangd/TUScheduler.cpp146
-rw-r--r--clangd/TUScheduler.h28
-rw-r--r--clangd/Threading.cpp11
-rw-r--r--clangd/Threading.h7
-rw-r--r--clangd/Trace.cpp104
-rw-r--r--clangd/Trace.h7
-rw-r--r--clangd/Transport.h13
-rw-r--r--clangd/URI.cpp98
-rw-r--r--clangd/URI.h7
-rw-r--r--clangd/XRefs.cpp333
-rw-r--r--clangd/XRefs.h29
-rw-r--r--clangd/benchmarks/IndexBenchmark.cpp25
-rw-r--r--clangd/clients/clangd-vscode/.gitignore1
-rw-r--r--clangd/clients/clangd-vscode/LICENSE2
-rw-r--r--clangd/clients/clangd-vscode/package-lock.json2027
-rw-r--r--clangd/clients/clangd-vscode/package.json20
-rw-r--r--clangd/clients/clangd-vscode/src/extension.ts49
-rw-r--r--clangd/fuzzer/ClangdFuzzer.cpp15
-rw-r--r--clangd/index/Background.cpp383
-rw-r--r--clangd/index/Background.h44
-rw-r--r--clangd/index/BackgroundIndexStorage.cpp7
-rw-r--r--clangd/index/CanonicalIncludes.cpp39
-rw-r--r--clangd/index/CanonicalIncludes.h7
-rw-r--r--clangd/index/FileIndex.cpp49
-rw-r--r--clangd/index/FileIndex.h15
-rw-r--r--clangd/index/Index.cpp62
-rw-r--r--clangd/index/Index.h29
-rw-r--r--clangd/index/IndexAction.cpp13
-rw-r--r--clangd/index/IndexAction.h7
-rw-r--r--clangd/index/MemIndex.cpp28
-rw-r--r--clangd/index/MemIndex.h7
-rw-r--r--clangd/index/Merge.cpp67
-rw-r--r--clangd/index/Merge.h7
-rw-r--r--clangd/index/Serialization.cpp149
-rw-r--r--clangd/index/Serialization.h7
-rw-r--r--clangd/index/SymbolCollector.cpp195
-rw-r--r--clangd/index/SymbolCollector.h19
-rw-r--r--clangd/index/SymbolID.cpp38
-rw-r--r--clangd/index/SymbolID.h7
-rw-r--r--clangd/index/YAMLSerialization.cpp51
-rw-r--r--clangd/index/dex/Dex.cpp136
-rw-r--r--clangd/index/dex/Dex.h11
-rw-r--r--clangd/index/dex/Iterator.cpp24
-rw-r--r--clangd/index/dex/Iterator.h7
-rw-r--r--clangd/index/dex/PostingList.cpp36
-rw-r--r--clangd/index/dex/PostingList.h7
-rw-r--r--clangd/index/dex/Token.h14
-rw-r--r--clangd/index/dex/Trigram.cpp20
-rw-r--r--clangd/index/dex/Trigram.h7
-rw-r--r--clangd/index/dex/dexp/Dexp.cpp168
-rw-r--r--clangd/indexer/IndexerMain.cpp34
-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/tool/CMakeLists.txt10
-rw-r--r--clangd/tool/ClangdMain.cpp387
-rw-r--r--clangd/xpc/CMakeLists.txt29
-rw-r--r--clangd/xpc/Conversion.cpp39
-rw-r--r--clangd/xpc/Conversion.h24
-rw-r--r--clangd/xpc/README.txt6
-rw-r--r--clangd/xpc/XPCTransport.cpp216
-rw-r--r--clangd/xpc/cmake/Info.plist.in28
-rw-r--r--clangd/xpc/cmake/XPCServiceInfo.plist.in30
-rw-r--r--clangd/xpc/cmake/modules/CreateClangdXPCFramework.cmake73
-rw-r--r--clangd/xpc/framework/CMakeLists.txt9
-rw-r--r--clangd/xpc/framework/ClangdXPC.cpp5
-rw-r--r--clangd/xpc/test-client/CMakeLists.txt26
-rw-r--r--clangd/xpc/test-client/ClangdXPCTestClient.cpp96
-rw-r--r--docs/ReleaseNotes.rst204
-rw-r--r--docs/clang-doc.rst4
-rw-r--r--docs/clang-rename.rst10
-rw-r--r--docs/clang-tidy.rst2
-rw-r--r--docs/clang-tidy/Contributing.rst512
-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-unnecessary-conversion.rst31
-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/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.rst12
-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/misc-non-private-member-variables-in-classes.rst10
-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-nodiscard.rst82
-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-identifier-naming.rst1921
-rw-r--r--docs/clang-tidy/checks/readability-magic-numbers.rst2
-rw-r--r--docs/clang-tidy/checks/readability-redundant-preprocessor.rst61
-rw-r--r--docs/clang-tidy/checks/readability-uppercase-literal-suffix.rst5
-rw-r--r--docs/clang-tidy/index.rst572
-rw-r--r--docs/clangd.rst29
-rw-r--r--docs/conf.py4
-rw-r--r--docs/include-fixer.rst2
-rw-r--r--docs/modularize.rst8
-rw-r--r--docs/pp-trace.rst130
-rw-r--r--include-fixer/FuzzySymbolIndex.cpp7
-rw-r--r--include-fixer/FuzzySymbolIndex.h7
-rw-r--r--include-fixer/InMemorySymbolIndex.cpp7
-rw-r--r--include-fixer/InMemorySymbolIndex.h7
-rw-r--r--include-fixer/IncludeFixer.cpp7
-rw-r--r--include-fixer/IncludeFixer.h7
-rw-r--r--include-fixer/IncludeFixerContext.cpp7
-rw-r--r--include-fixer/IncludeFixerContext.h7
-rw-r--r--include-fixer/SymbolIndex.h7
-rw-r--r--include-fixer/SymbolIndexManager.cpp7
-rw-r--r--include-fixer/SymbolIndexManager.h7
-rw-r--r--include-fixer/YamlSymbolIndex.cpp7
-rw-r--r--include-fixer/YamlSymbolIndex.h7
-rw-r--r--include-fixer/find-all-symbols/FindAllMacros.cpp7
-rw-r--r--include-fixer/find-all-symbols/FindAllMacros.h7
-rw-r--r--include-fixer/find-all-symbols/FindAllSymbols.cpp7
-rw-r--r--include-fixer/find-all-symbols/FindAllSymbols.h7
-rw-r--r--include-fixer/find-all-symbols/FindAllSymbolsAction.cpp7
-rw-r--r--include-fixer/find-all-symbols/FindAllSymbolsAction.h7
-rw-r--r--include-fixer/find-all-symbols/HeaderMapCollector.cpp7
-rw-r--r--include-fixer/find-all-symbols/HeaderMapCollector.h7
-rw-r--r--include-fixer/find-all-symbols/PathConfig.cpp7
-rw-r--r--include-fixer/find-all-symbols/PathConfig.h7
-rw-r--r--include-fixer/find-all-symbols/PragmaCommentHandler.cpp7
-rw-r--r--include-fixer/find-all-symbols/PragmaCommentHandler.h7
-rw-r--r--include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp7
-rw-r--r--include-fixer/find-all-symbols/STLPostfixHeaderMap.h7
-rw-r--r--include-fixer/find-all-symbols/SymbolInfo.cpp7
-rw-r--r--include-fixer/find-all-symbols/SymbolInfo.h7
-rw-r--r--include-fixer/find-all-symbols/SymbolReporter.h7
-rw-r--r--include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp7
-rwxr-xr-xinclude-fixer/find-all-symbols/tool/run-find-all-symbols.py7
-rw-r--r--include-fixer/plugin/IncludeFixerPlugin.cpp7
-rw-r--r--include-fixer/tool/ClangIncludeFixer.cpp7
-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.cpp7
-rw-r--r--pp-trace/PPCallbacksTracker.h7
-rw-r--r--pp-trace/PPTrace.cpp7
-rw-r--r--test/CMakeLists.txt9
-rw-r--r--test/clang-tidy/Inputs/absl/time/time.h15
-rw-r--r--test/clang-tidy/Inputs/mock-libcxx/bin/clang1
-rw-r--r--test/clang-tidy/abseil-duration-addition.cpp98
-rw-r--r--test/clang-tidy/abseil-duration-comparison.cpp27
-rw-r--r--test/clang-tidy/abseil-duration-conversion-cast.cpp95
-rw-r--r--test/clang-tidy/abseil-duration-factory-scale.cpp14
-rw-r--r--test/clang-tidy/abseil-duration-unnecessary-conversion.cpp69
-rw-r--r--test/clang-tidy/abseil-upgrade-duration-conversions.cpp33
-rw-r--r--test/clang-tidy/bugprone-argument-comment-literals.cpp124
-rw-r--r--test/clang-tidy/bugprone-string-constructor.cpp11
-rw-r--r--test/clang-tidy/bugprone-use-after-move.cpp13
-rwxr-xr-xtest/clang-tidy/check_clang_tidy.py7
-rw-r--r--test/clang-tidy/fuchsia-overloaded-operator.cpp2
-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-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-nodiscard-clang-unused.cpp25
-rw-r--r--test/clang-tidy/modernize-use-nodiscard-cxx11.cpp24
-rw-r--r--test/clang-tidy/modernize-use-nodiscard-gcc-unused.cpp25
-rw-r--r--test/clang-tidy/modernize-use-nodiscard-no-macro-inscope-cxx11.cpp13
-rw-r--r--test/clang-tidy/modernize-use-nodiscard-no-macro.cpp22
-rw-r--r--test/clang-tidy/modernize-use-nodiscard.cpp262
-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-redundant-preprocessor-ifdef.cpp36
-rw-r--r--test/clang-tidy/readability-redundant-preprocessor.cpp84
-rw-r--r--test/clang-tidy/readability-redundant-preprocessor.h5
-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/readability-uppercase-literal-suffix-integer-macro.cpp4
-rw-r--r--test/clang-tidy/readability-uppercase-literal-suffix-integer.cpp4
-rw-r--r--test/clang-tidy/static-analyzer-config.cpp2
-rw-r--r--test/clangd/Inputs/background-index/definition.jsonrpc2
-rw-r--r--test/clangd/background-index.test3
-rw-r--r--test/clangd/completion-auto-trigger.test106
-rw-r--r--test/clangd/diagnostic-category.test2
-rw-r--r--test/clangd/diagnostics.test2
-rw-r--r--test/clangd/did-change-configuration-params.test2
-rw-r--r--test/clangd/execute-command.test2
-rw-r--r--test/clangd/filestatus.test13
-rw-r--r--test/clangd/fixits-codeaction.test8
-rw-r--r--test/clangd/fixits-command.test6
-rw-r--r--test/clangd/fixits-embed-in-diagnostic.test2
-rw-r--r--test/clangd/initialize-params.test4
-rw-r--r--test/clangd/tweaks-format.test50
-rw-r--r--test/clangd/xpc/initialize.test10
-rw-r--r--test/clangd/xrefs.test49
-rw-r--r--test/lit.cfg8
-rw-r--r--test/lit.site.cfg.in1
-rw-r--r--test/modularize/ProblemsInconsistent.modularize10
-rw-r--r--test/pp-trace/pp-trace-conditional.cpp48
-rw-r--r--test/pp-trace/pp-trace-macro.cpp4
-rw-r--r--tool-template/ToolTemplate.cpp7
-rw-r--r--unittests/change-namespace/ChangeNamespaceTests.cpp7
-rw-r--r--unittests/clang-apply-replacements/ApplyReplacementsTest.cpp7
-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-move/ClangMoveTests.cpp7
-rw-r--r--unittests/clang-query/QueryEngineTest.cpp7
-rw-r--r--unittests/clang-query/QueryParserTest.cpp7
-rw-r--r--unittests/clang-tidy/ClangTidyTest.h7
-rw-r--r--unittests/clang-tidy/IncludeInserterTest.cpp7
-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.cpp28
-rw-r--r--unittests/clangd/Annotations.h7
-rw-r--r--unittests/clangd/BackgroundIndexTests.cpp179
-rw-r--r--unittests/clangd/CMakeLists.txt10
-rw-r--r--unittests/clangd/CancellationTests.cpp3
-rw-r--r--unittests/clangd/ClangdTests.cpp104
-rw-r--r--unittests/clangd/ClangdUnitTests.cpp262
-rw-r--r--unittests/clangd/CodeCompleteTests.cpp219
-rw-r--r--unittests/clangd/CodeCompletionStringsTests.cpp7
-rw-r--r--unittests/clangd/ContextTests.cpp7
-rw-r--r--unittests/clangd/DexTests.cpp79
-rw-r--r--unittests/clangd/DiagnosticsTests.cpp455
-rw-r--r--unittests/clangd/DraftStoreTests.cpp36
-rw-r--r--unittests/clangd/ExpectedTypeTest.cpp25
-rw-r--r--unittests/clangd/FSTests.cpp17
-rw-r--r--unittests/clangd/FileDistanceTests.cpp7
-rw-r--r--unittests/clangd/FileIndexTests.cpp96
-rw-r--r--unittests/clangd/FindSymbolsTests.cpp44
-rw-r--r--unittests/clangd/FunctionTests.cpp8
-rw-r--r--unittests/clangd/FuzzyMatchTests.cpp67
-rw-r--r--unittests/clangd/GlobalCompilationDatabaseTests.cpp33
-rw-r--r--unittests/clangd/HeadersTests.cpp18
-rw-r--r--unittests/clangd/IndexActionTests.cpp11
-rw-r--r--unittests/clangd/IndexTests.cpp38
-rw-r--r--unittests/clangd/JSONTransportTests.cpp36
-rw-r--r--unittests/clangd/Matchers.h7
-rw-r--r--unittests/clangd/QualityTests.cpp29
-rw-r--r--unittests/clangd/RIFFTests.cpp18
-rw-r--r--unittests/clangd/SelectionTests.cpp254
-rw-r--r--unittests/clangd/SerializationTests.cpp27
-rw-r--r--unittests/clangd/SourceCodeTests.cpp106
-rw-r--r--unittests/clangd/SymbolCollectorTests.cpp242
-rw-r--r--unittests/clangd/SymbolInfoTests.cpp251
-rw-r--r--unittests/clangd/SyncAPI.cpp70
-rw-r--r--unittests/clangd/SyncAPI.h11
-rw-r--r--unittests/clangd/TUSchedulerTests.cpp97
-rw-r--r--unittests/clangd/TestFS.cpp82
-rw-r--r--unittests/clangd/TestFS.h7
-rw-r--r--unittests/clangd/TestIndex.cpp71
-rw-r--r--unittests/clangd/TestIndex.h20
-rw-r--r--unittests/clangd/TestTU.cpp31
-rw-r--r--unittests/clangd/TestTU.h11
-rw-r--r--unittests/clangd/ThreadingTests.cpp7
-rw-r--r--unittests/clangd/TraceTests.cpp38
-rw-r--r--unittests/clangd/TweakTests.cpp190
-rw-r--r--unittests/clangd/URITests.cpp18
-rw-r--r--unittests/clangd/XRefsTests.cpp279
-rw-r--r--unittests/clangd/xpc/CMakeLists.txt21
-rw-r--r--unittests/clangd/xpc/ConversionTests.cpp35
-rw-r--r--unittests/include-fixer/FuzzySymbolIndexTests.cpp7
-rw-r--r--unittests/include-fixer/IncludeFixerTest.cpp7
-rw-r--r--unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp7
-rw-r--r--unittests/include/common/VirtualFileHelper.h7
903 files changed, 18546 insertions, 7788 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c3137ade..37e3e87e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,3 +1,8 @@
+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)
diff --git a/LICENSE.TXT b/LICENSE.TXT
index b886535d..24806ab4 100644
--- a/LICENSE.TXT
+++ b/LICENSE.TXT
@@ -1,10 +1,245 @@
==============================================================================
-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
-Copyright (c) 2007-2018 University of Illinois at Urbana-Champaign.
+Copyright (c) 2007-2019 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:
@@ -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/change-namespace/ChangeNamespace.cpp b/change-namespace/ChangeNamespace.cpp
index 7a710318..eb732639 100644
--- a/change-namespace/ChangeNamespace.cpp
+++ b/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/change-namespace/ChangeNamespace.h
index cfe3cbc7..293d5ce8 100644
--- a/change-namespace/ChangeNamespace.h
+++ b/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/ClangChangeNamespace.cpp b/change-namespace/tool/ClangChangeNamespace.cpp
index 180e8c38..0d515029 100644
--- a/change-namespace/tool/ClangChangeNamespace.cpp
+++ b/change-namespace/tool/ClangChangeNamespace.cpp
@@ -1,9 +1,8 @@
//===-- ClangIncludeFixer.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-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..7a656a66 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
//
//===----------------------------------------------------------------------===//
///
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/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..e57a2617 100644
--- a/clang-doc/Generators.cpp
+++ b/clang-doc/Generators.cpp
@@ -1,9 +1,8 @@
//===---- Generator.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..897fed56 100644
--- a/clang-doc/Serialize.cpp
+++ b/clang-doc/Serialize.cpp
@@ -1,9 +1,8 @@
//===-- Serializer.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..ceb42153 100644
--- a/clang-doc/YAMLGenerator.cpp
+++ b/clang-doc/YAMLGenerator.cpp
@@ -1,9 +1,8 @@
//===-- ClangDocYAML.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/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/clang-move/ClangMove.cpp b/clang-move/ClangMove.cpp
index ec9db738..9fd3e960 100644
--- a/clang-move/ClangMove.cpp
+++ b/clang-move/ClangMove.cpp
@@ -1,9 +1,8 @@
//===-- ClangMove.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
//
//===----------------------------------------------------------------------===//
@@ -76,10 +75,7 @@ std::string MakeAbsolutePath(StringRef CurrentDir, StringRef Path) {
return "";
llvm::SmallString<128> InitialDirectory(CurrentDir);
llvm::SmallString<128> AbsolutePath(Path);
- if (std::error_code EC =
- llvm::sys::fs::make_absolute(InitialDirectory, AbsolutePath))
- llvm::errs() << "Warning: could not make absolute file: '" << EC.message()
- << '\n';
+ llvm::sys::fs::make_absolute(InitialDirectory, AbsolutePath);
return CleanPath(std::move(AbsolutePath));
}
diff --git a/clang-move/ClangMove.h b/clang-move/ClangMove.h
index 94172181..8dfccf7a 100644
--- a/clang-move/ClangMove.h
+++ b/clang-move/ClangMove.h
@@ -1,9 +1,8 @@
//===-- ClangMove.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/HelperDeclRefGraph.cpp b/clang-move/HelperDeclRefGraph.cpp
index 28200e0b..93a0f879 100644
--- a/clang-move/HelperDeclRefGraph.cpp
+++ b/clang-move/HelperDeclRefGraph.cpp
@@ -1,9 +1,8 @@
//===-- UsedHelperDeclFinder.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
//
//===----------------------------------------------------------------------===//
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/tool/ClangMoveMain.cpp b/clang-move/tool/ClangMoveMain.cpp
index f50e973a..a73dd6e3 100644
--- a/clang-move/tool/ClangMoveMain.cpp
+++ b/clang-move/tool/ClangMoveMain.cpp
@@ -1,9 +1,8 @@
//===-- ClangMoveMain.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
//
//===----------------------------------------------------------------------===//
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 7c12e3ba..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
//
//===----------------------------------------------------------------------===//
@@ -27,29 +26,22 @@ namespace query {
// is found before End, return StringRef(). Begin is adjusted to exclude the
// lexed region.
StringRef QueryParser::lexWord() {
- while (true) {
- if (Begin == End)
- return StringRef(Begin, 0);
-
- if (!isWhitespace(*Begin))
- break;
+ Line = Line.ltrim();
- ++Begin;
- }
+ if (Line.empty())
+ // Even though the Line is empty, it contains a pointer and
+ // a (zero) length. The pointer is used in the LexOrCompleteWord
+ // code completion.
+ return Line;
- if (*Begin == '#') {
- End = Begin;
+ if (Line.front() == '#') {
+ Line = {};
return StringRef();
}
- const char *WordBegin = Begin;
-
- while (true) {
- ++Begin;
-
- if (Begin == End || isWhitespace(*Begin))
- return StringRef(WordBegin, Begin - WordBegin);
- }
+ StringRef Word = Line.take_until(isWhitespace);
+ Line = Line.drop_front(Word.size());
+ return Word;
}
// This is the StringSwitch-alike used by lexOrCompleteWord below. See that
@@ -133,10 +125,9 @@ template <typename QueryType> QueryRef QueryParser::parseSetOutputKind() {
}
QueryRef QueryParser::endQuery(QueryRef Q) {
- const char *Extra = Begin;
+ const StringRef Extra = Line;
if (!lexWord().empty())
- return new InvalidQuery("unexpected extra input: '" +
- StringRef(Extra, End - Extra) + "'");
+ return new InvalidQuery("unexpected extra input: '" + Extra + "'");
return Q;
}
@@ -174,8 +165,7 @@ QueryRef makeInvalidQueryFromDiagnostics(const Diagnostics &Diag) {
QueryRef QueryParser::completeMatcherExpression() {
std::vector<MatcherCompletion> Comps = Parser::completeExpression(
- StringRef(Begin, End - Begin), CompletionPos - Begin, nullptr,
- &QS.NamedValues);
+ Line, CompletionPos - Line.begin(), nullptr, &QS.NamedValues);
for (auto I = Comps.begin(), E = Comps.end(); I != E; ++I) {
Completions.push_back(LineEditor::Completion(I->TypedText, I->MatcherDecl));
}
@@ -222,8 +212,8 @@ QueryRef QueryParser::doParse() {
Diagnostics Diag;
ast_matchers::dynamic::VariantValue Value;
- if (!Parser::parseExpression(StringRef(Begin, End - Begin), nullptr,
- &QS.NamedValues, &Value, &Diag)) {
+ if (!Parser::parseExpression(Line, nullptr, &QS.NamedValues, &Value,
+ &Diag)) {
return makeInvalidQueryFromDiagnostics(Diag);
}
@@ -235,7 +225,7 @@ QueryRef QueryParser::doParse() {
return completeMatcherExpression();
Diagnostics Diag;
- auto MatcherSource = StringRef(Begin, End - Begin).trim();
+ auto MatcherSource = Line.trim();
Optional<DynTypedMatcher> Matcher = Parser::parseMatcherExpression(
MatcherSource, nullptr, &QS.NamedValues, &Diag);
if (!Matcher) {
diff --git a/clang-query/QueryParser.h b/clang-query/QueryParser.h
index 6730f990..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
//
//===----------------------------------------------------------------------===//
@@ -37,7 +36,7 @@ public:
private:
QueryParser(StringRef Line, const QuerySession &QS)
- : Begin(Line.begin()), End(Line.end()), CompletionPos(nullptr), QS(QS) {}
+ : Line(Line), CompletionPos(nullptr), QS(QS) {}
StringRef lexWord();
@@ -55,8 +54,7 @@ private:
/// \c InvalidQuery if a parse error occurs.
QueryRef doParse();
- const char *Begin;
- const char *End;
+ StringRef Line;
const char *CompletionPos;
std::vector<llvm::LineEditor::Completion> Completions;
diff --git a/clang-query/QuerySession.h b/clang-query/QuerySession.h
index 62ecb545..0f3bc1aa 100644
--- a/clang-query/QuerySession.h
+++ b/clang-query/QuerySession.h
@@ -1,16 +1,14 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_SESSION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_SESSION_H
-#include "Query.h"
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
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/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/ClangTidy.cpp b/clang-tidy/ClangTidy.cpp
index 0feda605..6534fd44 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
//
//===----------------------------------------------------------------------===//
///
@@ -529,24 +528,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);
diff --git a/clang-tidy/ClangTidy.h b/clang-tidy/ClangTidy.h
index dc11200d..29857320 100644
--- a/clang-tidy/ClangTidy.h
+++ b/clang-tidy/ClangTidy.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index 6e2385bb..637addf2 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
//
//===----------------------------------------------------------------------===//
///
@@ -319,7 +318,7 @@ static bool IsNOLINTFound(StringRef NolintDirectiveText, StringRef Line,
return true;
}
-static bool LineIsMarkedWithNOLINT(SourceManager &SM, SourceLocation Loc,
+static bool LineIsMarkedWithNOLINT(const SourceManager &SM, SourceLocation Loc,
unsigned DiagID,
const ClangTidyContext &Context) {
bool Invalid;
@@ -365,8 +364,8 @@ static bool LineIsMarkedWithNOLINT(SourceManager &SM, SourceLocation Loc,
return false;
}
-static bool LineIsMarkedWithNOLINTinMacro(SourceManager &SM, SourceLocation Loc,
- unsigned DiagID,
+static bool LineIsMarkedWithNOLINTinMacro(const SourceManager &SM,
+ SourceLocation Loc, unsigned DiagID,
const ClangTidyContext &Context) {
while (true) {
if (LineIsMarkedWithNOLINT(SM, Loc, DiagID, Context))
diff --git a/clang-tidy/ClangTidyDiagnosticConsumer.h b/clang-tidy/ClangTidyDiagnosticConsumer.h
index a868203f..63dbd526 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/ClangTidyForceLinker.h b/clang-tidy/ClangTidyForceLinker.h
index 2e8e8a83..966aeb28 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
//
//===----------------------------------------------------------------------===//
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/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..1489b48b 100644
--- a/clang-tidy/abseil/AbseilTidyModule.cpp
+++ b/clang-tidy/abseil/AbseilTidyModule.cpp
@@ -1,20 +1,22 @@
//===------- 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"
@@ -30,8 +32,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 +46,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>(
diff --git a/clang-tidy/abseil/CMakeLists.txt b/clang-tidy/abseil/CMakeLists.txt
index bf9d9e84..578dd57d 100644
--- a/clang-tidy/abseil/CMakeLists.txt
+++ b/clang-tidy/abseil/CMakeLists.txt
@@ -2,12 +2,15 @@ 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
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 ae368edf..337f2ca0 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
//
//===----------------------------------------------------------------------===//
@@ -35,11 +34,7 @@ void DurationComparisonCheck::registerMatchers(MatchFinder *Finder) {
void DurationComparisonCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Binop = Result.Nodes.getNodeAs<BinaryOperator>("binop");
- // Don't try to replace things inside of macro definitions.
- if (Binop->getExprLoc().isMacroID())
- return;
-
- llvm::Optional<DurationScale> Scale = getScaleForInverse(
+ llvm::Optional<DurationScale> Scale = getScaleForDurationInverse(
Result.Nodes.getNodeAs<FunctionDecl>("function_decl")->getName());
if (!Scale)
return;
@@ -48,19 +43,19 @@ 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.
- llvm::Optional<std::string> LhsReplacement =
+ if (!isNotInMacro(Result, Binop->getLHS()) ||
+ !isNotInMacro(Result, Binop->getRHS()))
+ return;
+ std::string LhsReplacement =
rewriteExprFromNumberToDuration(Result, *Scale, Binop->getLHS());
- llvm::Optional<std::string> RhsReplacement =
+ std::string RhsReplacement =
rewriteExprFromNumberToDuration(Result, *Scale, Binop->getRHS());
- if (!(LhsReplacement && RhsReplacement))
- return;
-
diag(Binop->getBeginLoc(), "perform comparison in the duration domain")
<< FixItHint::CreateReplacement(Binop->getSourceRange(),
- (llvm::Twine(*LhsReplacement) + " " +
+ (llvm::Twine(LhsReplacement) + " " +
Binop->getOpcodeStr() + " " +
- *RhsReplacement)
+ RhsReplacement)
.str());
}
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..f0ae82c0
--- /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 (!isNotInMacro(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 078f88cf..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
//
//===----------------------------------------------------------------------===//
@@ -123,6 +122,10 @@ void DurationFactoryScaleCheck::registerMatchers(MatchFinder *Finder) {
hasArgument(
0,
ignoringImpCasts(anyOf(
+ cxxFunctionalCastExpr(
+ hasDestinationType(
+ anyOf(isInteger(), realFloatingPointType())),
+ hasSourceExpression(initListExpr())),
integerLiteral(equals(0)), floatLiteral(equals(0.0)),
binaryOperator(hasOperatorName("*"),
hasEitherOperand(ignoringImpCasts(
@@ -206,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());
}
@@ -219,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 7a488134..c3e40789 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
//
//===----------------------------------------------------------------------===//
@@ -37,9 +36,8 @@ truncateIfIntegral(const FloatingLiteral &FloatLiteral) {
return llvm::None;
}
-/// Given a `Scale` return the inverse functions for it.
-static const std::pair<llvm::StringRef, llvm::StringRef> &
-getInverseForScale(DurationScale Scale) {
+const std::pair<llvm::StringRef, llvm::StringRef> &
+getDurationInverseForScale(DurationScale Scale) {
static const llvm::IndexedMap<std::pair<llvm::StringRef, llvm::StringRef>,
DurationScale2IndexFunctor>
InverseMap = []() {
@@ -73,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(
@@ -87,7 +85,7 @@ rewriteInverseDurationCall(const MatchFinder::MatchResult &Result,
}
/// 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";
@@ -105,14 +103,49 @@ llvm::StringRef getFactoryForScale(DurationScale Scale) {
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) {
- return selectFirst<const clang::Expr>(
- "val",
- match(expr(ignoringImpCasts(anyOf(integerLiteral(equals(0)),
- floatLiteral(equals(0.0)))))
- .bind("val"),
- Node, *Result.Context)) != nullptr;
+ auto ZeroMatcher =
+ anyOf(integerLiteral(equals(0)), floatLiteral(equals(0.0)));
+
+ // Check to see if we're using a zero directly.
+ if (selectFirst<const clang::Expr>(
+ "val", match(expr(ignoringImpCasts(ZeroMatcher)).bind("val"), Node,
+ *Result.Context)) != nullptr)
+ return true;
+
+ // Now check to see if we're using a functional cast with a scalar
+ // initializer expression, e.g. `int{0}`.
+ if (selectFirst<const clang::Expr>(
+ "val", match(cxxFunctionalCastExpr(
+ hasDestinationType(
+ anyOf(isInteger(), realFloatingPointType())),
+ hasSourceExpression(initListExpr(
+ hasInit(0, ignoringParenImpCasts(ZeroMatcher)))))
+ .bind("val"),
+ Node, *Result.Context)) != nullptr)
+ return true;
+
+ return false;
}
llvm::Optional<std::string>
@@ -161,7 +194,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},
@@ -183,14 +216,27 @@ llvm::Optional<DurationScale> getScaleForInverse(llvm::StringRef Name) {
return ScaleIter->second;
}
-llvm::Optional<std::string> rewriteExprFromNumberToDuration(
+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) {
const Expr &RootNode = *Node->IgnoreParenImpCasts();
- if (RootNode.getBeginLoc().isMacroID())
- return llvm::None;
-
// First check to see if we can undo a complimentary function call.
if (llvm::Optional<std::string> MaybeRewrite =
rewriteInverseDurationCall(Result, Scale, RootNode))
@@ -199,11 +245,28 @@ llvm::Optional<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();
}
+bool isNotInMacro(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();
+}
+
} // namespace abseil
} // namespace tidy
} // namespace clang
diff --git a/clang-tidy/abseil/DurationRewriter.h b/clang-tidy/abseil/DurationRewriter.h
index 97103b64..54a60f60 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,7 @@ 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);
// Determine if `Node` represents a literal floating point or integral zero.
bool IsLiteralZero(const ast_matchers::MatchFinder::MatchResult &Result,
@@ -61,14 +60,32 @@ 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> &
+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`.
-llvm::Optional<std::string> rewriteExprFromNumberToDuration(
+std::string rewriteExprFromNumberToDuration(
const ast_matchers::MatchFinder::MatchResult &Result, DurationScale Scale,
const Expr *Node);
+/// Return `true` 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 isNotInMacro(const ast_matchers::MatchFinder::MatchResult &Result,
+ const Expr *E);
+
AST_MATCHER_FUNCTION(ast_matchers::internal::Matcher<FunctionDecl>,
DurationConversionFunction) {
using namespace clang::ast_matchers;
@@ -89,6 +106,14 @@ 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"));
+}
+
} // namespace abseil
} // namespace tidy
} // namespace clang
diff --git a/clang-tidy/abseil/DurationSubtractionCheck.cpp b/clang-tidy/abseil/DurationSubtractionCheck.cpp
index 8b85bd2c..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,14 +37,13 @@ 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;
- llvm::Optional<std::string> RhsReplacement =
+ std::string RhsReplacement =
rewriteExprFromNumberToDuration(Result, *Scale, Binop->getRHS());
- if (!RhsReplacement)
- return;
const Expr *LhsArg = Result.Nodes.getNodeAs<Expr>("lhs_arg");
@@ -54,7 +52,7 @@ void DurationSubtractionCheck::check(const MatchFinder::MatchResult &Result) {
Binop->getSourceRange(),
(llvm::Twine("absl::") + FuncDecl->getName() + "(" +
tooling::fixit::getText(*LhsArg, *Result.Context) + " - " +
- *RhsReplacement + ")")
+ RhsReplacement + ")")
.str());
}
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..83650cd1
--- /dev/null
+++ b/clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp
@@ -0,0 +1,58 @@
+//===--- 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();
+
+ Finder->addMatcher(
+ callExpr(
+ callee(functionDecl(hasName(DurationFactory))),
+ hasArgument(0, callExpr(callee(functionDecl(hasAnyName(
+ FloatConversion, IntegerConversion))),
+ hasArgument(0, expr().bind("arg")))))
+ .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 (!isNotInMacro(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..9009647a 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/abseil/StringFindStartswithCheck.h b/clang-tidy/abseil/StringFindStartswithCheck.h
index 1c04e805..68bae50a 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
//
//===----------------------------------------------------------------------===//
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..898392b1 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,10 +60,9 @@ 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
//
//===----------------------------------------------------------------------===//
@@ -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
//
//===----------------------------------------------------------------------===//
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..da6c6692 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
//
//===----------------------------------------------------------------------===//
///
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..53e8b8e7 100644
--- a/clang-tidy/android/ComparisonInTempFailureRetryCheck.h
+++ b/clang-tidy/android/ComparisonInTempFailureRetryCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..e1666153 100644
--- a/clang-tidy/boost/UseToStringCheck.h
+++ b/clang-tidy/boost/UseToStringCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..451b309c 100644
--- a/clang-tidy/bugprone/ArgumentCommentCheck.h
+++ b/clang-tidy/bugprone/ArgumentCommentCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
@@ -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..ffc8000d 100644
--- a/clang-tidy/bugprone/AssertSideEffectCheck.h
+++ b/clang-tidy/bugprone/AssertSideEffectCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..7ddaab2f 100644
--- a/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.h
+++ b/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..16e4678a 100644
--- a/clang-tidy/bugprone/CopyConstructorInitCheck.h
+++ b/clang-tidy/bugprone/CopyConstructorInitCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/DanglingHandleCheck.cpp b/clang-tidy/bugprone/DanglingHandleCheck.cpp
index 81b799ed..9cefc20f 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/DanglingHandleCheck.h b/clang-tidy/bugprone/DanglingHandleCheck.h
index add8d427..801240fa 100644
--- a/clang-tidy/bugprone/DanglingHandleCheck.h
+++ b/clang-tidy/bugprone/DanglingHandleCheck.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/bugprone/ExceptionEscapeCheck.cpp b/clang-tidy/bugprone/ExceptionEscapeCheck.cpp
index 3c8a6c5d..0849e2e7 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,12 @@ 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));
}
void ExceptionEscapeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
@@ -194,22 +59,25 @@ 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.throwsException(MatchedDecl))
+ // 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..4626e425 100644
--- a/clang-tidy/bugprone/ExceptionEscapeCheck.h
+++ b/clang-tidy/bugprone/ExceptionEscapeCheck.h
@@ -1,9 +1,8 @@
-//===--- 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
//
//===----------------------------------------------------------------------===//
@@ -11,7 +10,7 @@
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTION_ESCAPE_H
#include "../ClangTidy.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..dce71ac0 100644
--- a/clang-tidy/bugprone/FoldInitTypeCheck.h
+++ b/clang-tidy/bugprone/FoldInitTypeCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..dfecddc9 100644
--- a/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.h
+++ b/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..7f3a4222 100644
--- a/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.h
+++ b/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/InaccurateEraseCheck.cpp b/clang-tidy/bugprone/InaccurateEraseCheck.cpp
index c1e65b58..b236e992 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/InaccurateEraseCheck.h b/clang-tidy/bugprone/InaccurateEraseCheck.h
index d6b37290..7a8b3aa0 100644
--- a/clang-tidy/bugprone/InaccurateEraseCheck.h
+++ b/clang-tidy/bugprone/InaccurateEraseCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..1c84316d 100644
--- a/clang-tidy/bugprone/IncorrectRoundingsCheck.h
+++ b/clang-tidy/bugprone/IncorrectRoundingsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..20776688 100644
--- a/clang-tidy/bugprone/IntegerDivisionCheck.h
+++ b/clang-tidy/bugprone/IntegerDivisionCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp b/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp
index bdb769dc..bcd1ab8a 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/LambdaFunctionNameCheck.h b/clang-tidy/bugprone/LambdaFunctionNameCheck.h
index b7b1b441..b00df533 100644
--- a/clang-tidy/bugprone/LambdaFunctionNameCheck.h
+++ b/clang-tidy/bugprone/LambdaFunctionNameCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/MacroParenthesesCheck.cpp b/clang-tidy/bugprone/MacroParenthesesCheck.cpp
index 6846bc2f..2bebf4ad 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/MacroParenthesesCheck.h b/clang-tidy/bugprone/MacroParenthesesCheck.h
index 383a6cce..4b9e1819 100644
--- a/clang-tidy/bugprone/MacroParenthesesCheck.h
+++ b/clang-tidy/bugprone/MacroParenthesesCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.cpp b/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.cpp
index 30c770e3..91ec0944 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.h b/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.h
index a2a31341..6917c5b2 100644
--- a/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.h
+++ b/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..aede5ff9 100644
--- a/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h
+++ b/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..ccf4cf75 100644
--- a/clang-tidy/bugprone/MisplacedWideningCastCheck.h
+++ b/clang-tidy/bugprone/MisplacedWideningCastCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..2565dcda 100644
--- a/clang-tidy/bugprone/MoveForwardingReferenceCheck.h
+++ b/clang-tidy/bugprone/MoveForwardingReferenceCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..0fd91eb3 100644
--- a/clang-tidy/bugprone/MultipleStatementMacroCheck.h
+++ b/clang-tidy/bugprone/MultipleStatementMacroCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/ParentVirtualCallCheck.cpp b/clang-tidy/bugprone/ParentVirtualCallCheck.cpp
index 919a6910..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
//
//===----------------------------------------------------------------------===//
@@ -50,9 +49,7 @@ static BasesVector getParentsByGrandParent(const CXXRecordDecl &GrandParent,
// TypePtr is the nearest base class to ThisClass between ThisClass and
// GrandParent, where MemberDecl is overridden. TypePtr is the class the
// check proposes to fix to.
- const Type *TypePtr =
- ActualMemberDecl->getThisType(ActualMemberDecl->getASTContext())
- .getTypePtr();
+ const Type *TypePtr = ActualMemberDecl->getThisType().getTypePtr();
const CXXRecordDecl *RecordDeclType = TypePtr->getPointeeCXXRecordDecl();
assert(RecordDeclType && "TypePtr is not a pointer to CXXRecordDecl!");
if (RecordDeclType->getCanonicalDecl()->isDerivedFrom(&GrandParent))
diff --git a/clang-tidy/bugprone/ParentVirtualCallCheck.h b/clang-tidy/bugprone/ParentVirtualCallCheck.h
index 08c3aefb..a1753cde 100755
--- a/clang-tidy/bugprone/ParentVirtualCallCheck.h
+++ b/clang-tidy/bugprone/ParentVirtualCallCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..e358279f 100644
--- a/clang-tidy/bugprone/SizeofContainerCheck.h
+++ b/clang-tidy/bugprone/SizeofContainerCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/SizeofExpressionCheck.cpp b/clang-tidy/bugprone/SizeofExpressionCheck.cpp
index d662657a..959e0ae3 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/SizeofExpressionCheck.h b/clang-tidy/bugprone/SizeofExpressionCheck.h
index 8e14c315..b06551a4 100644
--- a/clang-tidy/bugprone/SizeofExpressionCheck.h
+++ b/clang-tidy/bugprone/SizeofExpressionCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/StringConstructorCheck.cpp b/clang-tidy/bugprone/StringConstructorCheck.cpp
index d8882306..3a4e75bc 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
//
//===----------------------------------------------------------------------===//
@@ -100,6 +99,15 @@ void StringConstructorCheck::registerMatchers(MatchFinder *Finder) {
integerLiteral().bind("int"))))))
.bind("constructor"),
this);
+
+ // Check the literal string constructor with char pointer.
+ // [i.e. string (const char* s);]
+ Finder->addMatcher(
+ cxxConstructExpr(hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
+ hasArgument(0, expr().bind("from-ptr")),
+ hasArgument(1, unless(hasType(isInteger()))))
+ .bind("constructor"),
+ this);
}
void StringConstructorCheck::check(const MatchFinder::MatchResult &Result) {
@@ -128,6 +136,13 @@ void StringConstructorCheck::check(const MatchFinder::MatchResult &Result) {
if (Lit->getValue().ugt(Str->getLength())) {
diag(Loc, "length is bigger then string literal size");
}
+ } else if (const auto *Ptr = Result.Nodes.getNodeAs<Expr>("from-ptr")) {
+ Expr::EvalResult ConstPtr;
+ if (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..22740156 100644
--- a/clang-tidy/bugprone/StringConstructorCheck.h
+++ b/clang-tidy/bugprone/StringConstructorCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp b/clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp
index f49a5709..cce0de9f 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/StringIntegerAssignmentCheck.h b/clang-tidy/bugprone/StringIntegerAssignmentCheck.h
index 42fa53e9..66da587a 100644
--- a/clang-tidy/bugprone/StringIntegerAssignmentCheck.h
+++ b/clang-tidy/bugprone/StringIntegerAssignmentCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..68885106 100644
--- a/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.h
+++ b/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..32c4a0b7 100644
--- a/clang-tidy/bugprone/SuspiciousEnumUsageCheck.h
+++ b/clang-tidy/bugprone/SuspiciousEnumUsageCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..98872e64 100644
--- a/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h
+++ b/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..d1f58a48 100644
--- a/clang-tidy/bugprone/SuspiciousMissingCommaCheck.h
+++ b/clang-tidy/bugprone/SuspiciousMissingCommaCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp b/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp
index f92fc37f..576fba51 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/SuspiciousSemicolonCheck.h b/clang-tidy/bugprone/SuspiciousSemicolonCheck.h
index adfced1a..12829b1a 100644
--- a/clang-tidy/bugprone/SuspiciousSemicolonCheck.h
+++ b/clang-tidy/bugprone/SuspiciousSemicolonCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..409d79bc 100644
--- a/clang-tidy/bugprone/SuspiciousStringCompareCheck.h
+++ b/clang-tidy/bugprone/SuspiciousStringCompareCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..a1e10df6 100644
--- a/clang-tidy/bugprone/SwappedArgumentsCheck.h
+++ b/clang-tidy/bugprone/SwappedArgumentsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..6d589491 100644
--- a/clang-tidy/bugprone/TerminatingContinueCheck.h
+++ b/clang-tidy/bugprone/TerminatingContinueCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..76b4dc15 100644
--- a/clang-tidy/bugprone/ThrowKeywordMissingCheck.h
+++ b/clang-tidy/bugprone/ThrowKeywordMissingCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp b/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
index 59cc185e..395885e9 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/TooSmallLoopVariableCheck.h b/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
index 0819fcf1..54589ac5 100644
--- a/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
+++ b/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..01903df4 100644
--- a/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h
+++ b/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..9eda29c7 100644
--- a/clang-tidy/bugprone/UndelegatedConstructorCheck.h
+++ b/clang-tidy/bugprone/UndelegatedConstructorCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..7a4a6efa 100644
--- a/clang-tidy/bugprone/UnusedRaiiCheck.h
+++ b/clang-tidy/bugprone/UnusedRaiiCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..35678edd 100644
--- a/clang-tidy/bugprone/UnusedReturnValueCheck.h
+++ b/clang-tidy/bugprone/UnusedReturnValueCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/bugprone/UseAfterMoveCheck.cpp b/clang-tidy/bugprone/UseAfterMoveCheck.cpp
index 11799ebf..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
//
//===----------------------------------------------------------------------===//
@@ -207,7 +206,7 @@ void UseAfterMoveFinder::getUsesAndReinits(
}
bool isStandardSmartPointer(const ValueDecl *VD) {
- const Type *TheType = VD->getType().getTypePtrOrNull();
+ const Type *TheType = VD->getType().getNonReferenceType().getTypePtrOrNull();
if (!TheType)
return false;
diff --git a/clang-tidy/bugprone/UseAfterMoveCheck.h b/clang-tidy/bugprone/UseAfterMoveCheck.h
index f6dea68d..c0984b45 100644
--- a/clang-tidy/bugprone/UseAfterMoveCheck.h
+++ b/clang-tidy/bugprone/UseAfterMoveCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..38314ee0 100644
--- a/clang-tidy/bugprone/VirtualNearMissCheck.h
+++ b/clang-tidy/bugprone/VirtualNearMissCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..cfc2f373 100644
--- a/clang-tidy/cert/CommandProcessorCheck.cpp
+++ b/clang-tidy/cert/CommandProcessorCheck.cpp
@@ -1,9 +1,8 @@
//===--- Env33CCheck.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..1f172e45 100644
--- a/clang-tidy/cert/CommandProcessorCheck.h
+++ b/clang-tidy/cert/CommandProcessorCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..06de157f 100644
--- a/clang-tidy/cert/DontModifyStdNamespaceCheck.h
+++ b/clang-tidy/cert/DontModifyStdNamespaceCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..7752c6e7 100644
--- a/clang-tidy/cert/FloatLoopCounter.h
+++ b/clang-tidy/cert/FloatLoopCounter.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..b88145e5 100644
--- a/clang-tidy/cert/LimitedRandomnessCheck.h
+++ b/clang-tidy/cert/LimitedRandomnessCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..6b7eda2b 100644
--- a/clang-tidy/cert/PostfixOperatorCheck.h
+++ b/clang-tidy/cert/PostfixOperatorCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..4fbca8fd 100644
--- a/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h
+++ b/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cert/SetLongJmpCheck.cpp b/clang-tidy/cert/SetLongJmpCheck.cpp
index 89ba5e77..6b418d49 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cert/SetLongJmpCheck.h b/clang-tidy/cert/SetLongJmpCheck.h
index 1d6c0981..ea20ba7f 100644
--- a/clang-tidy/cert/SetLongJmpCheck.h
+++ b/clang-tidy/cert/SetLongJmpCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..6b59b859 100644
--- a/clang-tidy/cert/StaticObjectExceptionCheck.h
+++ b/clang-tidy/cert/StaticObjectExceptionCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cert/StrToNumCheck.cpp b/clang-tidy/cert/StrToNumCheck.cpp
index 0b3ea43b..38e2dc00 100644
--- a/clang-tidy/cert/StrToNumCheck.cpp
+++ b/clang-tidy/cert/StrToNumCheck.cpp
@@ -1,9 +1,8 @@
//===--- Err34CCheck.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..423a9059 100644
--- a/clang-tidy/cert/StrToNumCheck.h
+++ b/clang-tidy/cert/StrToNumCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..042b98c1 100644
--- a/clang-tidy/cert/ThrownExceptionTypeCheck.h
+++ b/clang-tidy/cert/ThrownExceptionTypeCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cert/VariadicFunctionDefCheck.cpp b/clang-tidy/cert/VariadicFunctionDefCheck.cpp
index ea6112a6..4fe6b7af 100644
--- a/clang-tidy/cert/VariadicFunctionDefCheck.cpp
+++ b/clang-tidy/cert/VariadicFunctionDefCheck.cpp
@@ -1,9 +1,8 @@
//===--- 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..7f8d479d 100644
--- a/clang-tidy/cert/VariadicFunctionDefCheck.h
+++ b/clang-tidy/cert/VariadicFunctionDefCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..fdf2880b 100644
--- a/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
+++ b/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
@@ -1,9 +1,8 @@
//===--- CppCoreGuidelinesModule.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.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..07351b86 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/MacroUsageCheck.h b/clang-tidy/cppcoreguidelines/MacroUsageCheck.h
index a39d55a2..fc96e338 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
//
//===----------------------------------------------------------------------===//
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..32e3fb54 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h b/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.h
index 28b24a6b..c056926c 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
//
//===----------------------------------------------------------------------===//
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..b31145ca 100644
--- a/clang-tidy/fuchsia/DefaultArgumentsCheck.h
+++ b/clang-tidy/fuchsia/DefaultArgumentsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..02d4cff6 100644
--- a/clang-tidy/fuchsia/MultipleInheritanceCheck.h
+++ b/clang-tidy/fuchsia/MultipleInheritanceCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/fuchsia/OverloadedOperatorCheck.cpp b/clang-tidy/fuchsia/OverloadedOperatorCheck.cpp
index 8e6c74f3..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
//
//===----------------------------------------------------------------------===//
@@ -21,6 +20,8 @@ AST_MATCHER(FunctionDecl, isFuchsiaOverloadedOperator) {
if (CXXMethodNode->isCopyAssignmentOperator() ||
CXXMethodNode->isMoveAssignmentOperator())
return false;
+ if (CXXMethodNode->getParent()->isLambda())
+ return false;
}
return Node.isOverloadedOperator();
}
diff --git a/clang-tidy/fuchsia/OverloadedOperatorCheck.h b/clang-tidy/fuchsia/OverloadedOperatorCheck.h
index a22e5ae5..6d99e8bf 100644
--- a/clang-tidy/fuchsia/OverloadedOperatorCheck.h
+++ b/clang-tidy/fuchsia/OverloadedOperatorCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/fuchsia/RestrictSystemIncludesCheck.cpp b/clang-tidy/fuchsia/RestrictSystemIncludesCheck.cpp
index 4817e904..e42e32cd 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h b/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h
index d4e5ac1e..64da2e76 100644
--- a/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h
+++ b/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..5e16d0ae 100644
--- a/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.h
+++ b/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..181d1422 100644
--- a/clang-tidy/fuchsia/TrailingReturnCheck.h
+++ b/clang-tidy/fuchsia/TrailingReturnCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..8e39d816 100644
--- a/clang-tidy/fuchsia/VirtualInheritanceCheck.h
+++ b/clang-tidy/fuchsia/VirtualInheritanceCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..0f6ec2e0 100644
--- a/clang-tidy/google/AvoidCStyleCastsCheck.h
+++ b/clang-tidy/google/AvoidCStyleCastsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..bc50bc27 100644
--- a/clang-tidy/google/AvoidThrowingObjCExceptionCheck.h
+++ b/clang-tidy/google/AvoidThrowingObjCExceptionCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp b/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp
new file mode 100644
index 00000000..fbc47b77
--- /dev/null
+++ b/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp
@@ -0,0 +1,89 @@
+//===--- 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(
+ CompilerInstance &Compiler) {
+ Compiler.getPreprocessor().addPPCallbacks(
+ llvm::make_unique<AvoidUnderscoreInGoogletestNameCallback>(
+ &Compiler.getPreprocessor(), 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..8a1a2f25
--- /dev/null
+++ b/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h
@@ -0,0 +1,33 @@
+//===--- 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 "../ClangTidy.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(CompilerInstance &Compiler) 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..cbaa0a6f 100644
--- a/clang-tidy/google/DefaultArgumentsCheck.h
+++ b/clang-tidy/google/DefaultArgumentsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..7efc104b 100644
--- a/clang-tidy/google/ExplicitConstructorCheck.h
+++ b/clang-tidy/google/ExplicitConstructorCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..1eb55282 100644
--- a/clang-tidy/google/ExplicitMakePairCheck.h
+++ b/clang-tidy/google/ExplicitMakePairCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/FunctionNamingCheck.cpp b/clang-tidy/google/FunctionNamingCheck.cpp
index f7064708..3eeb6fa6 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/FunctionNamingCheck.h b/clang-tidy/google/FunctionNamingCheck.h
index 46499e90..6efea261 100644
--- a/clang-tidy/google/FunctionNamingCheck.h
+++ b/clang-tidy/google/FunctionNamingCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..80247bc3 100644
--- a/clang-tidy/google/GlobalNamesInHeadersCheck.h
+++ b/clang-tidy/google/GlobalNamesInHeadersCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/GlobalVariableDeclarationCheck.cpp b/clang-tidy/google/GlobalVariableDeclarationCheck.cpp
index 63885237..b2ad2764 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/GlobalVariableDeclarationCheck.h b/clang-tidy/google/GlobalVariableDeclarationCheck.h
index ed0352bb..7213bebd 100644
--- a/clang-tidy/google/GlobalVariableDeclarationCheck.h
+++ b/clang-tidy/google/GlobalVariableDeclarationCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..c9a1f3be 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/IntegerTypesCheck.h b/clang-tidy/google/IntegerTypesCheck.h
index 8d8f9038..d8a846d9 100644
--- a/clang-tidy/google/IntegerTypesCheck.h
+++ b/clang-tidy/google/IntegerTypesCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..2b7ea8fe 100644
--- a/clang-tidy/google/NonConstReferences.h
+++ b/clang-tidy/google/NonConstReferences.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..2208b37a 100644
--- a/clang-tidy/google/OverloadedUnaryAndCheck.h
+++ b/clang-tidy/google/OverloadedUnaryAndCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/TodoCommentCheck.cpp b/clang-tidy/google/TodoCommentCheck.cpp
index f1c79ce6..c46f07df 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/google/TodoCommentCheck.h b/clang-tidy/google/TodoCommentCheck.h
index dbdc3668..eb89dd03 100644
--- a/clang-tidy/google/TodoCommentCheck.h
+++ b/clang-tidy/google/TodoCommentCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..92cece2b 100644
--- a/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h
+++ b/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..eb636ea2 100644
--- a/clang-tidy/google/UsingNamespaceDirectiveCheck.h
+++ b/clang-tidy/google/UsingNamespaceDirectiveCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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/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..3d23644e 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/llvm/IncludeOrderCheck.h b/clang-tidy/llvm/IncludeOrderCheck.h
index ad876b95..b10496e0 100644
--- a/clang-tidy/llvm/IncludeOrderCheck.h
+++ b/clang-tidy/llvm/IncludeOrderCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/llvm/LLVMTidyModule.cpp b/clang-tidy/llvm/LLVMTidyModule.cpp
index ea46ca93..f5242685 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
//
//===----------------------------------------------------------------------===//
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..c2b03e81 100644
--- a/clang-tidy/llvm/TwineLocalCheck.h
+++ b/clang-tidy/llvm/TwineLocalCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..8e5eb7c8 100644
--- a/clang-tidy/misc/DefinitionsInHeadersCheck.h
+++ b/clang-tidy/misc/DefinitionsInHeadersCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..a156e3e3 100644
--- a/clang-tidy/misc/MisplacedConstCheck.h
+++ b/clang-tidy/misc/MisplacedConstCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..46a3bb72 100644
--- a/clang-tidy/misc/NewDeleteOverloadsCheck.h
+++ b/clang-tidy/misc/NewDeleteOverloadsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..5ebaba83 100644
--- a/clang-tidy/misc/NonCopyableObjects.h
+++ b/clang-tidy/misc/NonCopyableObjects.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..6072eae8 100644
--- a/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.h
+++ b/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..02d37e16 100644
--- a/clang-tidy/misc/RedundantExpressionCheck.h
+++ b/clang-tidy/misc/RedundantExpressionCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/misc/StaticAssertCheck.cpp b/clang-tidy/misc/StaticAssertCheck.cpp
index 583ed7ad..18d94128 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/misc/StaticAssertCheck.h b/clang-tidy/misc/StaticAssertCheck.h
index faefce17..f3d3586e 100644
--- a/clang-tidy/misc/StaticAssertCheck.h
+++ b/clang-tidy/misc/StaticAssertCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..6b79c20f 100644
--- a/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h
+++ b/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..761701df 100644
--- a/clang-tidy/misc/UnconventionalAssignOperatorCheck.h
+++ b/clang-tidy/misc/UnconventionalAssignOperatorCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..d013f32c 100644
--- a/clang-tidy/misc/UniqueptrResetReleaseCheck.h
+++ b/clang-tidy/misc/UniqueptrResetReleaseCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..af27ef0f 100644
--- a/clang-tidy/misc/UnusedAliasDeclsCheck.h
+++ b/clang-tidy/misc/UnusedAliasDeclsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..f4e07083 100644
--- a/clang-tidy/misc/UnusedParametersCheck.h
+++ b/clang-tidy/misc/UnusedParametersCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/misc/UnusedUsingDeclsCheck.cpp b/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
index 48009b5a..532dbfd4 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/misc/UnusedUsingDeclsCheck.h b/clang-tidy/misc/UnusedUsingDeclsCheck.h
index 2a41a8f6..acc6a44e 100644
--- a/clang-tidy/misc/UnusedUsingDeclsCheck.h
+++ b/clang-tidy/misc/UnusedUsingDeclsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..c1042d52 100644
--- a/clang-tidy/modernize/AvoidBindCheck.h
+++ b/clang-tidy/modernize/AvoidBindCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..ef638e9b 100644
--- a/clang-tidy/modernize/AvoidCArraysCheck.h
+++ b/clang-tidy/modernize/AvoidCArraysCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/CMakeLists.txt b/clang-tidy/modernize/CMakeLists.txt
index cfacc952..bb5c0aeb 100644
--- a/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tidy/modernize/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_library(clangTidyModernizeModule
UseEmplaceCheck.cpp
UseEqualsDefaultCheck.cpp
UseEqualsDeleteCheck.cpp
+ UseNodiscardCheck.cpp
UseNoexceptCheck.cpp
UseNullptrCheck.cpp
UseOverrideCheck.cpp
diff --git a/clang-tidy/modernize/ConcatNestedNamespacesCheck.cpp b/clang-tidy/modernize/ConcatNestedNamespacesCheck.cpp
index bef85f7b..33ac8561 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/ConcatNestedNamespacesCheck.h b/clang-tidy/modernize/ConcatNestedNamespacesCheck.h
index 547690d2..7f3c6934 100644
--- a/clang-tidy/modernize/ConcatNestedNamespacesCheck.h
+++ b/clang-tidy/modernize/ConcatNestedNamespacesCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/DeprecatedHeadersCheck.cpp b/clang-tidy/modernize/DeprecatedHeadersCheck.cpp
index 1ff3f898..ffc041b4 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/DeprecatedHeadersCheck.h b/clang-tidy/modernize/DeprecatedHeadersCheck.h
index ee7254e3..4be4ad90 100644
--- a/clang-tidy/modernize/DeprecatedHeadersCheck.h
+++ b/clang-tidy/modernize/DeprecatedHeadersCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..bbb5ff74 100644
--- a/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.h
+++ b/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..f98a1dc4 100644
--- a/clang-tidy/modernize/LoopConvertCheck.h
+++ b/clang-tidy/modernize/LoopConvertCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..9b0c5d82 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/MakeSmartPtrCheck.h b/clang-tidy/modernize/MakeSmartPtrCheck.h
index 02428d7a..82855e24 100644
--- a/clang-tidy/modernize/MakeSmartPtrCheck.h
+++ b/clang-tidy/modernize/MakeSmartPtrCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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 6bad6cbe..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
//
//===----------------------------------------------------------------------===//
@@ -32,6 +31,7 @@
#include "UseEmplaceCheck.h"
#include "UseEqualsDefaultCheck.h"
#include "UseEqualsDeleteCheck.h"
+#include "UseNodiscardCheck.h"
#include "UseNoexceptCheck.h"
#include "UseNullptrCheck.h"
#include "UseOverrideCheck.h"
@@ -82,6 +82,8 @@ public:
CheckFactories.registerCheck<UseEqualsDefaultCheck>("modernize-use-equals-default");
CheckFactories.registerCheck<UseEqualsDeleteCheck>(
"modernize-use-equals-delete");
+ CheckFactories.registerCheck<UseNodiscardCheck>(
+ "modernize-use-nodiscard");
CheckFactories.registerCheck<UseNoexceptCheck>("modernize-use-noexcept");
CheckFactories.registerCheck<UseNullptrCheck>("modernize-use-nullptr");
CheckFactories.registerCheck<UseOverrideCheck>("modernize-use-override");
diff --git a/clang-tidy/modernize/PassByValueCheck.cpp b/clang-tidy/modernize/PassByValueCheck.cpp
index f54c5754..15c37253 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/PassByValueCheck.h b/clang-tidy/modernize/PassByValueCheck.h
index 37deb3f7..fde65174 100644
--- a/clang-tidy/modernize/PassByValueCheck.h
+++ b/clang-tidy/modernize/PassByValueCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..370400cc 100644
--- a/clang-tidy/modernize/RawStringLiteralCheck.h
+++ b/clang-tidy/modernize/RawStringLiteralCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/RedundantVoidArgCheck.cpp b/clang-tidy/modernize/RedundantVoidArgCheck.cpp
index ea49ab7b..96eb7a2b 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/RedundantVoidArgCheck.h b/clang-tidy/modernize/RedundantVoidArgCheck.h
index c990ef46..6c90fa3c 100644
--- a/clang-tidy/modernize/RedundantVoidArgCheck.h
+++ b/clang-tidy/modernize/RedundantVoidArgCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp b/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
index 3281ef66..0de835e0 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/ReplaceAutoPtrCheck.h b/clang-tidy/modernize/ReplaceAutoPtrCheck.h
index 5b73d51b..174676e1 100644
--- a/clang-tidy/modernize/ReplaceAutoPtrCheck.h
+++ b/clang-tidy/modernize/ReplaceAutoPtrCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp b/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp
index 9a715693..73afec7a 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/ReplaceRandomShuffleCheck.h b/clang-tidy/modernize/ReplaceRandomShuffleCheck.h
index 050d7401..65367080 100644
--- a/clang-tidy/modernize/ReplaceRandomShuffleCheck.h
+++ b/clang-tidy/modernize/ReplaceRandomShuffleCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..2c60a4e3 100644
--- a/clang-tidy/modernize/ReturnBracedInitListCheck.h
+++ b/clang-tidy/modernize/ReturnBracedInitListCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..2f873744 100644
--- a/clang-tidy/modernize/ShrinkToFitCheck.h
+++ b/clang-tidy/modernize/ShrinkToFitCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..e1e95881 100644
--- a/clang-tidy/modernize/UnaryStaticAssertCheck.h
+++ b/clang-tidy/modernize/UnaryStaticAssertCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..f10cd08c 100644
--- a/clang-tidy/modernize/UseAutoCheck.h
+++ b/clang-tidy/modernize/UseAutoCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..898d9f38 100644
--- a/clang-tidy/modernize/UseBoolLiteralsCheck.h
+++ b/clang-tidy/modernize/UseBoolLiteralsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..77f0e73a 100644
--- a/clang-tidy/modernize/UseDefaultMemberInitCheck.h
+++ b/clang-tidy/modernize/UseDefaultMemberInitCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..6a55ffb9 100644
--- a/clang-tidy/modernize/UseEmplaceCheck.h
+++ b/clang-tidy/modernize/UseEmplaceCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..486ccb20 100644
--- a/clang-tidy/modernize/UseEqualsDefaultCheck.h
+++ b/clang-tidy/modernize/UseEqualsDefaultCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..7d1c74d3 100644
--- a/clang-tidy/modernize/UseEqualsDeleteCheck.h
+++ b/clang-tidy/modernize/UseEqualsDeleteCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/UseNodiscardCheck.cpp b/clang-tidy/modernize/UseNodiscardCheck.cpp
new file mode 100644
index 00000000..d2ac7d52
--- /dev/null
+++ b/clang-tidy/modernize/UseNodiscardCheck.cpp
@@ -0,0 +1,144 @@
+//===--- UseNodiscardCheck.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 "UseNodiscardCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Type.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+static bool doesNoDiscardMacroExist(ASTContext &Context,
+ const llvm::StringRef &MacroId) {
+ // Don't check for the Macro existence if we are using an attribute
+ // either a C++17 standard attribute or pre C++17 syntax
+ if (MacroId.startswith("[[") || MacroId.startswith("__attribute__"))
+ return true;
+
+ // Otherwise look up the macro name in the context to see if its defined.
+ return Context.Idents.get(MacroId).hasMacroDefinition();
+}
+
+namespace {
+AST_MATCHER(CXXMethodDecl, isOverloadedOperator) {
+ // Don't put ``[[nodiscard]]`` in front of operators.
+ return Node.isOverloadedOperator();
+}
+AST_MATCHER(CXXMethodDecl, isConversionOperator) {
+ // Don't put ``[[nodiscard]]`` in front of a conversion decl
+ // like operator bool().
+ return isa<CXXConversionDecl>(Node);
+}
+AST_MATCHER(CXXMethodDecl, hasClassMutableFields) {
+ // Don't put ``[[nodiscard]]`` on functions on classes with
+ // mutable member variables.
+ return Node.getParent()->hasMutableFields();
+}
+AST_MATCHER(ParmVarDecl, hasParameterPack) {
+ // Don't put ``[[nodiscard]]`` on functions with parameter pack arguments.
+ return Node.isParameterPack();
+}
+AST_MATCHER(CXXMethodDecl, hasTemplateReturnType) {
+ // Don't put ``[[nodiscard]]`` in front of functions returning a template
+ // type.
+ return Node.getReturnType()->isTemplateTypeParmType() ||
+ Node.getReturnType()->isInstantiationDependentType();
+}
+AST_MATCHER(CXXMethodDecl, isDefinitionOrInline) {
+ // A function definition, with optional inline but not the declaration.
+ return !(Node.isThisDeclarationADefinition() && Node.isOutOfLine());
+}
+AST_MATCHER(QualType, isInstantiationDependentType) {
+ return Node->isInstantiationDependentType();
+}
+AST_MATCHER(QualType, isNonConstReferenceOrPointer) {
+ // If the function has any non-const-reference arguments
+ // bool foo(A &a)
+ // or pointer arguments
+ // bool foo(A*)
+ // then they may not care about the return value because of passing data
+ // via the arguments.
+ return (Node->isTemplateTypeParmType() || Node->isPointerType() ||
+ (Node->isReferenceType() &&
+ !Node.getNonReferenceType().isConstQualified()) ||
+ Node->isInstantiationDependentType());
+}
+} // namespace
+
+UseNodiscardCheck::UseNodiscardCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ NoDiscardMacro(Options.get("ReplacementString", "[[nodiscard]]")) {}
+
+void UseNodiscardCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "ReplacementString", NoDiscardMacro);
+}
+
+void UseNodiscardCheck::registerMatchers(MatchFinder *Finder) {
+ // If we use ``[[nodiscard]]`` attribute, we require at least C++17. Use a
+ // macro or ``__attribute__`` with pre c++17 compilers by using
+ // ReplacementString option.
+ if ((NoDiscardMacro == "[[nodiscard]]" && !getLangOpts().CPlusPlus17) ||
+ !getLangOpts().CPlusPlus)
+ return;
+
+ auto FunctionObj =
+ cxxRecordDecl(hasAnyName("::std::function", "::boost::function"));
+
+ // Find all non-void const methods which have not already been marked to
+ // warn on unused result.
+ Finder->addMatcher(
+ cxxMethodDecl(
+ allOf(isConst(), isDefinitionOrInline(),
+ unless(anyOf(
+ returns(voidType()), isNoReturn(), isOverloadedOperator(),
+ isVariadic(), hasTemplateReturnType(),
+ hasClassMutableFields(), isConversionOperator(),
+ hasAttr(clang::attr::WarnUnusedResult),
+ hasType(isInstantiationDependentType()),
+ hasAnyParameter(anyOf(
+ parmVarDecl(anyOf(hasType(FunctionObj),
+ hasType(references(FunctionObj)))),
+ hasType(isNonConstReferenceOrPointer()),
+ hasParameterPack()))))))
+ .bind("no_discard"),
+ this);
+}
+
+void UseNodiscardCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *MatchedDecl = Result.Nodes.getNodeAs<CXXMethodDecl>("no_discard");
+ // Don't make replacements if the location is invalid or in a macro.
+ SourceLocation Loc = MatchedDecl->getLocation();
+ if (Loc.isInvalid() || Loc.isMacroID())
+ return;
+
+ SourceLocation RetLoc = MatchedDecl->getInnerLocStart();
+
+ ASTContext &Context = *Result.Context;
+
+ auto Diag = diag(RetLoc, "function %0 should be marked " + NoDiscardMacro)
+ << MatchedDecl;
+
+ // Check for the existence of the keyword being used as the ``[[nodiscard]]``.
+ if (!doesNoDiscardMacroExist(Context, NoDiscardMacro))
+ return;
+
+ // Possible false positives include:
+ // 1. A const member function which returns a variable which is ignored
+ // but performs some external I/O operation and the return value could be
+ // ignored.
+ Diag << FixItHint::CreateInsertion(RetLoc, NoDiscardMacro + " ");
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/modernize/UseNodiscardCheck.h b/clang-tidy/modernize/UseNodiscardCheck.h
new file mode 100644
index 00000000..004ef58c
--- /dev/null
+++ b/clang-tidy/modernize/UseNodiscardCheck.h
@@ -0,0 +1,49 @@
+//===--- UseNodiscardCheck.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_MODERNIZE_USENODISCARDCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USENODISCARDCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// \brief Add ``[[nodiscard]]`` to non-void const-member functions with no
+/// arguments or pass-by-value or pass by const-reference arguments.
+/// \code
+/// bool empty() const;
+/// bool empty(const Bar &) const;
+/// bool empty(int bar) const;
+/// \endcode
+/// Is converted to:
+/// \code
+/// [[nodiscard]] bool empty() const;
+/// [[nodiscard]] bool empty(const Bar &) const;
+/// [[nodiscard]] bool empty(int bar) const;
+/// \endcode
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-nodiscard.html
+class UseNodiscardCheck : public ClangTidyCheck {
+public:
+ UseNodiscardCheck(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 std::string NoDiscardMacro;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USENODISCARDCHECK_H
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..f947d5db 100644
--- a/clang-tidy/modernize/UseNoexceptCheck.h
+++ b/clang-tidy/modernize/UseNoexceptCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..7fa8b4f1 100644
--- a/clang-tidy/modernize/UseNullptrCheck.h
+++ b/clang-tidy/modernize/UseNullptrCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/UseOverrideCheck.cpp b/clang-tidy/modernize/UseOverrideCheck.cpp
index 9429eb2c..6b065955 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/modernize/UseOverrideCheck.h b/clang-tidy/modernize/UseOverrideCheck.h
index 83ce7da7..0f316095 100644
--- a/clang-tidy/modernize/UseOverrideCheck.h
+++ b/clang-tidy/modernize/UseOverrideCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..effc754c 100644
--- a/clang-tidy/modernize/UseTransparentFunctorsCheck.h
+++ b/clang-tidy/modernize/UseTransparentFunctorsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..80db6a61 100644
--- a/clang-tidy/modernize/UseUncaughtExceptionsCheck.h
+++ b/clang-tidy/modernize/UseUncaughtExceptionsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..0975751f 100644
--- a/clang-tidy/modernize/UseUsingCheck.h
+++ b/clang-tidy/modernize/UseUsingCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..833608bd 100644
--- a/clang-tidy/mpi/BufferDerefCheck.h
+++ b/clang-tidy/mpi/BufferDerefCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..28ff6056 100644
--- a/clang-tidy/mpi/TypeMismatchCheck.h
+++ b/clang-tidy/mpi/TypeMismatchCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..33deaba9 100644
--- a/clang-tidy/objc/AvoidNSErrorInitCheck.h
+++ b/clang-tidy/objc/AvoidNSErrorInitCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..2a3cd40d 100644
--- a/clang-tidy/objc/AvoidSpinlockCheck.h
+++ b/clang-tidy/objc/AvoidSpinlockCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..93ebc7e0 100644
--- a/clang-tidy/objc/ForbiddenSubclassingCheck.h
+++ b/clang-tidy/objc/ForbiddenSubclassingCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/objc/ObjCTidyModule.cpp b/clang-tidy/objc/ObjCTidyModule.cpp
index 19152c21..5686c9fb 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/objc/PropertyDeclarationCheck.cpp b/clang-tidy/objc/PropertyDeclarationCheck.cpp
index 94b82f00..653c6bb8 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/objc/PropertyDeclarationCheck.h b/clang-tidy/objc/PropertyDeclarationCheck.h
index b2683bae..d28bde40 100644
--- a/clang-tidy/objc/PropertyDeclarationCheck.h
+++ b/clang-tidy/objc/PropertyDeclarationCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..9b28e506 100644
--- a/clang-tidy/performance/FasterStringFindCheck.h
+++ b/clang-tidy/performance/FasterStringFindCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..6621f39a 100644
--- a/clang-tidy/performance/ForRangeCopyCheck.h
+++ b/clang-tidy/performance/ForRangeCopyCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..3c27498a 100644
--- a/clang-tidy/performance/ImplicitConversionInLoopCheck.h
+++ b/clang-tidy/performance/ImplicitConversionInLoopCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..09e2c950 100644
--- a/clang-tidy/performance/InefficientAlgorithmCheck.h
+++ b/clang-tidy/performance/InefficientAlgorithmCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..cfefa339 100644
--- a/clang-tidy/performance/InefficientStringConcatenationCheck.h
+++ b/clang-tidy/performance/InefficientStringConcatenationCheck.h
@@ -1,10 +1,9 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..c9785920 100644
--- a/clang-tidy/performance/InefficientVectorOperationCheck.h
+++ b/clang-tidy/performance/InefficientVectorOperationCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..ec1b81be 100644
--- a/clang-tidy/performance/MoveConstArgCheck.h
+++ b/clang-tidy/performance/MoveConstArgCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/MoveConstructorInitCheck.cpp b/clang-tidy/performance/MoveConstructorInitCheck.cpp
index 52283fb2..abc5f4f2 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/MoveConstructorInitCheck.h b/clang-tidy/performance/MoveConstructorInitCheck.h
index 3b7dda06..34a202e3 100644
--- a/clang-tidy/performance/MoveConstructorInitCheck.h
+++ b/clang-tidy/performance/MoveConstructorInitCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..43a83459 100644
--- a/clang-tidy/performance/NoexceptMoveConstructorCheck.h
+++ b/clang-tidy/performance/NoexceptMoveConstructorCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/PerformanceTidyModule.cpp b/clang-tidy/performance/PerformanceTidyModule.cpp
index 646c6595..0a5a0be2 100644
--- a/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -1,9 +1,8 @@
//===--- PeformanceTidyModule.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..7b9b1f79 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/TypePromotionInMathFnCheck.h b/clang-tidy/performance/TypePromotionInMathFnCheck.h
index 22429570..bb5900ae 100644
--- a/clang-tidy/performance/TypePromotionInMathFnCheck.h
+++ b/clang-tidy/performance/TypePromotionInMathFnCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..bf785e6a 100644
--- a/clang-tidy/performance/UnnecessaryCopyInitialization.h
+++ b/clang-tidy/performance/UnnecessaryCopyInitialization.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/UnnecessaryValueParamCheck.cpp b/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
index ff3674fe..44f5fc20 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/performance/UnnecessaryValueParamCheck.h b/clang-tidy/performance/UnnecessaryValueParamCheck.h
index a1d65869..84252edb 100644
--- a/clang-tidy/performance/UnnecessaryValueParamCheck.h
+++ b/clang-tidy/performance/UnnecessaryValueParamCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..9d5cb557 100644
--- a/clang-tidy/portability/SIMDIntrinsicsCheck.h
+++ b/clang-tidy/portability/SIMDIntrinsicsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..c8b96b65 100644
--- a/clang-tidy/readability/AvoidConstParamsInDecls.h
+++ b/clang-tidy/readability/AvoidConstParamsInDecls.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..fb45def3 100644
--- a/clang-tidy/readability/BracesAroundStatementsCheck.h
+++ b/clang-tidy/readability/BracesAroundStatementsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/CMakeLists.txt b/clang-tidy/readability/CMakeLists.txt
index c429b812..b48e307e 100644
--- a/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tidy/readability/CMakeLists.txt
@@ -24,6 +24,7 @@ add_clang_library(clangTidyReadabilityModule
RedundantDeclarationCheck.cpp
RedundantFunctionPtrDereferenceCheck.cpp
RedundantMemberInitCheck.cpp
+ RedundantPreprocessorCheck.cpp
RedundantSmartptrGetCheck.cpp
RedundantStringCStrCheck.cpp
RedundantStringInitCheck.cpp
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..58ebc552 100644
--- a/clang-tidy/readability/ConstReturnTypeCheck.h
+++ b/clang-tidy/readability/ConstReturnTypeCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..3d8615b0 100644
--- a/clang-tidy/readability/ContainerSizeEmptyCheck.h
+++ b/clang-tidy/readability/ContainerSizeEmptyCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..f877322b 100644
--- a/clang-tidy/readability/DeleteNullPointerCheck.h
+++ b/clang-tidy/readability/DeleteNullPointerCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..5acf6e28 100644
--- a/clang-tidy/readability/DeletedDefaultCheck.h
+++ b/clang-tidy/readability/DeletedDefaultCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..2feb3aa1 100644
--- a/clang-tidy/readability/ElseAfterReturnCheck.h
+++ b/clang-tidy/readability/ElseAfterReturnCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/FunctionSizeCheck.cpp b/clang-tidy/readability/FunctionSizeCheck.cpp
index 9547afb8..7be502bf 100644
--- a/clang-tidy/readability/FunctionSizeCheck.cpp
+++ b/clang-tidy/readability/FunctionSizeCheck.cpp
@@ -1,9 +1,8 @@
//===--- FunctionSize.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
//
//===----------------------------------------------------------------------===//
@@ -145,7 +144,12 @@ void FunctionSizeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
}
void FunctionSizeCheck::registerMatchers(MatchFinder *Finder) {
- Finder->addMatcher(functionDecl(unless(isInstantiated())).bind("func"), this);
+ // Lambdas ignored - historically considered part of enclosing function.
+ // FIXME: include them instead? Top-level lambdas are currently never counted.
+ Finder->addMatcher(functionDecl(unless(isInstantiated()),
+ unless(cxxMethodDecl(ofClass(isLambda()))))
+ .bind("func"),
+ this);
}
void FunctionSizeCheck::check(const MatchFinder::MatchResult &Result) {
diff --git a/clang-tidy/readability/FunctionSizeCheck.h b/clang-tidy/readability/FunctionSizeCheck.h
index 7defccdb..33340e60 100644
--- a/clang-tidy/readability/FunctionSizeCheck.h
+++ b/clang-tidy/readability/FunctionSizeCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tidy/readability/IdentifierNamingCheck.cpp
index fb3c02e1..56ece5c6 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/IdentifierNamingCheck.h b/clang-tidy/readability/IdentifierNamingCheck.h
index c236ad52..0023a6fa 100644
--- a/clang-tidy/readability/IdentifierNamingCheck.h
+++ b/clang-tidy/readability/IdentifierNamingCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..91d14a73 100644
--- a/clang-tidy/readability/ImplicitBoolConversionCheck.h
+++ b/clang-tidy/readability/ImplicitBoolConversionCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..2002b091 100644
--- a/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.h
+++ b/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.h
@@ -1,9 +1,8 @@
//===- 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
//
//===----------------------------------------------------------------------===//
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..a172d214 100644
--- a/clang-tidy/readability/IsolateDeclarationCheck.h
+++ b/clang-tidy/readability/IsolateDeclarationCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..1ec9db25 100644
--- a/clang-tidy/readability/MagicNumbersCheck.h
+++ b/clang-tidy/readability/MagicNumbersCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/MisleadingIndentationCheck.cpp b/clang-tidy/readability/MisleadingIndentationCheck.cpp
index 9791531f..767406e3 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/MisleadingIndentationCheck.h b/clang-tidy/readability/MisleadingIndentationCheck.h
index 0ca50bb0..c39212a4 100644
--- a/clang-tidy/readability/MisleadingIndentationCheck.h
+++ b/clang-tidy/readability/MisleadingIndentationCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..55bab95c 100644
--- a/clang-tidy/readability/MisplacedArrayIndexCheck.h
+++ b/clang-tidy/readability/MisplacedArrayIndexCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..f783c583 100644
--- a/clang-tidy/readability/NamedParameterCheck.h
+++ b/clang-tidy/readability/NamedParameterCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/NamespaceCommentCheck.cpp b/clang-tidy/readability/NamespaceCommentCheck.cpp
index 229cc626..17184ec2 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/NamespaceCommentCheck.h b/clang-tidy/readability/NamespaceCommentCheck.h
index 1b1a2315..8fb32758 100644
--- a/clang-tidy/readability/NamespaceCommentCheck.h
+++ b/clang-tidy/readability/NamespaceCommentCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..74634c21 100644
--- a/clang-tidy/readability/NonConstParameterCheck.h
+++ b/clang-tidy/readability/NonConstParameterCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tidy/readability/ReadabilityTidyModule.cpp
index 8dab2968..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
//
//===----------------------------------------------------------------------===//
@@ -31,6 +30,7 @@
#include "RedundantDeclarationCheck.h"
#include "RedundantFunctionPtrDereferenceCheck.h"
#include "RedundantMemberInitCheck.h"
+#include "RedundantPreprocessorCheck.h"
#include "RedundantSmartptrGetCheck.h"
#include "RedundantStringCStrCheck.h"
#include "RedundantStringInitCheck.h"
@@ -83,6 +83,8 @@ public:
"readability-redundant-function-ptr-dereference");
CheckFactories.registerCheck<RedundantMemberInitCheck>(
"readability-redundant-member-init");
+ CheckFactories.registerCheck<RedundantPreprocessorCheck>(
+ "readability-redundant-preprocessor");
CheckFactories.registerCheck<SimplifySubscriptExprCheck>(
"readability-simplify-subscript-expr");
CheckFactories.registerCheck<StaticAccessedThroughInstanceCheck>(
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..19433984 100644
--- a/clang-tidy/readability/RedundantControlFlowCheck.h
+++ b/clang-tidy/readability/RedundantControlFlowCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..5286bff4 100644
--- a/clang-tidy/readability/RedundantDeclarationCheck.h
+++ b/clang-tidy/readability/RedundantDeclarationCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..19db1d34 100644
--- a/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.h
+++ b/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..f4c4c097 100644
--- a/clang-tidy/readability/RedundantMemberInitCheck.h
+++ b/clang-tidy/readability/RedundantMemberInitCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/RedundantPreprocessorCheck.cpp b/clang-tidy/readability/RedundantPreprocessorCheck.cpp
new file mode 100644
index 00000000..e208c58e
--- /dev/null
+++ b/clang-tidy/readability/RedundantPreprocessorCheck.cpp
@@ -0,0 +1,108 @@
+//===--- RedundantPreprocessorCheck.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 "RedundantPreprocessorCheck.h"
+#include "clang/Frontend/CompilerInstance.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+namespace {
+/// Information about an opening preprocessor directive.
+struct PreprocessorEntry {
+ SourceLocation Loc;
+ /// Condition used after the preprocessor directive.
+ std::string Condition;
+};
+
+class RedundantPreprocessorCallbacks : public PPCallbacks {
+ enum DirectiveKind { DK_If = 0, DK_Ifdef = 1, DK_Ifndef = 2 };
+
+public:
+ explicit RedundantPreprocessorCallbacks(ClangTidyCheck &Check,
+ Preprocessor &PP)
+ : Check(Check), PP(PP),
+ WarningDescription("nested redundant %select{#if|#ifdef|#ifndef}0; "
+ "consider removing it"),
+ NoteDescription("previous %select{#if|#ifdef|#ifndef}0 was here") {}
+
+ void If(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue) override {
+ StringRef Condition =
+ Lexer::getSourceText(CharSourceRange::getTokenRange(ConditionRange),
+ PP.getSourceManager(), PP.getLangOpts());
+ CheckMacroRedundancy(Loc, Condition, IfStack, DK_If, DK_If, true);
+ }
+
+ void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MacroDefinition) override {
+ std::string MacroName = PP.getSpelling(MacroNameTok);
+ CheckMacroRedundancy(Loc, MacroName, IfdefStack, DK_Ifdef, DK_Ifdef, true);
+ CheckMacroRedundancy(Loc, MacroName, IfndefStack, DK_Ifdef, DK_Ifndef,
+ false);
+ }
+
+ void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MacroDefinition) override {
+ std::string MacroName = PP.getSpelling(MacroNameTok);
+ CheckMacroRedundancy(Loc, MacroName, IfndefStack, DK_Ifndef, DK_Ifndef,
+ true);
+ CheckMacroRedundancy(Loc, MacroName, IfdefStack, DK_Ifndef, DK_Ifdef,
+ false);
+ }
+
+ void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
+ if (!IfStack.empty() && IfLoc == IfStack.back().Loc)
+ IfStack.pop_back();
+ if (!IfdefStack.empty() && IfLoc == IfdefStack.back().Loc)
+ IfdefStack.pop_back();
+ if (!IfndefStack.empty() && IfLoc == IfndefStack.back().Loc)
+ IfndefStack.pop_back();
+ }
+
+private:
+ void CheckMacroRedundancy(SourceLocation Loc, StringRef MacroName,
+ SmallVector<PreprocessorEntry, 4> &Stack,
+ DirectiveKind WarningKind, DirectiveKind NoteKind,
+ bool Store) {
+ if (PP.getSourceManager().isInMainFile(Loc)) {
+ for (const auto &Entry : Stack) {
+ if (Entry.Condition == MacroName) {
+ Check.diag(Loc, WarningDescription) << WarningKind;
+ Check.diag(Entry.Loc, NoteDescription, DiagnosticIDs::Note)
+ << NoteKind;
+ }
+ }
+ }
+
+ if (Store)
+ // This is an actual directive to be remembered.
+ Stack.push_back({Loc, MacroName});
+ }
+
+ ClangTidyCheck &Check;
+ Preprocessor &PP;
+ SmallVector<PreprocessorEntry, 4> IfStack;
+ SmallVector<PreprocessorEntry, 4> IfdefStack;
+ SmallVector<PreprocessorEntry, 4> IfndefStack;
+ const std::string WarningDescription;
+ const std::string NoteDescription;
+};
+} // namespace
+
+void RedundantPreprocessorCheck::registerPPCallbacks(
+ CompilerInstance &Compiler) {
+ Compiler.getPreprocessor().addPPCallbacks(
+ ::llvm::make_unique<RedundantPreprocessorCallbacks>(
+ *this, Compiler.getPreprocessor()));
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/readability/RedundantPreprocessorCheck.h b/clang-tidy/readability/RedundantPreprocessorCheck.h
new file mode 100644
index 00000000..cb70ac7c
--- /dev/null
+++ b/clang-tidy/readability/RedundantPreprocessorCheck.h
@@ -0,0 +1,34 @@
+//===--- RedundantPreprocessorCheck.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_READABILITY_REDUNDANTPREPROCESSORCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTPREPROCESSORCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// This check flags redundant preprocessor directives: nested directives with
+/// the same condition.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-preprocessor.html
+class RedundantPreprocessorCheck : public ClangTidyCheck {
+public:
+ RedundantPreprocessorCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerPPCallbacks(CompilerInstance &Compiler) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTPREPROCESSORCHECK_H
diff --git a/clang-tidy/readability/RedundantSmartptrGetCheck.cpp b/clang-tidy/readability/RedundantSmartptrGetCheck.cpp
index 189130ef..73157c9e 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/RedundantSmartptrGetCheck.h b/clang-tidy/readability/RedundantSmartptrGetCheck.h
index a6f5706c..d4d311ff 100644
--- a/clang-tidy/readability/RedundantSmartptrGetCheck.h
+++ b/clang-tidy/readability/RedundantSmartptrGetCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..dd53e181 100644
--- a/clang-tidy/readability/RedundantStringCStrCheck.h
+++ b/clang-tidy/readability/RedundantStringCStrCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..38399ed9 100644
--- a/clang-tidy/readability/RedundantStringInitCheck.h
+++ b/clang-tidy/readability/RedundantStringInitCheck.h
@@ -1,9 +1,8 @@
//===- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/SimplifyBooleanExprCheck.cpp b/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
index b565a5fe..aa58ad11 100644
--- a/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
+++ b/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
@@ -1,9 +1,8 @@
//===--- SimplifyBooleanExpr.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
//
//===----------------------------------------------------------------------===//
@@ -319,8 +318,6 @@ bool containsDiscardedTokens(const MatchFinder::MatchResult &Result,
} // namespace
class SimplifyBooleanExprCheck::Visitor : public RecursiveASTVisitor<Visitor> {
- using Base = RecursiveASTVisitor<Visitor>;
-
public:
Visitor(SimplifyBooleanExprCheck *Check,
const MatchFinder::MatchResult &Result)
@@ -507,16 +504,8 @@ void SimplifyBooleanExprCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
ChainedConditionalAssignment);
}
-// This is a silly hack to let us run a RecursiveASTVisitor on the Context.
-// We want to match exactly one node in the AST, doesn't matter which.
-AST_MATCHER_P(Decl, matchOnce, bool *, Matched) {
- if (*Matched)
- return false;
- return *Matched = true;
-}
-
void SimplifyBooleanExprCheck::registerMatchers(MatchFinder *Finder) {
- Finder->addMatcher(matchOnce(&MatchedOnce), this);
+ Finder->addMatcher(translationUnitDecl().bind("top"), this);
matchBoolCondition(Finder, true, ConditionThenStmtId);
matchBoolCondition(Finder, false, ConditionElseStmtId);
@@ -535,8 +524,10 @@ void SimplifyBooleanExprCheck::registerMatchers(MatchFinder *Finder) {
}
void SimplifyBooleanExprCheck::check(const MatchFinder::MatchResult &Result) {
- if (const CXXBoolLiteralExpr *TrueConditionRemoved =
- getBoolLiteral(Result, ConditionThenStmtId))
+ if (Result.Nodes.getNodeAs<TranslationUnitDecl>("top"))
+ Visitor(this, Result).TraverseAST(*Result.Context);
+ else if (const CXXBoolLiteralExpr *TrueConditionRemoved =
+ getBoolLiteral(Result, ConditionThenStmtId))
replaceWithThenStatement(Result, TrueConditionRemoved);
else if (const CXXBoolLiteralExpr *FalseConditionRemoved =
getBoolLiteral(Result, ConditionElseStmtId))
@@ -564,10 +555,6 @@ void SimplifyBooleanExprCheck::check(const MatchFinder::MatchResult &Result) {
else if (const auto *Compound =
Result.Nodes.getNodeAs<CompoundStmt>(CompoundNotBoolId))
replaceCompoundReturnWithCondition(Result, Compound, true);
- else { // MatchOnce matcher
- assert(MatchedOnce);
- Visitor(this, Result).TraverseAST(*Result.Context);
- }
}
void SimplifyBooleanExprCheck::issueDiag(
diff --git a/clang-tidy/readability/SimplifyBooleanExprCheck.h b/clang-tidy/readability/SimplifyBooleanExprCheck.h
index 14ac82de..dc1daa27 100644
--- a/clang-tidy/readability/SimplifyBooleanExprCheck.h
+++ b/clang-tidy/readability/SimplifyBooleanExprCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
@@ -79,7 +78,6 @@ private:
SourceLocation Loc, StringRef Description,
SourceRange ReplacementRange, StringRef Replacement);
- bool MatchedOnce = false;
const bool ChainedConditionalReturn;
const bool ChainedConditionalAssignment;
};
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..2929fbe5 100644
--- a/clang-tidy/readability/SimplifySubscriptExprCheck.h
+++ b/clang-tidy/readability/SimplifySubscriptExprCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..d01d8ac8 100644
--- a/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h
+++ b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..12601979 100644
--- a/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h
+++ b/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/StringCompareCheck.cpp b/clang-tidy/readability/StringCompareCheck.cpp
index 38ac43f2..395f406a 100644
--- a/clang-tidy/readability/StringCompareCheck.cpp
+++ b/clang-tidy/readability/StringCompareCheck.cpp
@@ -1,9 +1,8 @@
//===--- MiscStringCompare.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..39e5bd52 100644
--- a/clang-tidy/readability/StringCompareCheck.h
+++ b/clang-tidy/readability/StringCompareCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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..492c642a 100644
--- a/clang-tidy/readability/UniqueptrDeleteReleaseCheck.h
+++ b/clang-tidy/readability/UniqueptrDeleteReleaseCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp b/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp
index eeaece11..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
//
//===----------------------------------------------------------------------===//
@@ -183,12 +182,14 @@ UppercaseLiteralSuffixCheck::UppercaseLiteralSuffixCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
NewSuffixes(
- utils::options::parseStringList(Options.get("NewSuffixes", ""))) {}
+ utils::options::parseStringList(Options.get("NewSuffixes", ""))),
+ IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", 1) != 0) {}
void UppercaseLiteralSuffixCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "NewSuffixes",
utils::options::serializeStringList(NewSuffixes));
+ Options.store(Opts, "IgnoreMacros", IgnoreMacros);
}
void UppercaseLiteralSuffixCheck::registerMatchers(MatchFinder *Finder) {
@@ -216,6 +217,8 @@ bool UppercaseLiteralSuffixCheck::checkBoundMatch(
// We might have a suffix that is already uppercase.
if (auto Details = shouldReplaceLiteralSuffix<LiteralType>(
*Literal, NewSuffixes, *Result.SourceManager, getLangOpts())) {
+ if (Details->LiteralLocation.getBegin().isMacroID() && IgnoreMacros)
+ return true;
auto Complaint = diag(Details->LiteralLocation.getBegin(),
"%0 literal has suffix '%1', which is not uppercase")
<< LiteralType::Name << Details->OldSuffix;
diff --git a/clang-tidy/readability/UppercaseLiteralSuffixCheck.h b/clang-tidy/readability/UppercaseLiteralSuffixCheck.h
index 8d26e6c2..69ddd63e 100644
--- a/clang-tidy/readability/UppercaseLiteralSuffixCheck.h
+++ b/clang-tidy/readability/UppercaseLiteralSuffixCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
@@ -35,6 +34,7 @@ private:
bool checkBoundMatch(const ast_matchers::MatchFinder::MatchResult &Result);
const std::vector<std::string> NewSuffixes;
+ const bool IgnoreMacros;
};
} // namespace readability
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/ClangTidyMain.cpp b/clang-tidy/tool/ClangTidyMain.cpp
index 12a60244..469f360d 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
//
//===----------------------------------------------------------------------===//
///
diff --git a/clang-tidy/tool/clang-tidy-diff.py b/clang-tidy/tool/clang-tidy-diff.py
index f2c15e5e..cf6db4a7 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
#
#===------------------------------------------------------------------------===#
@@ -57,6 +56,9 @@ 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.')
parser.add_argument('-extra-arg', dest='extra_arg',
action='append', default=[],
help='Additional argument to append to the compiler '
@@ -122,6 +124,8 @@ def main():
command.append('-line-filter=' + quote + line_filter_json + quote)
if args.fix:
command.append('-fix')
+ if args.export_fixes:
+ command.append('-export-fixes=' + args.export_fixes)
if args.checks != '':
command.append('-checks=' + quote + args.checks + quote)
if args.quiet:
diff --git a/clang-tidy/tool/run-clang-tidy.py b/clang-tidy/tool/run-clang-tidy.py
index 93635cbe..5ec40f20 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
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..7f1ca529
--- /dev/null
+++ b/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -0,0 +1,154 @@
+//===--- 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"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+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; });
+}
+
+namespace tidy {
+namespace utils {
+
+ExceptionAnalyzer::TypeVec ExceptionAnalyzer::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;
+}
+
+ExceptionAnalyzer::TypeVec ExceptionAnalyzer::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;
+}
+
+bool ExceptionAnalyzer::throwsException(const FunctionDecl *Func) {
+ // Check if the function has already been analyzed and reuse that result.
+ if (FunctionCache.count(Func) > 0)
+ return FunctionCache[Func];
+
+ llvm::SmallSet<const FunctionDecl *, 32> CallStack;
+ TypeVec ExceptionList = throwsException(Func, CallStack);
+
+ // Remove all ignored exceptions from the list of exceptions that can be
+ // thrown.
+ auto NewEnd = llvm::remove_if(ExceptionList, [this](const Type *Exception) {
+ return isIgnoredExceptionType(Exception);
+ });
+ ExceptionList.erase(NewEnd, ExceptionList.end());
+
+ // Cache the result of the analysis.
+ bool FunctionThrows = ExceptionList.size() > 0;
+ FunctionCache.insert(std::make_pair(Func, FunctionThrows));
+
+ return FunctionThrows;
+}
+
+bool ExceptionAnalyzer::isIgnoredExceptionType(const Type *Exception) {
+ if (const auto *TD = Exception->getAsTagDecl()) {
+ if (TD->getDeclName().isIdentifier())
+ return IgnoredExceptions.count(TD->getName()) > 0;
+ }
+ return false;
+}
+
+} // 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..327da300
--- /dev/null
+++ b/clang-tidy/utils/ExceptionAnalyzer.h
@@ -0,0 +1,48 @@
+//===--- 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 "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:
+ ExceptionAnalyzer() = default;
+
+ bool throwsException(const FunctionDecl *Func);
+ void ignoreExceptions(llvm::StringSet<> ExceptionNames) {
+ IgnoredExceptions = std::move(ExceptionNames);
+ }
+
+private:
+ using TypeVec = llvm::SmallVector<const Type *, 8>;
+
+ TypeVec throwsException(const FunctionDecl *Func,
+ llvm::SmallSet<const FunctionDecl *, 32> &CallStack);
+ TypeVec throwsException(const Stmt *St, const TypeVec &Caught,
+ llvm::SmallSet<const FunctionDecl *, 32> &CallStack);
+ bool isIgnoredExceptionType(const Type *Exception);
+
+ llvm::StringSet<> IgnoredExceptions;
+ llvm::DenseMap<const FunctionDecl *, bool> 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..cc56b3f5 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
//
//===----------------------------------------------------------------------===//
diff --git a/clang-tidy/utils/HeaderGuard.h b/clang-tidy/utils/HeaderGuard.h
index a2d8288e..f2062e52 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
//
//===----------------------------------------------------------------------===//
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..a56b5ab5 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
//
//===----------------------------------------------------------------------===//
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..30b76643 100644
--- a/clang-tidy/utils/OptionsUtils.cpp
+++ b/clang-tidy/utils/OptionsUtils.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
//
//===----------------------------------------------------------------------===//
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..ae06601b 100644
--- a/clang-tidy/zircon/TemporaryObjectsCheck.h
+++ b/clang-tidy/zircon/TemporaryObjectsCheck.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
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 dea45671..47559c10 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
//
//===----------------------------------------------------------------------===//
@@ -18,7 +17,6 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/ScopedPrinter.h"
-using namespace llvm;
namespace clang {
namespace clangd {
@@ -35,8 +33,8 @@ bool isSpelledInSourceCode(const Decl *D) {
// macros, we should use the location where the whole definition occurs.
if (Loc.isMacroID()) {
std::string PrintLoc = SM.getSpellingLoc(Loc).printToString(SM);
- if (StringRef(PrintLoc).startswith("<scratch") ||
- StringRef(PrintLoc).startswith("<command line>"))
+ if (llvm::StringRef(PrintLoc).startswith("<scratch") ||
+ llvm::StringRef(PrintLoc).startswith("<command line>"))
return false;
}
return true;
@@ -44,7 +42,7 @@ bool isSpelledInSourceCode(const Decl *D) {
bool isImplementationDetail(const Decl *D) { return !isSpelledInSourceCode(D); }
-SourceLocation findNameLoc(const clang::Decl* D) {
+SourceLocation findNameLoc(const clang::Decl *D) {
const auto &SM = D->getASTContext().getSourceManager();
if (!isSpelledInSourceCode(D))
// Use the expansion location as spelling location is not interesting.
@@ -54,7 +52,7 @@ SourceLocation findNameLoc(const clang::Decl* D) {
std::string printQualifiedName(const NamedDecl &ND) {
std::string QName;
- raw_string_ostream OS(QName);
+ llvm::raw_string_ostream OS(QName);
PrintingPolicy Policy(ND.getASTContext().getLangOpts());
// Note that inline namespaces are treated as transparent scopes. This
// reflects the way they're most commonly used for lookup. Ideally we'd
@@ -115,18 +113,19 @@ std::string printNamespaceScope(const DeclContext &DC) {
return "";
}
-Optional<SymbolID> getSymbolID(const Decl *D) {
- SmallString<128> USR;
+llvm::Optional<SymbolID> getSymbolID(const Decl *D) {
+ llvm::SmallString<128> USR;
if (index::generateUSRForDecl(D, USR))
return None;
return SymbolID(USR);
}
-Optional<SymbolID> getSymbolID(const IdentifierInfo &II, const MacroInfo *MI,
- const SourceManager &SM) {
+llvm::Optional<SymbolID> getSymbolID(const IdentifierInfo &II,
+ const MacroInfo *MI,
+ const SourceManager &SM) {
if (MI == nullptr)
return None;
- SmallString<128> USR;
+ llvm::SmallString<128> USR;
if (index::generateUSRForMacro(II.getName(), MI->getDefinitionLoc(), SM, USR))
return None;
return SymbolID(USR);
diff --git a/clangd/AST.h b/clangd/AST.h
index aa787ace..15c46a4f 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,9 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_AST_H_
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_AST_H_
+#include "index/Index.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/SourceLocation.h"
-#include "index/Index.h"
namespace clang {
class SourceManager;
diff --git a/clangd/CMakeLists.txt b/clangd/CMakeLists.txt
index 39467bd5..6db78920 100644
--- a/clangd/CMakeLists.txt
+++ b/clangd/CMakeLists.txt
@@ -1,7 +1,20 @@
+# Configure the Features.inc file.
+llvm_canonicalize_cmake_booleans(
+ CLANGD_BUILD_XPC)
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/Features.inc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/Features.inc
+)
+
set(LLVM_LINK_COMPONENTS
Support
)
+if(CLANG_BUILT_STANDALONE)
+ # needed to get HAVE_CXX_ATOMICS64_WITHOUT_LIB defined
+ include(CheckAtomic)
+endif()
+
set(CLANGD_ATOMIC_LIB "")
if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
list(APPEND CLANGD_ATOMIC_LIB "atomic")
@@ -27,11 +40,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
@@ -57,6 +72,8 @@ add_clang_library(clangDaemon
index/dex/PostingList.cpp
index/dex/Trigram.cpp
+ refactor/Tweak.cpp
+
LINK_LIBS
clangAST
clangASTMatchers
@@ -94,6 +111,7 @@ add_clang_library(clangDaemon
${CLANGD_ATOMIC_LIB}
)
+add_subdirectory(refactor/tweaks)
if( LLVM_LIB_FUZZING_ENGINE OR LLVM_USE_SANITIZE_COVERAGE )
add_subdirectory(fuzzer)
endif()
@@ -104,3 +122,6 @@ add_subdirectory(index/dex/dexp)
if (LLVM_INCLUDE_BENCHMARKS)
add_subdirectory(benchmarks)
endif()
+if ( CLANGD_BUILD_XPC )
+ add_subdirectory(xpc)
+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 a9d1795d..981c69df 100644
--- a/clangd/ClangdLSPServer.cpp
+++ b/clangd/ClangdLSPServer.cpp
@@ -1,27 +1,59 @@
//===--- 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/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"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
+class IgnoreCompletionError : public llvm::ErrorInfo<CancelledError> {
+public:
+ void log(llvm::raw_ostream &OS) const override {
+ OS << "ignored auto-triggered completion, preceding char did not match";
+ }
+ std::error_code convertToErrorCode() const override {
+ return std::make_error_code(std::errc::operation_canceled);
+ }
+};
+
+/// 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) {
@@ -60,7 +92,7 @@ class ClangdLSPServer::MessageHandler : public Transport::MessageHandler {
public:
MessageHandler(ClangdLSPServer &Server) : Server(Server) {}
- bool onNotify(StringRef Method, json::Value Params) override {
+ bool onNotify(llvm::StringRef Method, llvm::json::Value Params) override {
log("<-- {0}", Method);
if (Method == "exit")
return false;
@@ -75,7 +107,8 @@ public:
return true;
}
- bool onCall(StringRef Method, json::Value Params, json::Value ID) override {
+ bool onCall(llvm::StringRef Method, llvm::json::Value Params,
+ llvm::json::Value ID) override {
// Calls can be canceled by the client. Add cancellation context.
WithContext WithCancel(cancelableRequestContext(ID));
trace::Span Tracer(Method);
@@ -84,22 +117,23 @@ public:
log("<-- {0}({1})", Method, ID);
if (!Server.Server && Method != "initialize") {
elog("Call {0} before initialization.", Method);
- Reply(make_error<LSPError>("server not initialized",
- ErrorCode::ServerNotInitialized));
+ Reply(llvm::make_error<LSPError>("server not initialized",
+ ErrorCode::ServerNotInitialized));
} else if (auto Handler = Calls.lookup(Method))
Handler(std::move(Params), std::move(Reply));
else
- Reply(
- make_error<LSPError>("method not found", ErrorCode::MethodNotFound));
+ Reply(llvm::make_error<LSPError>("method not found",
+ ErrorCode::MethodNotFound));
return true;
}
- bool onReply(json::Value ID, Expected<json::Value> Result) override {
+ bool onReply(llvm::json::Value ID,
+ llvm::Expected<llvm::json::Value> Result) override {
// We ignore replies, just log them.
if (Result)
log("<-- reply({0})", ID);
else
- log("<-- reply({0}) error: {1}", ID, toString(Result.takeError()));
+ log("<-- reply({0}) error: {1}", ID, llvm::toString(Result.takeError()));
return true;
}
@@ -107,15 +141,15 @@ public:
template <typename Param, typename Result>
void bind(const char *Method,
void (ClangdLSPServer::*Handler)(const Param &, Callback<Result>)) {
- Calls[Method] = [Method, Handler, this](json::Value RawParams,
+ Calls[Method] = [Method, Handler, this](llvm::json::Value RawParams,
ReplyOnce Reply) {
Param P;
if (fromJSON(RawParams, P)) {
(Server.*Handler)(P, std::move(Reply));
} else {
elog("Failed to decode {0} request.", Method);
- Reply(make_error<LSPError>("failed to decode request",
- ErrorCode::InvalidRequest));
+ Reply(llvm::make_error<LSPError>("failed to decode request",
+ ErrorCode::InvalidRequest));
}
};
}
@@ -124,7 +158,8 @@ public:
template <typename Param>
void bind(const char *Method,
void (ClangdLSPServer::*Handler)(const Param &)) {
- Notifications[Method] = [Method, Handler, this](json::Value RawParams) {
+ Notifications[Method] = [Method, Handler,
+ this](llvm::json::Value RawParams) {
Param P;
if (!fromJSON(RawParams, P)) {
elog("Failed to decode {0} request.", Method);
@@ -145,14 +180,14 @@ private:
class ReplyOnce {
std::atomic<bool> Replied = {false};
std::chrono::steady_clock::time_point Start;
- json::Value ID;
+ llvm::json::Value ID;
std::string Method;
ClangdLSPServer *Server; // Null when moved-from.
- json::Object *TraceArgs;
+ llvm::json::Object *TraceArgs;
public:
- ReplyOnce(const json::Value &ID, StringRef Method, ClangdLSPServer *Server,
- json::Object *TraceArgs)
+ ReplyOnce(const llvm::json::Value &ID, llvm::StringRef Method,
+ ClangdLSPServer *Server, llvm::json::Object *TraceArgs)
: Start(std::chrono::steady_clock::now()), ID(ID), Method(Method),
Server(Server), TraceArgs(TraceArgs) {
assert(Server);
@@ -163,20 +198,20 @@ private:
Server(Other.Server), TraceArgs(Other.TraceArgs) {
Other.Server = nullptr;
}
- ReplyOnce& operator=(ReplyOnce&&) = delete;
+ ReplyOnce &operator=(ReplyOnce &&) = delete;
ReplyOnce(const ReplyOnce &) = delete;
- ReplyOnce& operator=(const ReplyOnce&) = delete;
+ ReplyOnce &operator=(const ReplyOnce &) = delete;
~ReplyOnce() {
if (Server && !Replied) {
elog("No reply to message {0}({1})", Method, ID);
assert(false && "must reply to all calls!");
- (*this)(make_error<LSPError>("server failed to reply",
- ErrorCode::InternalError));
+ (*this)(llvm::make_error<LSPError>("server failed to reply",
+ ErrorCode::InternalError));
}
}
- void operator()(Expected<json::Value> Reply) {
+ void operator()(llvm::Expected<llvm::json::Value> Reply) {
assert(Server && "moved-from!");
if (Replied.exchange(true)) {
elog("Replied twice to message {0}({1})", Method, ID);
@@ -191,34 +226,34 @@ private:
std::lock_guard<std::mutex> Lock(Server->TranspWriter);
Server->Transp.reply(std::move(ID), std::move(Reply));
} else {
- Error Err = Reply.takeError();
+ llvm::Error Err = Reply.takeError();
log("--> reply:{0}({1}) {2:ms}, error: {3}", Method, ID, Duration, Err);
if (TraceArgs)
- (*TraceArgs)["Error"] = to_string(Err);
+ (*TraceArgs)["Error"] = llvm::to_string(Err);
std::lock_guard<std::mutex> Lock(Server->TranspWriter);
Server->Transp.reply(std::move(ID), std::move(Err));
}
}
};
- StringMap<std::function<void(json::Value)>> Notifications;
- StringMap<std::function<void(json::Value, ReplyOnce)>> Calls;
+ llvm::StringMap<std::function<void(llvm::json::Value)>> Notifications;
+ llvm::StringMap<std::function<void(llvm::json::Value, ReplyOnce)>> Calls;
// Method calls may be cancelled by ID, so keep track of their state.
// This needs a mutex: handlers may finish on a different thread, and that's
// when we clean up entries in the map.
mutable std::mutex RequestCancelersMutex;
- StringMap<std::pair<Canceler, /*Cookie*/ unsigned>> RequestCancelers;
+ llvm::StringMap<std::pair<Canceler, /*Cookie*/ unsigned>> RequestCancelers;
unsigned NextRequestCookie = 0; // To disambiguate reused IDs, see below.
- void onCancel(const json::Value &Params) {
- const json::Value *ID = nullptr;
+ void onCancel(const llvm::json::Value &Params) {
+ const llvm::json::Value *ID = nullptr;
if (auto *O = Params.getAsObject())
ID = O->get("id");
if (!ID) {
elog("Bad cancellation request: {0}", Params);
return;
}
- auto StrID = to_string(*ID);
+ auto StrID = llvm::to_string(*ID);
std::lock_guard<std::mutex> Lock(RequestCancelersMutex);
auto It = RequestCancelers.find(StrID);
if (It != RequestCancelers.end())
@@ -228,9 +263,9 @@ private:
// - allows cancellation using RequestCancelers[ID]
// - cleans up the entry in RequestCancelers when it's no longer needed
// If a client reuses an ID, the last wins and the first cannot be canceled.
- Context cancelableRequestContext(const json::Value &ID) {
+ Context cancelableRequestContext(const llvm::json::Value &ID) {
auto Task = cancelableTask();
- auto StrID = to_string(ID); // JSON-serialize ID for map key.
+ auto StrID = llvm::to_string(ID); // JSON-serialize ID for map key.
auto Cookie = NextRequestCookie++; // No lock, only called on main thread.
{
std::lock_guard<std::mutex> Lock(RequestCancelersMutex);
@@ -239,7 +274,7 @@ private:
// When the request ends, we can clean up the entry we just added.
// The cookie lets us check that it hasn't been overwritten due to ID
// reuse.
- return Task.first.derive(make_scope_exit([this, StrID, Cookie] {
+ return Task.first.derive(llvm::make_scope_exit([this, StrID, Cookie] {
std::lock_guard<std::mutex> Lock(RequestCancelersMutex);
auto It = RequestCancelers.find(StrID);
if (It != RequestCancelers.end() && It->second.second == Cookie)
@@ -251,7 +286,7 @@ private:
};
// call(), notify(), and reply() wrap the Transport, adding logging and locking.
-void ClangdLSPServer::call(StringRef Method, json::Value Params) {
+void ClangdLSPServer::call(llvm::StringRef Method, llvm::json::Value Params) {
auto ID = NextCallID++;
log("--> {0}({1})", Method, ID);
// We currently don't handle responses, so no need to store ID anywhere.
@@ -259,27 +294,28 @@ void ClangdLSPServer::call(StringRef Method, json::Value Params) {
Transp.call(Method, std::move(Params), ID);
}
-void ClangdLSPServer::notify(StringRef Method, json::Value Params) {
+void ClangdLSPServer::notify(llvm::StringRef Method, llvm::json::Value Params) {
log("--> {0}", Method);
std::lock_guard<std::mutex> Lock(TranspWriter);
Transp.notify(Method, std::move(Params));
}
void ClangdLSPServer::onInitialize(const InitializeParams &Params,
- Callback<json::Value> Reply) {
+ Callback<llvm::json::Value> Reply) {
if (Params.rootUri && *Params.rootUri)
ClangdServerOpts.WorkspaceRoot = Params.rootUri->file();
else if (Params.rootPath && !Params.rootPath->empty())
ClangdServerOpts.WorkspaceRoot = *Params.rootPath;
if (Server)
- return Reply(make_error<LSPError>("server already initialized",
- ErrorCode::InvalidRequest));
+ return Reply(llvm::make_error<LSPError>("server already initialized",
+ ErrorCode::InvalidRequest));
if (const auto &Dir = Params.initializationOptions.compilationDatabasePath)
CompileCommandsDir = Dir;
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);
@@ -294,28 +330,31 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
SupportsCodeAction = Params.capabilities.CodeActionStructure;
SupportsHierarchicalDocumentSymbol =
Params.capabilities.HierarchicalDocumentSymbol;
-
- Reply(json::Object{
+ SupportFileStatus = Params.initializationOptions.FileStatus;
+ Reply(llvm::json::Object{
{{"capabilities",
- json::Object{
+ llvm::json::Object{
{"textDocumentSync", (int)TextDocumentSyncKind::Incremental},
{"documentFormattingProvider", true},
{"documentRangeFormattingProvider", true},
{"documentOnTypeFormattingProvider",
- json::Object{
+ llvm::json::Object{
{"firstTriggerCharacter", "}"},
{"moreTriggerCharacter", {}},
}},
{"codeActionProvider", true},
{"completionProvider",
- json::Object{
+ llvm::json::Object{
{"resolveProvider", false},
+ // We do extra checks for '>' and ':' in completion to only
+ // trigger on '->' and '::'.
{"triggerCharacters", {".", ">", ":"}},
}},
{"signatureHelpProvider",
- json::Object{
+ llvm::json::Object{
{"triggerCharacters", {"(", ","}},
}},
+ {"declarationProvider", true},
{"definitionProvider", true},
{"documentHighlightProvider", true},
{"hoverProvider", true},
@@ -324,8 +363,10 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
{"workspaceSymbolProvider", true},
{"referencesProvider", true},
{"executeCommandProvider",
- json::Object{
- {"commands", {ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND}},
+ llvm::json::Object{
+ {"commands",
+ {ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND,
+ ExecuteCommandParams::CLANGD_APPLY_TWEAK}},
}},
}}}});
}
@@ -344,8 +385,8 @@ void ClangdLSPServer::onSync(const NoParams &Params,
if (Server->blockUntilIdleForTest(/*TimeoutSeconds=*/60))
Reply(nullptr);
else
- Reply(createStringError(llvm::inconvertibleErrorCode(),
- "Not idle after a minute"));
+ Reply(llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Not idle after a minute"));
}
void ClangdLSPServer::onDocumentDidOpen(
@@ -366,7 +407,7 @@ void ClangdLSPServer::onDocumentDidChange(
: WantDiagnostics::No;
PathRef File = Params.textDocument.uri.file();
- Expected<std::string> Contents =
+ llvm::Expected<std::string> Contents =
DraftMgr.updateDraft(File, Params.contentChanges);
if (!Contents) {
// If this fails, we are most likely going to be not in sync anymore with
@@ -386,8 +427,8 @@ void ClangdLSPServer::onFileEvent(const DidChangeWatchedFilesParams &Params) {
}
void ClangdLSPServer::onCommand(const ExecuteCommandParams &Params,
- Callback<json::Value> Reply) {
- auto ApplyEdit = [&](WorkspaceEdit WE) {
+ Callback<llvm::json::Value> Reply) {
+ 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
@@ -407,12 +448,37 @@ 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
// more commands are added, this will be here has a safe guard.
- Reply(make_error<LSPError>(
- formatv("Unsupported command \"{0}\".", Params.command).str(),
+ Reply(llvm::make_error<LSPError>(
+ llvm::formatv("Unsupported command \"{0}\".", Params.command).str(),
ErrorCode::InvalidParams));
}
}
@@ -424,7 +490,7 @@ void ClangdLSPServer::onWorkspaceSymbol(
Params.query, CCOpts.Limit,
Bind(
[this](decltype(Reply) Reply,
- Expected<std::vector<SymbolInformation>> Items) {
+ llvm::Expected<std::vector<SymbolInformation>> Items) {
if (!Items)
return Reply(Items.takeError());
for (auto &Sym : *Items)
@@ -438,17 +504,17 @@ void ClangdLSPServer::onWorkspaceSymbol(
void ClangdLSPServer::onRename(const RenameParams &Params,
Callback<WorkspaceEdit> Reply) {
Path File = Params.textDocument.uri.file();
- Optional<std::string> Code = DraftMgr.getDraft(File);
+ llvm::Optional<std::string> Code = DraftMgr.getDraft(File);
if (!Code)
- return Reply(make_error<LSPError>("onRename called for non-added file",
- ErrorCode::InvalidParams));
+ return Reply(llvm::make_error<LSPError>(
+ "onRename called for non-added file", ErrorCode::InvalidParams));
Server->rename(
File, Params.position, Params.newName,
Bind(
- [File, Code,
- Params](decltype(Reply) Reply,
- Expected<std::vector<tooling::Replacement>> Replacements) {
+ [File, Code, Params](
+ decltype(Reply) Reply,
+ llvm::Expected<std::vector<tooling::Replacement>> Replacements) {
if (!Replacements)
return Reply(Replacements.takeError());
@@ -477,7 +543,7 @@ void ClangdLSPServer::onDocumentOnTypeFormatting(
auto File = Params.textDocument.uri.file();
auto Code = DraftMgr.getDraft(File);
if (!Code)
- return Reply(make_error<LSPError>(
+ return Reply(llvm::make_error<LSPError>(
"onDocumentOnTypeFormatting called for non-added file",
ErrorCode::InvalidParams));
@@ -494,7 +560,7 @@ void ClangdLSPServer::onDocumentRangeFormatting(
auto File = Params.textDocument.uri.file();
auto Code = DraftMgr.getDraft(File);
if (!Code)
- return Reply(make_error<LSPError>(
+ return Reply(llvm::make_error<LSPError>(
"onDocumentRangeFormatting called for non-added file",
ErrorCode::InvalidParams));
@@ -511,9 +577,9 @@ void ClangdLSPServer::onDocumentFormatting(
auto File = Params.textDocument.uri.file();
auto Code = DraftMgr.getDraft(File);
if (!Code)
- return Reply(
- make_error<LSPError>("onDocumentFormatting called for non-added file",
- ErrorCode::InvalidParams));
+ return Reply(llvm::make_error<LSPError>(
+ "onDocumentFormatting called for non-added file",
+ ErrorCode::InvalidParams));
auto ReplacementsOrError = Server->formatFile(*Code, File);
if (ReplacementsOrError)
@@ -529,8 +595,8 @@ flattenSymbolHierarchy(llvm::ArrayRef<DocumentSymbol> Symbols,
const URIForFile &FileURI) {
std::vector<SymbolInformation> Results;
- std::function<void(const DocumentSymbol &, StringRef)> Process =
- [&](const DocumentSymbol &S, Optional<StringRef> ParentName) {
+ std::function<void(const DocumentSymbol &, llvm::StringRef)> Process =
+ [&](const DocumentSymbol &S, llvm::Optional<llvm::StringRef> ParentName) {
SymbolInformation SI;
SI.containerName = ParentName ? "" : *ParentName;
SI.name = S.name;
@@ -550,13 +616,13 @@ flattenSymbolHierarchy(llvm::ArrayRef<DocumentSymbol> Symbols,
}
void ClangdLSPServer::onDocumentSymbol(const DocumentSymbolParams &Params,
- Callback<json::Value> Reply) {
+ Callback<llvm::json::Value> Reply) {
URIForFile FileURI = Params.textDocument.uri;
Server->documentSymbols(
Params.textDocument.uri.file(),
Bind(
[this, FileURI](decltype(Reply) Reply,
- Expected<std::vector<DocumentSymbol>> Items) {
+ llvm::Expected<std::vector<DocumentSymbol>> Items) {
if (!Items)
return Reply(Items.takeError());
adjustSymbolKinds(*Items, SupportedSymbolKinds);
@@ -568,7 +634,7 @@ void ClangdLSPServer::onDocumentSymbol(const DocumentSymbolParams &Params,
std::move(Reply)));
}
-static Optional<Command> asCommand(const CodeAction &Action) {
+static llvm::Optional<Command> asCommand(const CodeAction &Action) {
Command Cmd;
if (Action.command && Action.edit)
return None; // Not representable. (We never emit these anyway).
@@ -587,37 +653,58 @@ static Optional<Command> asCommand(const CodeAction &Action) {
}
void ClangdLSPServer::onCodeAction(const CodeActionParams &Params,
- Callback<json::Value> Reply) {
- auto Code = DraftMgr.getDraft(Params.textDocument.uri.file());
+ Callback<llvm::json::Value> Reply) {
+ URIForFile File = Params.textDocument.uri;
+ auto Code = DraftMgr.getDraft(File.file());
if (!Code)
- return Reply(make_error<LSPError>("onCodeAction called for non-added file",
- ErrorCode::InvalidParams));
+ 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(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(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 TextDocumentPositionParams &Params,
+void ClangdLSPServer::onCompletion(const CompletionParams &Params,
Callback<CompletionList> Reply) {
+ if (!shouldRunCompletion(Params))
+ return Reply(llvm::make_error<IgnoreCompletionError>());
Server->codeComplete(Params.textDocument.uri.file(), Params.position, CCOpts,
Bind(
[this](decltype(Reply) Reply,
- Expected<CodeCompleteResult> List) {
+ llvm::Expected<CodeCompleteResult> List) {
if (!List)
return Reply(List.takeError());
CompletionList LSPList;
@@ -639,15 +726,70 @@ 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,
Callback<std::string> Reply) {
- Optional<Path> Result = Server->switchSourceHeader(Params.uri.file());
+ llvm::Optional<Path> Result = Server->switchSourceHeader(Params.uri.file());
Reply(Result ? URI::createFile(*Result).toString() : "");
}
@@ -659,7 +801,7 @@ void ClangdLSPServer::onDocumentHighlight(
}
void ClangdLSPServer::onHover(const TextDocumentPositionParams &Params,
- Callback<Optional<Hover>> Reply) {
+ Callback<llvm::Optional<Hover>> Reply) {
Server->findHover(Params.textDocument.uri.file(), Params.position,
std::move(Reply));
}
@@ -695,7 +837,7 @@ void ClangdLSPServer::onChangeConfiguration(
void ClangdLSPServer::onReference(const ReferenceParams &Params,
Callback<std::vector<Location>> Reply) {
Server->findReferences(Params.textDocument.uri.file(), Params.position,
- std::move(Reply));
+ CCOpts.Limit, std::move(Reply));
}
void ClangdLSPServer::onSymbolInfo(const TextDocumentPositionParams &Params,
@@ -705,11 +847,13 @@ void ClangdLSPServer::onSymbolInfo(const TextDocumentPositionParams &Params,
}
ClangdLSPServer::ClangdLSPServer(class Transport &Transp,
+ const FileSystemProvider &FSProvider,
const clangd::CodeCompleteOptions &CCOpts,
- Optional<Path> CompileCommandsDir,
+ llvm::Optional<Path> CompileCommandsDir,
bool UseDirBasedCDB,
const ClangdServer::Options &Opts)
- : Transp(Transp), MsgHandler(new MessageHandler(*this)), CCOpts(CCOpts),
+ : Transp(Transp), MsgHandler(new MessageHandler(*this)),
+ FSProvider(FSProvider), CCOpts(CCOpts),
SupportedSymbolKinds(defaultSymbolKinds()),
SupportedCompletionItemKinds(defaultCompletionItemKinds()),
UseDirBasedCDB(UseDirBasedCDB),
@@ -726,6 +870,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);
@@ -758,7 +903,7 @@ bool ClangdLSPServer::run() {
return CleanExit && ShutdownRequestReceived;
}
-std::vector<Fix> ClangdLSPServer::getFixes(StringRef File,
+std::vector<Fix> ClangdLSPServer::getFixes(llvm::StringRef File,
const clangd::Diagnostic &D) {
std::lock_guard<std::mutex> Lock(FixItsMutex);
auto DiagToFixItsIter = FixItsMap.find(File);
@@ -773,6 +918,41 @@ std::vector<Fix> ClangdLSPServer::getFixes(StringRef File,
return FixItsIter->second;
}
+bool ClangdLSPServer::shouldRunCompletion(
+ const CompletionParams &Params) const {
+ llvm::StringRef Trigger = Params.context.triggerCharacter;
+ if (Params.context.triggerKind != CompletionTriggerKind::TriggerCharacter ||
+ (Trigger != ">" && Trigger != ":"))
+ return true;
+
+ auto Code = DraftMgr.getDraft(Params.textDocument.uri.file());
+ if (!Code)
+ return true; // completion code will log the error for untracked doc.
+
+ // A completion request is sent when the user types '>' or ':', but we only
+ // want to trigger on '->' and '::'. We check the preceeding character to make
+ // sure it matches what we expected.
+ // Running the lexer here would be more robust (e.g. we can detect comments
+ // and avoid triggering completion there), but we choose to err on the side
+ // of simplicity here.
+ auto Offset = positionToOffset(*Code, Params.position,
+ /*AllowColumnsBeyondLineLength=*/false);
+ if (!Offset) {
+ vlog("could not convert position '{0}' to offset for file '{1}'",
+ Params.position, Params.textDocument.uri.file());
+ return true;
+ }
+ if (*Offset < 2)
+ return false;
+
+ if (Trigger == ">")
+ return (*Code)[*Offset - 2] == '-'; // trigger only on '->'.
+ if (Trigger == ":")
+ return (*Code)[*Offset - 2] == ':'; // trigger only on '::'.
+ assert(false && "unhandled trigger character");
+ return true;
+}
+
void ClangdLSPServer::onDiagnosticsReady(PathRef File,
std::vector<Diag> Diagnostics) {
auto URI = URIForFile::canonicalize(File, /*TUPath=*/File);
@@ -780,7 +960,7 @@ void ClangdLSPServer::onDiagnosticsReady(PathRef File,
DiagnosticToReplacementMap LocalFixIts; // Temporary storage
for (auto &Diag : Diagnostics) {
toLSPDiags(Diag, URI, DiagOpts,
- [&](clangd::Diagnostic Diag, ArrayRef<Fix> Fixes) {
+ [&](clangd::Diagnostic Diag, llvm::ArrayRef<Fix> Fixes) {
auto &FixItsForDiagnostic = LocalFixIts[Diag];
llvm::copy(Fixes, std::back_inserter(FixItsForDiagnostic));
LSPDiagnostics.push_back(std::move(Diag));
@@ -796,12 +976,25 @@ void ClangdLSPServer::onDiagnosticsReady(PathRef File,
// Publish diagnostics.
notify("textDocument/publishDiagnostics",
- json::Object{
+ llvm::json::Object{
{"uri", URI},
{"diagnostics", std::move(LSPDiagnostics)},
});
}
+void ClangdLSPServer::onFileUpdated(PathRef File, const TUStatus &Status) {
+ if (!SupportFileStatus)
+ return;
+ // FIXME: we don't emit "BuildingFile" and `RunningAction`, as these
+ // two statuses are running faster in practice, which leads the UI constantly
+ // changing, and doesn't provide much value. We may want to emit status at a
+ // reasonable time interval (e.g. 0.5s).
+ if (Status.Action.S == TUAction::BuildingFile ||
+ Status.Action.S == TUAction::RunningAction)
+ return;
+ notify("textDocument/clangd.fileStatus", Status.render(File));
+}
+
void ClangdLSPServer::reparseOpenedFiles() {
for (const Path &FilePath : DraftMgr.getActiveFiles())
Server->addDocument(FilePath, *DraftMgr.getDraft(FilePath),
diff --git a/clangd/ClangdLSPServer.h b/clangd/ClangdLSPServer.h
index 8f8b951b..cda46ad1 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
//
//===----------------------------------------------------------------------===//
@@ -38,7 +37,8 @@ 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,
const ClangdServer::Options &Opts);
~ClangdLSPServer();
@@ -52,6 +52,7 @@ public:
private:
// Implement DiagnosticsConsumer.
void onDiagnosticsReady(PathRef File, std::vector<Diag> Diagnostics) override;
+ void onFileUpdated(PathRef File, const TUStatus &Status) override;
// LSP methods. Notifications have signature void(const Params&).
// Calls have signature void(const Params&, Callback<Response>).
@@ -73,10 +74,11 @@ private:
void onDocumentSymbol(const DocumentSymbolParams &,
Callback<llvm::json::Value>);
void onCodeAction(const CodeActionParams &, Callback<llvm::json::Value>);
- void onCompletion(const TextDocumentPositionParams &,
- Callback<CompletionList>);
+ 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>>);
@@ -97,6 +99,12 @@ private:
std::vector<Fix> getFixes(StringRef File, const clangd::Diagnostic &D);
+ /// Checks if completion request should be ignored. We need this due to the
+ /// limitation of the LSP. Per LSP, a client sends requests for all "trigger
+ /// character" we specify, but for '>' and ':' we need to check they actually
+ /// produce '->' and '::', respectively.
+ bool shouldRunCompletion(const CompletionParams &Params) const;
+
/// Forces a reparse of all currently opened files. As a result, this method
/// may be very expensive. This method is normally called when the
/// compilation database is changed.
@@ -123,7 +131,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.
@@ -132,11 +140,12 @@ private:
SymbolKindBitset SupportedSymbolKinds;
/// The supported completion item kinds of the client.
CompletionItemKindBitset SupportedCompletionItemKinds;
- // Whether the client supports CodeAction response objects.
+ /// Whether the client supports CodeAction response objects.
bool SupportsCodeAction = false;
/// From capabilities of textDocument/documentSymbol.
bool SupportsHierarchicalDocumentSymbol = false;
-
+ /// Whether the client supports showing file status.
+ bool SupportFileStatus = false;
// Store of the current versions of the open documents.
DraftStore DraftMgr;
diff --git a/clangd/ClangdServer.cpp b/clangd/ClangdServer.cpp
index da491ee4..9dc33280 100644
--- a/clangd/ClangdServer.cpp
+++ b/clangd/ClangdServer.cpp
@@ -1,26 +1,28 @@
//===--- 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 "SourceCode.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,26 +30,22 @@
#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>
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
-std::string getStandardResourceDir() {
- static int Dummy; // Just an address in this process.
- return CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy);
-}
-
class RefactoringResultCollector final
: public tooling::RefactoringResultConsumer {
public:
- void handleError(Error Err) override {
+ 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
@@ -63,7 +61,7 @@ public:
Result = std::move(SourceReplacements);
}
- Optional<Expected<tooling::AtomicChanges>> Result;
+ llvm::Optional<llvm::Expected<tooling::AtomicChanges>> Result;
};
// Update the FileIndex with new ASTs and plumb the diagnostics responses.
@@ -72,9 +70,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 {
@@ -109,11 +108,11 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
DiagnosticsConsumer &DiagConsumer,
const Options &Opts)
: CDB(CDB), FSProvider(FSProvider),
- ResourceDir(Opts.ResourceDir ? *Opts.ResourceDir
- : getStandardResourceDir()),
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
@@ -138,7 +137,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());
@@ -147,21 +146,27 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
AddIndex(DynamicIdx.get());
}
-void ClangdServer::addDocument(PathRef File, StringRef Contents,
+void ClangdServer::addDocument(PathRef File, llvm::StringRef Contents,
WantDiagnostics WantDiags) {
+ ParseOptions Opts;
+ Opts.ClangTidyOpts = tidy::ClangTidyOptions::getDefaults();
+ if (ClangTidyOptProvider)
+ Opts.ClangTidyOpts = ClangTidyOptProvider->getOptions(File);
+ Opts.SuggestMissingIncludes = SuggestMissingIncludes;
// 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);
+ ParseInputs Inputs;
+ Inputs.CompileCommand = getCompileCommand(File);
+ 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);
-}
+void ClangdServer::removeDocument(PathRef File) { WorkScheduler.remove(File); }
void ClangdServer::codeComplete(PathRef File, Position Pos,
const clangd::CodeCompleteOptions &Opts,
@@ -177,13 +182,13 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
auto Task = [PCHs, Pos, FS, CodeCompleteOpts,
this](Path File, Callback<CodeCompleteResult> CB,
- Expected<InputsAndPreamble> IP) {
+ llvm::Expected<InputsAndPreamble> IP) {
if (!IP)
return CB(IP.takeError());
if (isCancelled())
- return CB(make_error<CancelledError>());
+ return CB(llvm::make_error<CancelledError>());
- Optional<SpeculativeFuzzyFind> SpecFuzzyFind;
+ llvm::Optional<SpeculativeFuzzyFind> SpecFuzzyFind;
if (CodeCompleteOpts.Index && CodeCompleteOpts.SpeculativeIndexRequest) {
SpecFuzzyFind.emplace();
{
@@ -224,7 +229,7 @@ void ClangdServer::signatureHelp(PathRef File, Position Pos,
auto FS = FSProvider.getFileSystem();
auto *Index = this->Index;
auto Action = [Pos, FS, PCHs, Index](Path File, Callback<SignatureHelp> CB,
- Expected<InputsAndPreamble> IP) {
+ llvm::Expected<InputsAndPreamble> IP) {
if (!IP)
return CB(IP.takeError());
@@ -241,43 +246,44 @@ void ClangdServer::signatureHelp(PathRef File, Position Pos,
Bind(Action, File.str(), std::move(CB)));
}
-Expected<tooling::Replacements>
-ClangdServer::formatRange(StringRef Code, PathRef File, Range Rng) {
- Expected<size_t> Begin = positionToOffset(Code, Rng.start);
+llvm::Expected<tooling::Replacements>
+ClangdServer::formatRange(llvm::StringRef Code, PathRef File, Range Rng) {
+ llvm::Expected<size_t> Begin = positionToOffset(Code, Rng.start);
if (!Begin)
return Begin.takeError();
- Expected<size_t> End = positionToOffset(Code, Rng.end);
+ llvm::Expected<size_t> End = positionToOffset(Code, Rng.end);
if (!End)
return End.takeError();
return formatCode(Code, File, {tooling::Range(*Begin, *End - *Begin)});
}
-Expected<tooling::Replacements> ClangdServer::formatFile(StringRef Code,
- PathRef File) {
+llvm::Expected<tooling::Replacements>
+ClangdServer::formatFile(llvm::StringRef Code, PathRef File) {
// Format everything.
return formatCode(Code, File, {tooling::Range(0, Code.size())});
}
-Expected<tooling::Replacements>
-ClangdServer::formatOnType(StringRef Code, PathRef File, Position Pos) {
+llvm::Expected<tooling::Replacements>
+ClangdServer::formatOnType(llvm::StringRef Code, PathRef File, Position Pos) {
// Look for the previous opening brace from the character position and
// format starting from there.
- Expected<size_t> CursorPos = positionToOffset(Code, Pos);
+ llvm::Expected<size_t> CursorPos = positionToOffset(Code, Pos);
if (!CursorPos)
return CursorPos.takeError();
- size_t PreviousLBracePos = StringRef(Code).find_last_of('{', *CursorPos);
- if (PreviousLBracePos == StringRef::npos)
+ size_t PreviousLBracePos =
+ llvm::StringRef(Code).find_last_of('{', *CursorPos);
+ if (PreviousLBracePos == llvm::StringRef::npos)
PreviousLBracePos = *CursorPos;
size_t Len = *CursorPos - PreviousLBracePos;
return formatCode(Code, File, {tooling::Range(PreviousLBracePos, Len)});
}
-void ClangdServer::rename(PathRef File, Position Pos, StringRef NewName,
+void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
Callback<std::vector<tooling::Replacement>> CB) {
auto Action = [Pos](Path File, std::string NewName,
Callback<std::vector<tooling::Replacement>> CB,
- Expected<InputsAndAST> InpAST) {
+ llvm::Expected<InputsAndAST> InpAST) {
if (!InpAST)
return CB(InpAST.takeError());
auto &AST = InpAST->AST;
@@ -324,16 +330,75 @@ void ClangdServer::rename(PathRef File, Position Pos, 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,
- unique_function<void(std::string)> Callback) {
- auto Action = [](decltype(Callback) Callback, Expected<InputsAndAST> InpAST) {
+ llvm::unique_function<void(std::string)> Callback) {
+ auto Action = [](decltype(Callback) Callback,
+ llvm::Expected<InputsAndAST> InpAST) {
if (!InpAST) {
llvm::consumeError(InpAST.takeError());
return Callback("<no-ast>");
}
std::string Result;
- raw_string_ostream ResultOS(Result);
+ llvm::raw_string_ostream ResultOS(Result);
clangd::dumpAST(InpAST->AST, ResultOS);
ResultOS.flush();
@@ -343,25 +408,25 @@ 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,
- Expected<InputsAndAST> InpAST) {
+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)));
}
-Optional<Path> ClangdServer::switchSourceHeader(PathRef Path) {
+llvm::Optional<Path> ClangdServer::switchSourceHeader(PathRef Path) {
- StringRef SourceExtensions[] = {".cpp", ".c", ".cc", ".cxx",
- ".c++", ".m", ".mm"};
- StringRef HeaderExtensions[] = {".h", ".hh", ".hpp", ".hxx", ".inc"};
+ llvm::StringRef SourceExtensions[] = {".cpp", ".c", ".cc", ".cxx",
+ ".c++", ".m", ".mm"};
+ llvm::StringRef HeaderExtensions[] = {".h", ".hh", ".hpp", ".hxx", ".inc"};
- StringRef PathExt = sys::path::extension(Path);
+ llvm::StringRef PathExt = llvm::sys::path::extension(Path);
// Lookup in a list of known extensions.
auto SourceIter =
@@ -383,28 +448,28 @@ Optional<Path> ClangdServer::switchSourceHeader(PathRef Path) {
// Array to lookup extensions for the switch. An opposite of where original
// extension was found.
- ArrayRef<StringRef> NewExts;
+ llvm::ArrayRef<llvm::StringRef> NewExts;
if (IsSource)
NewExts = HeaderExtensions;
else
NewExts = SourceExtensions;
// Storage for the new path.
- SmallString<128> NewPath = StringRef(Path);
+ llvm::SmallString<128> NewPath = llvm::StringRef(Path);
// Instance of vfs::FileSystem, used for file existence checks.
auto FS = FSProvider.getFileSystem();
// Loop through switched extension candidates.
- for (StringRef NewExt : NewExts) {
- sys::path::replace_extension(NewPath, NewExt);
+ for (llvm::StringRef NewExt : NewExts) {
+ llvm::sys::path::replace_extension(NewPath, NewExt);
if (FS->exists(NewPath))
return NewPath.str().str(); // First str() to convert from SmallString to
// StringRef, second to convert from StringRef
// to std::string
// Also check NewExt in upper-case, just in case.
- sys::path::replace_extension(NewPath, NewExt.upper());
+ llvm::sys::path::replace_extension(NewPath, NewExt.upper());
if (FS->exists(NewPath))
return NewPath.str().str();
}
@@ -412,9 +477,9 @@ Optional<Path> ClangdServer::switchSourceHeader(PathRef Path) {
return None;
}
-Expected<tooling::Replacements>
-ClangdServer::formatCode(StringRef Code, PathRef File,
- ArrayRef<tooling::Range> Ranges) {
+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,
@@ -437,7 +502,7 @@ ClangdServer::formatCode(StringRef Code, PathRef File,
void ClangdServer::findDocumentHighlights(
PathRef File, Position Pos, Callback<std::vector<DocumentHighlight>> CB) {
auto Action = [Pos](Callback<std::vector<DocumentHighlight>> CB,
- Expected<InputsAndAST> InpAST) {
+ llvm::Expected<InputsAndAST> InpAST) {
if (!InpAST)
return CB(InpAST.takeError());
CB(clangd::findDocumentHighlights(InpAST->AST, Pos));
@@ -447,9 +512,9 @@ void ClangdServer::findDocumentHighlights(
}
void ClangdServer::findHover(PathRef File, Position Pos,
- Callback<Optional<Hover>> CB) {
- auto Action = [Pos](Callback<Optional<Hover>> CB,
- Expected<InputsAndAST> InpAST) {
+ Callback<llvm::Optional<Hover>> CB) {
+ auto Action = [Pos](Callback<llvm::Optional<Hover>> CB,
+ llvm::Expected<InputsAndAST> InpAST) {
if (!InpAST)
return CB(InpAST.takeError());
CB(clangd::getHover(InpAST->AST, Pos));
@@ -460,13 +525,9 @@ void ClangdServer::findHover(PathRef File, Position Pos,
tooling::CompileCommand ClangdServer::getCompileCommand(PathRef File) {
trace::Span Span("GetCompileCommand");
- Optional<tooling::CompileCommand> C = CDB.getCompileCommand(File);
+ llvm::Optional<tooling::CompileCommand> C = CDB.getCompileCommand(File);
if (!C) // FIXME: Suppress diagnostics? Let the user know?
C = CDB.getFallbackCommand(File);
-
- // 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);
}
@@ -476,7 +537,8 @@ void ClangdServer::onFileEvent(const DidChangeWatchedFilesParams &Params) {
}
void ClangdServer::workspaceSymbols(
- StringRef Query, int Limit, Callback<std::vector<SymbolInformation>> CB) {
+ llvm::StringRef Query, int Limit,
+ Callback<std::vector<SymbolInformation>> CB) {
std::string QueryCopy = Query;
WorkScheduler.run(
"getWorkspaceSymbols",
@@ -488,7 +550,7 @@ void ClangdServer::workspaceSymbols(
std::move(CB)));
}
-void ClangdServer::documentSymbols(StringRef File,
+void ClangdServer::documentSymbols(llvm::StringRef File,
Callback<std::vector<DocumentSymbol>> CB) {
auto Action = [](Callback<std::vector<DocumentSymbol>> CB,
llvm::Expected<InputsAndAST> InpAST) {
@@ -500,13 +562,13 @@ void ClangdServer::documentSymbols(StringRef File,
Bind(Action, std::move(CB)));
}
-void ClangdServer::findReferences(PathRef File, Position Pos,
+void ClangdServer::findReferences(PathRef File, Position Pos, uint32_t Limit,
Callback<std::vector<Location>> CB) {
- auto Action = [Pos, this](Callback<std::vector<Location>> CB,
- Expected<InputsAndAST> InpAST) {
+ auto Action = [Pos, Limit, this](Callback<std::vector<Location>> CB,
+ llvm::Expected<InputsAndAST> InpAST) {
if (!InpAST)
return CB(InpAST.takeError());
- CB(clangd::findReferences(InpAST->AST, Pos, Index));
+ CB(clangd::findReferences(InpAST->AST, Pos, Limit, Index));
};
WorkScheduler.runWithAST("References", File, Bind(Action, std::move(CB)));
@@ -515,7 +577,7 @@ void ClangdServer::findReferences(PathRef File, Position Pos,
void ClangdServer::symbolInfo(PathRef File, Position Pos,
Callback<std::vector<SymbolDetails>> CB) {
auto Action = [Pos](Callback<std::vector<SymbolDetails>> CB,
- Expected<InputsAndAST> InpAST) {
+ llvm::Expected<InputsAndAST> InpAST) {
if (!InpAST)
return CB(InpAST.takeError());
CB(clangd::getSymbolInfo(InpAST->AST, Pos));
@@ -530,7 +592,7 @@ ClangdServer::getUsedBytesPerFile() const {
}
LLVM_NODISCARD bool
-ClangdServer::blockUntilIdleForTest(Optional<double> TimeoutSeconds) {
+ClangdServer::blockUntilIdleForTest(llvm::Optional<double> TimeoutSeconds) {
return WorkScheduler.blockUntilIdle(timeoutSeconds(TimeoutSeconds)) &&
(!BackgroundIdx ||
BackgroundIdx->blockUntilIdleForTest(TimeoutSeconds));
diff --git a/clangd/ClangdServer.h b/clangd/ClangdServer.h
index 4ce1506d..f3294186 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"
@@ -93,6 +96,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 +117,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 +168,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.
@@ -181,7 +193,7 @@ public:
Callback<std::vector<DocumentSymbol>> CB);
/// Retrieve locations for symbol references.
- void findReferences(PathRef File, Position Pos,
+ void findReferences(PathRef File, Position Pos, uint32_t Limit,
Callback<std::vector<Location>> CB);
/// Run formatting for \p Rng inside \p File with content \p Code.
@@ -202,6 +214,18 @@ public:
void rename(PathRef File, Position Pos, llvm::StringRef NewName,
Callback<std::vector<tooling::Replacement>> 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
/// \p File. \p File must be in the list of added documents.
@@ -258,6 +282,13 @@ 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;
diff --git a/clangd/ClangdUnit.cpp b/clangd/ClangdUnit.cpp
index 013d180b..b07abd9a 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,9 +11,13 @@
#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/Frontend/CompilerInstance.h"
@@ -31,12 +34,13 @@
#include "clang/Serialization/ASTWriter.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>
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -45,7 +49,7 @@ bool compileCommandsAreEqual(const tooling::CompileCommand &LHS,
const tooling::CompileCommand &RHS) {
// We don't check for Output, it should not matter to clangd.
return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename &&
- makeArrayRef(LHS.CommandLine).equals(RHS.CommandLine);
+ llvm::makeArrayRef(LHS.CommandLine).equals(RHS.CommandLine);
}
template <class T> std::size_t getUsedBytes(const std::vector<T> &Vec) {
@@ -80,8 +84,8 @@ public:
std::vector<Decl *> takeTopLevelDecls() { return std::move(TopLevelDecls); }
protected:
- std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) override {
+ std::unique_ptr<ASTConsumer>
+ CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) override {
return llvm::make_unique<DeclTrackingASTConsumer>(/*ref*/ TopLevelDecls);
}
@@ -92,15 +96,19 @@ private:
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); }
+ 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 {
@@ -112,10 +120,17 @@ public:
return collectIncludeStructureCallback(*SourceMgr, &Includes);
}
+ CommentHandler *getCommentHandler() override {
+ IWYUHandler = collectIWYUHeaderMaps(&CanonIncludes);
+ return IWYUHandler.get();
+ }
+
private:
PathRef File;
PreambleParsedCallback ParsedCallback;
IncludeStructure Includes;
+ CanonicalIncludes CanonIncludes;
+ std::unique_ptr<CommentHandler> IWYUHandler = nullptr;
SourceManager *SourceMgr = nullptr;
};
@@ -134,6 +149,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())));
@@ -179,12 +197,12 @@ private:
if (Inc.Resolved != "")
File = SM.getFileManager().getFile(Inc.Resolved);
- StringRef WrittenFilename =
- StringRef(Inc.Written).drop_front().drop_back();
- bool Angled = StringRef(Inc.Written).startswith("<");
+ llvm::StringRef WrittenFilename =
+ llvm::StringRef(Inc.Written).drop_front().drop_back();
+ bool Angled = llvm::StringRef(Inc.Written).startswith("<");
// Re-lex the #include directive to find its interesting parts.
- StringRef Src = SM.getBufferData(SM.getMainFileID());
+ llvm::StringRef Src = SM.getBufferData(SM.getMainFileID());
Lexer RawLexer(SM.getLocForStartOfFile(SM.getMainFileID()), LangOpts,
Src.begin(), Src.begin() + Inc.HashOffset, Src.end());
Token HashTok, IncludeTok, FilenameTok;
@@ -205,7 +223,7 @@ private:
if (File)
Delegate->FileSkipped(*File, FilenameTok, Inc.FileKind);
else {
- SmallString<1> UnusedRecovery;
+ llvm::SmallString<1> UnusedRecovery;
Delegate->FileNotFound(WrittenFilename, UnusedRecovery);
}
}
@@ -220,16 +238,17 @@ private:
} // namespace
-void dumpAST(ParsedAST &AST, raw_ostream &OS) {
+void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS) {
AST.getASTContext().getTranslationUnitDecl()->dump(OS, true);
}
-Optional<ParsedAST>
+llvm::Optional<ParsedAST>
ParsedAST::build(std::unique_ptr<CompilerInvocation> CI,
std::shared_ptr<const PreambleData> Preamble,
- std::unique_ptr<MemoryBuffer> Buffer,
+ std::unique_ptr<llvm::MemoryBuffer> Buffer,
std::shared_ptr<PCHContainerOperations> PCHs,
- IntrusiveRefCntPtr<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.
@@ -238,9 +257,11 @@ ParsedAST::build(std::unique_ptr<CompilerInvocation> CI,
Preamble ? &Preamble->Preamble : nullptr;
StoreDiags ASTDiags;
+ std::string Content = Buffer->getBuffer();
+
auto Clang =
prepareCompilerInstance(std::move(CI), PreamblePCH, std::move(Buffer),
- std::move(PCHs), std::move(VFS), ASTDiags);
+ std::move(PCHs), VFS, ASTDiags);
if (!Clang)
return None;
@@ -263,18 +284,13 @@ 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());
@@ -287,6 +303,28 @@ ParsedAST::build(std::unique_ptr<CompilerInvocation> CI,
}
}
+ // 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{};
@@ -299,6 +337,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());
@@ -328,7 +377,7 @@ ParsedAST::build(std::unique_ptr<CompilerInvocation> CI,
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;
@@ -362,7 +411,7 @@ const Preprocessor &ParsedAST::getPreprocessor() const {
return Clang->getPreprocessor();
}
-ArrayRef<Decl *> ParsedAST::getLocalTopLevelDecls() {
+llvm::ArrayRef<Decl *> ParsedAST::getLocalTopLevelDecls() {
return LocalTopLevelDecls;
}
@@ -404,53 +453,32 @@ 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::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)), 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;
- 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,
@@ -460,7 +488,7 @@ buildPreamble(PathRef FileName, CompilerInvocation &CI,
PreambleParsedCallback PreambleCallback) {
// Note that we don't need to copy the input contents, preamble can live
// without those.
- auto ContentsBuffer = MemoryBuffer::getMemBuffer(Inputs.Contents);
+ auto ContentsBuffer = llvm::MemoryBuffer::getMemBuffer(Inputs.Contents);
auto Bounds =
ComputePreambleBounds(*CI.getLangOpts(), ContentsBuffer.get(), 0);
@@ -468,7 +496,7 @@ buildPreamble(PathRef FileName, CompilerInvocation &CI,
compileCommandsAreEqual(Inputs.CompileCommand, OldCompileCommand) &&
OldPreamble->Preamble.CanReuse(CI, ContentsBuffer.get(), Bounds,
Inputs.FS.get())) {
- vlog("Reusing preamble for file {0}", Twine(FileName));
+ vlog("Reusing preamble for file {0}", llvm::Twine(FileName));
return OldPreamble;
}
vlog("Preamble for file {0} cannot be reused. Attempting to rebuild it.",
@@ -477,7 +505,7 @@ buildPreamble(PathRef FileName, CompilerInvocation &CI,
trace::Span Tracer("BuildPreamble");
SPAN_ATTACH(Tracer, "File", FileName);
StoreDiags PreambleDiagnostics;
- IntrusiveRefCntPtr<DiagnosticsEngine> PreambleDiagsEngine =
+ llvm::IntrusiveRefCntPtr<DiagnosticsEngine> PreambleDiagsEngine =
CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(),
&PreambleDiagnostics, false);
@@ -496,7 +524,7 @@ buildPreamble(PathRef FileName, CompilerInvocation &CI,
// dirs.
}
- SmallString<32> AbsFileName(FileName);
+ llvm::SmallString<32> AbsFileName(FileName);
Inputs.FS->makeAbsolute(AbsFileName);
auto StatCache = llvm::make_unique<PreambleFileStatusCache>(AbsFileName);
auto BuiltPreamble = PrecompiledPreamble::Build(
@@ -513,18 +541,19 @@ buildPreamble(PathRef FileName, CompilerInvocation &CI,
FileName);
return std::make_shared<PreambleData>(
std::move(*BuiltPreamble), PreambleDiagnostics.take(),
- SerializedDeclsCollector.takeIncludes(), std::move(StatCache));
+ SerializedDeclsCollector.takeIncludes(), std::move(StatCache),
+ SerializedDeclsCollector.takeCanonicalIncludes());
} else {
elog("Could not build a preamble for file {0}", FileName);
return nullptr;
}
}
-Optional<ParsedAST> buildAST(PathRef FileName,
- std::unique_ptr<CompilerInvocation> Invocation,
- const ParseInputs &Inputs,
- std::shared_ptr<const PreambleData> Preamble,
- std::shared_ptr<PCHContainerOperations> PCHs) {
+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) {
trace::Span Tracer("BuildAST");
SPAN_ATTACH(Tracer, "File", FileName);
@@ -537,9 +566,10 @@ Optional<ParsedAST> buildAST(PathRef FileName,
// dirs.
}
- return ParsedAST::build(
- llvm::make_unique<CompilerInvocation>(*Invocation), Preamble,
- MemoryBuffer::getMemBufferCopy(Inputs.Contents), PCHs, std::move(VFS));
+ return ParsedAST::build(llvm::make_unique<CompilerInvocation>(*Invocation),
+ Preamble,
+ llvm::MemoryBuffer::getMemBufferCopy(Inputs.Contents),
+ PCHs, 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..d5bdd1ab 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,7 +33,7 @@ class raw_ostream;
namespace vfs {
class FileSystem;
-}
+} // namespace vfs
} // namespace llvm
namespace clang {
@@ -39,7 +41,7 @@ class PCHContainerOperations;
namespace tooling {
struct CompileCommand;
-}
+} // namespace tooling
namespace clangd {
@@ -47,7 +49,8 @@ namespace clangd {
struct PreambleData {
PreambleData(PrecompiledPreamble Preamble, std::vector<Diag> Diags,
IncludeStructure Includes,
- std::unique_ptr<PreambleFileStatusCache> StatCache);
+ std::unique_ptr<PreambleFileStatusCache> StatCache,
+ CanonicalIncludes CanonIncludes);
tooling::CompileCommand CompileCommand;
PrecompiledPreamble Preamble;
@@ -58,13 +61,7 @@ struct PreambleData {
// 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.
@@ -77,7 +74,8 @@ public:
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 +103,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 +129,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.
diff --git a/clangd/CodeComplete.cpp b/clangd/CodeComplete.cpp
index 74b90bcf..b059216a 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
//
//===----------------------------------------------------------------------===//
//
@@ -59,7 +58,6 @@
// We log detailed candidate here if you run with -debug-only=codecomplete.
#define DEBUG_TYPE "CodeComplete"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -179,40 +177,19 @@ 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 Expected<HeaderFile> toHeaderFile(StringRef Header, 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};
-}
-
/// A code completion result, in clang-native form.
/// It may be promoted to a CompletionItem if it's among the top-ranked results.
struct CompletionCandidate {
- StringRef Name; // Used for filtering and sorting.
+ llvm::StringRef Name; // Used for filtering and sorting.
// We may have a result from Sema, from the index, or both.
const CodeCompletionResult *SemaResult = nullptr;
const Symbol *IndexResult = nullptr;
- SmallVector<StringRef, 1> RankedIncludeHeaders;
+ 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 {
- SmallString<256> Scratch;
+ llvm::SmallString<256> Scratch;
if (IndexResult) {
switch (IndexResult->SymInfo.Kind) {
case index::SymbolKind::ClassMethod:
@@ -226,7 +203,7 @@ struct CompletionCandidate {
case index::SymbolKind::Function:
// We can't group overloads together that need different #includes.
// This could break #include insertion.
- return hash_combine(
+ return llvm::hash_combine(
(IndexResult->Scope + IndexResult->Name).toStringRef(Scratch),
headerToInsertIfAllowed().getValueOr(""));
default:
@@ -239,14 +216,15 @@ struct CompletionCandidate {
if (!D || !D->isFunctionOrFunctionTemplate())
return 0;
{
- raw_svector_ostream OS(Scratch);
+ llvm::raw_svector_ostream OS(Scratch);
D->printQualifiedName(OS);
}
- return hash_combine(Scratch, headerToInsertIfAllowed().getValueOr(""));
+ return llvm::hash_combine(Scratch,
+ headerToInsertIfAllowed().getValueOr(""));
}
// The best header to include if include insertion is allowed.
- Optional<StringRef> headerToInsertIfAllowed() const {
+ llvm::Optional<llvm::StringRef> headerToInsertIfAllowed() const {
if (RankedIncludeHeaders.empty())
return None;
if (SemaResult && SemaResult->Declaration) {
@@ -260,7 +238,7 @@ struct CompletionCandidate {
return RankedIncludeHeaders[0];
}
- using Bundle = SmallVector<CompletionCandidate, 4>;
+ using Bundle = llvm::SmallVector<CompletionCandidate, 4>;
};
using ScoredBundle =
std::pair<CompletionCandidate::Bundle, CodeCompletion::Scores>;
@@ -283,8 +261,9 @@ struct ScoredBundleGreater {
struct CodeCompletionBuilder {
CodeCompletionBuilder(ASTContext &ASTCtx, const CompletionCandidate &C,
CodeCompletionString *SemaCCS,
- ArrayRef<std::string> QueryScopes,
- const IncludeInserter &Includes, StringRef FileName,
+ llvm::ArrayRef<std::string> QueryScopes,
+ const IncludeInserter &Includes,
+ llvm::StringRef FileName,
CodeCompletionContext::Kind ContextKind,
const CodeCompleteOptions &Opts)
: ASTCtx(ASTCtx), ExtractDocumentation(Opts.IncludeComments),
@@ -292,7 +271,7 @@ struct CodeCompletionBuilder {
add(C, SemaCCS);
if (C.SemaResult) {
Completion.Origin |= SymbolOrigin::AST;
- Completion.Name = StringRef(SemaCCS->getTypedText());
+ Completion.Name = llvm::StringRef(SemaCCS->getTypedText());
if (Completion.Scope.empty()) {
if ((C.SemaResult->Kind == CodeCompletionResult::RK_Declaration) ||
(C.SemaResult->Kind == CodeCompletionResult::RK_Pattern))
@@ -330,9 +309,9 @@ struct CodeCompletionBuilder {
// If the completion was visible to Sema, no qualifier is needed. This
// avoids unneeded qualifiers in cases like with `using ns::X`.
if (Completion.RequiredQualifier.empty() && !C.SemaResult) {
- StringRef ShortestQualifier = C.IndexResult->Scope;
- for (StringRef Scope : QueryScopes) {
- StringRef Qualifier = C.IndexResult->Scope;
+ llvm::StringRef ShortestQualifier = C.IndexResult->Scope;
+ for (llvm::StringRef Scope : QueryScopes) {
+ llvm::StringRef Qualifier = C.IndexResult->Scope;
if (Qualifier.consume_front(Scope) &&
Qualifier.size() < ShortestQualifier.size())
ShortestQualifier = Qualifier;
@@ -343,8 +322,8 @@ struct CodeCompletionBuilder {
}
// Turn absolute path into a literal string that can be #included.
- auto Inserted =
- [&](StringRef Header) -> Expected<std::pair<std::string, bool>> {
+ auto Inserted = [&](llvm::StringRef Header)
+ -> llvm::Expected<std::pair<std::string, bool>> {
auto ResolvedDeclaring =
toHeaderFile(C.IndexResult->CanonicalDeclaration.FileURI, FileName);
if (!ResolvedDeclaring)
@@ -462,7 +441,7 @@ private:
// foo<${1:class}>(${2:int p1}).
// We transform this pattern to '<$1>()$0' or '<$0>()'.
- bool EmptyArgs = StringRef(*Snippet).endswith("()");
+ bool EmptyArgs = llvm::StringRef(*Snippet).endswith("()");
if (Snippet->front() == '<')
return EmptyArgs ? "<$1>()$0" : "<$1>($0)";
if (Snippet->front() == '(')
@@ -476,7 +455,7 @@ private:
// Classes and template using aliases can only have template arguments,
// e.g. Foo<${1:class}>.
- if (StringRef(*Snippet).endswith("<>"))
+ if (llvm::StringRef(*Snippet).endswith("<>"))
return "<>"; // can happen with defaulted template arguments.
return "<$0>";
}
@@ -492,14 +471,14 @@ private:
ASTContext &ASTCtx;
CodeCompletion Completion;
- SmallVector<BundledEntry, 1> Bundled;
+ llvm::SmallVector<BundledEntry, 1> Bundled;
bool ExtractDocumentation;
bool EnableFunctionArgSnippets;
};
// Determine the symbol ID for a Sema code completion result, if possible.
-Optional<SymbolID> getSymbolID(const CodeCompletionResult &R,
- const SourceManager &SM) {
+llvm::Optional<SymbolID> getSymbolID(const CodeCompletionResult &R,
+ const SourceManager &SM) {
switch (R.Kind) {
case CodeCompletionResult::RK_Declaration:
case CodeCompletionResult::RK_Pattern: {
@@ -539,13 +518,13 @@ struct SpecifiedScope {
std::vector<std::string> AccessibleScopes;
// The full scope qualifier as typed by the user (without the leading "::").
// Set if the qualifier is not fully resolved by Sema.
- Optional<std::string> UnresolvedQualifier;
+ llvm::Optional<std::string> UnresolvedQualifier;
// Construct scopes being queried in indexes. The results are deduplicated.
// This method format the scopes to match the index request representation.
std::vector<std::string> scopesForIndexQuery() {
std::set<std::string> Results;
- for (StringRef AS : AccessibleScopes)
+ for (llvm::StringRef AS : AccessibleScopes)
Results.insert(
((UnresolvedQualifier ? *UnresolvedQualifier : "") + AS).str());
return {Results.begin(), Results.end()};
@@ -688,7 +667,7 @@ static bool isBlacklistedMember(const NamedDecl &D) {
// within the callback.
struct CompletionRecorder : public CodeCompleteConsumer {
CompletionRecorder(const CodeCompleteOptions &Opts,
- unique_function<void()> ResultsCallback)
+ llvm::unique_function<void()> ResultsCallback)
: CodeCompleteConsumer(Opts.getClangCompleteOpts(),
/*OutputIsBinary=*/false),
CCContext(CodeCompletionContext::CCC_Other), Opts(Opts),
@@ -766,7 +745,7 @@ struct CompletionRecorder : public CodeCompleteConsumer {
// Returns the filtering/sorting name for Result, which must be from Results.
// Returned string is owned by this recorder (or the AST).
- StringRef getName(const CodeCompletionResult &Result) {
+ llvm::StringRef getName(const CodeCompletionResult &Result) {
switch (Result.Kind) {
case CodeCompletionResult::RK_Declaration:
if (auto *ID = Result.Declaration->getIdentifier())
@@ -796,13 +775,13 @@ private:
CodeCompleteOptions Opts;
std::shared_ptr<GlobalCodeCompletionAllocator> CCAllocator;
CodeCompletionTUInfo CCTUInfo;
- unique_function<void()> ResultsCallback;
+ llvm::unique_function<void()> ResultsCallback;
};
struct ScoredSignature {
// When set, requires documentation to be requested from the index with this
// ID.
- Optional<SymbolID> IDForDoc;
+ llvm::Optional<SymbolID> IDForDoc;
SignatureInformation Signature;
SignatureQualitySignals Quality;
};
@@ -862,7 +841,7 @@ public:
// Sema does not load the docs from the preamble, so we need to fetch extra
// docs from the index instead.
- DenseMap<SymbolID, std::string> FetchedDocs;
+ llvm::DenseMap<SymbolID, std::string> FetchedDocs;
if (Index) {
LookupRequest IndexRequest;
for (const auto &S : ScoredSignatures) {
@@ -879,38 +858,37 @@ public:
IndexRequest.IDs.size(), FetchedDocs.size());
}
- llvm::sort(
- ScoredSignatures,
- [](const ScoredSignature &L, const ScoredSignature &R) {
- // Ordering follows:
- // - Less number of parameters is better.
- // - Function is better than FunctionType which is better than
- // Function Template.
- // - High score is better.
- // - Shorter signature is better.
- // - Alphebatically smaller is better.
- if (L.Quality.NumberOfParameters != R.Quality.NumberOfParameters)
- return L.Quality.NumberOfParameters < R.Quality.NumberOfParameters;
- if (L.Quality.NumberOfOptionalParameters !=
- R.Quality.NumberOfOptionalParameters)
- return L.Quality.NumberOfOptionalParameters <
- R.Quality.NumberOfOptionalParameters;
- if (L.Quality.Kind != R.Quality.Kind) {
- using OC = CodeCompleteConsumer::OverloadCandidate;
- switch (L.Quality.Kind) {
- case OC::CK_Function:
- return true;
- case OC::CK_FunctionType:
- return R.Quality.Kind != OC::CK_Function;
- case OC::CK_FunctionTemplate:
- return false;
- }
- llvm_unreachable("Unknown overload candidate type.");
- }
- if (L.Signature.label.size() != R.Signature.label.size())
- return L.Signature.label.size() < R.Signature.label.size();
- return L.Signature.label < R.Signature.label;
- });
+ llvm::sort(ScoredSignatures, [](const ScoredSignature &L,
+ const ScoredSignature &R) {
+ // Ordering follows:
+ // - Less number of parameters is better.
+ // - Function is better than FunctionType which is better than
+ // Function Template.
+ // - High score is better.
+ // - Shorter signature is better.
+ // - Alphebatically smaller is better.
+ if (L.Quality.NumberOfParameters != R.Quality.NumberOfParameters)
+ return L.Quality.NumberOfParameters < R.Quality.NumberOfParameters;
+ if (L.Quality.NumberOfOptionalParameters !=
+ R.Quality.NumberOfOptionalParameters)
+ return L.Quality.NumberOfOptionalParameters <
+ R.Quality.NumberOfOptionalParameters;
+ if (L.Quality.Kind != R.Quality.Kind) {
+ using OC = CodeCompleteConsumer::OverloadCandidate;
+ switch (L.Quality.Kind) {
+ case OC::CK_Function:
+ return true;
+ case OC::CK_FunctionType:
+ return R.Quality.Kind != OC::CK_Function;
+ case OC::CK_FunctionTemplate:
+ return false;
+ }
+ llvm_unreachable("Unknown overload candidate type.");
+ }
+ if (L.Signature.label.size() != R.Signature.label.size())
+ return L.Signature.label.size() < R.Signature.label.size();
+ return L.Signature.label < R.Signature.label;
+ });
for (auto &SS : ScoredSignatures) {
auto IndexDocIt =
@@ -931,7 +909,7 @@ private:
// CompletionString.h.
ScoredSignature processOverloadCandidate(const OverloadCandidate &Candidate,
const CodeCompletionString &CCS,
- StringRef DocComment) const {
+ llvm::StringRef DocComment) const {
SignatureInformation Signature;
SignatureQualitySignals Signal;
const char *ReturnType = nullptr;
@@ -1003,9 +981,9 @@ struct SemaCompleteInput {
PathRef FileName;
const tooling::CompileCommand &Command;
const PreambleData *Preamble;
- StringRef Contents;
+ llvm::StringRef Contents;
Position Pos;
- IntrusiveRefCntPtr<vfs::FileSystem> VFS;
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;
std::shared_ptr<PCHContainerOperations> PCHs;
};
@@ -1016,33 +994,21 @@ 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.
- }
-
- IntrusiveRefCntPtr<vfs::FileSystem> VFS = Input.VFS;
+ 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.
@@ -1057,8 +1023,8 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
FrontendOpts.CodeCompletionAt.Column) =
offsetToClangLineColumn(Input.Contents, *Offset);
- std::unique_ptr<MemoryBuffer> ContentsBuffer =
- MemoryBuffer::getMemBufferCopy(Input.Contents, Input.FileName);
+ std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer =
+ llvm::MemoryBuffer::getMemBufferCopy(Input.Contents, Input.FileName);
// The diagnostic options must be set before creating a CompilerInstance.
CI->getDiagnosticOpts().IgnoreWarnings = true;
// We reuse the preamble whether it's valid or not. This is a
@@ -1072,6 +1038,7 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
*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
@@ -1140,8 +1107,10 @@ 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.
-Optional<FuzzyFindRequest> speculativeFuzzyFindRequestForCompletion(
- FuzzyFindRequest CachedReq, PathRef File, StringRef Content, Position Pos) {
+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 "
@@ -1153,46 +1122,6 @@ Optional<FuzzyFindRequest> speculativeFuzzyFindRequestForCompletion(
return CachedReq;
}
-} // namespace
-
-clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const {
- clang::CodeCompleteOptions Result;
- Result.IncludeCodePatterns = EnableSnippets && IncludeCodePatterns;
- Result.IncludeMacros = IncludeMacros;
- Result.IncludeGlobals = true;
- // We choose to include full comments and not do doxygen parsing in
- // completion.
- // FIXME: ideally, we should support doxygen in some form, e.g. do markdown
- // formatting of the comments.
- Result.IncludeBriefComments = false;
-
- // When an is used, Sema is responsible for completing the main file,
- // the index can provide results from the preamble.
- // Tell Sema not to deserialize the preamble to look for results.
- Result.LoadExternal = !Index;
- Result.IncludeFixIts = IncludeFixIts;
-
- return Result;
-}
-
-// 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.
-SmallVector<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;
- });
- SmallVector<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:
@@ -1224,30 +1153,30 @@ SmallVector<StringRef, 1> getRankedIncludes(const Symbol &Sym) {
// - TopN determines the results with the best score.
class CodeCompleteFlow {
PathRef FileName;
- IncludeStructure Includes; // Complete once the compiler runs.
+ IncludeStructure Includes; // Complete once the compiler runs.
SpeculativeFuzzyFind *SpecFuzzyFind; // Can be nullptr.
const CodeCompleteOptions &Opts;
// 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?
- Optional<FuzzyMatcher> Filter; // Initialized once Sema runs.
+ bool Incomplete = false; // Would more be available with a higher limit?
+ llvm::Optional<FuzzyMatcher> Filter; // Initialized once Sema runs.
std::vector<std::string> QueryScopes; // Initialized once Sema runs.
// Initialized once QueryScopes is initialized, if there are scopes.
- Optional<ScopeDistance> ScopeProximity;
+ 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;
// Include-insertion and proximity scoring rely on the include structure.
// This is available after Sema has run.
- Optional<IncludeInserter> Inserter; // Available during runWithSema.
- Optional<URIDistance> FileProximity; // Initialized once Sema runs.
+ llvm::Optional<IncludeInserter> Inserter; // Available during runWithSema.
+ llvm::Optional<URIDistance> FileProximity; // Initialized once Sema runs.
/// Speculative request based on the cached request and the filter text before
/// the cursor.
/// Initialized right before sema run. This is only set if `SpecFuzzyFind` is
/// set and contains a cached request.
- Optional<FuzzyFindRequest> SpecReq;
+ llvm::Optional<FuzzyFindRequest> SpecReq;
public:
// A CodeCompleteFlow object is only useful for calling run() exactly once.
@@ -1273,19 +1202,12 @@ 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();
- }
+ 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());
for (const auto &Inc : Includes.MainFileIncludes)
@@ -1297,7 +1219,7 @@ public:
// The per-result proximity scoring is (amortized) very cheap.
FileDistanceOptions ProxOpts{}; // Use defaults.
const auto &SM = Recorder->CCSema->getSourceManager();
- StringMap<SourceParams> ProxSources;
+ llvm::StringMap<SourceParams> ProxSources;
for (auto &Entry : Includes.includeDepth(
SM.getFileEntryForID(SM.getMainFileID())->getName())) {
auto &Source = ProxSources[Entry.getKey()];
@@ -1317,7 +1239,7 @@ public:
log("Code complete: sema context {0}, query scopes [{1}] (AnyScope={2}), "
"expected type {3}",
getCompletionKindString(Recorder->CCContext.getKind()),
- join(QueryScopes.begin(), QueryScopes.end(), ","), AllScopes,
+ llvm::join(QueryScopes.begin(), QueryScopes.end(), ","), AllScopes,
PreferredType ? Recorder->CCContext.getPreferredType().getAsString()
: "<none>");
});
@@ -1411,6 +1333,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)
@@ -1442,7 +1366,7 @@ private:
const SymbolSlab &IndexResults) {
trace::Span Tracer("Merge and score results");
std::vector<CompletionCandidate::Bundle> Bundles;
- DenseMap<size_t, size_t> BundleLookup;
+ llvm::DenseMap<size_t, size_t> BundleLookup;
auto AddToBundles = [&](const CodeCompletionResult *SemaResult,
const Symbol *IndexResult) {
CompletionCandidate C;
@@ -1461,7 +1385,7 @@ private:
Bundles.back().push_back(std::move(C));
}
};
- DenseSet<const Symbol *> UsedIndexResults;
+ llvm::DenseSet<const Symbol *> UsedIndexResults;
auto CorrespondingIndexResult =
[&](const CodeCompletionResult &SemaResult) -> const Symbol * {
if (auto SymID =
@@ -1491,7 +1415,7 @@ private:
return std::move(Top).items();
}
- Optional<float> fuzzyScore(const CompletionCandidate &C) {
+ llvm::Optional<float> fuzzyScore(const CompletionCandidate &C) {
// Macros can be very spammy, so we only support prefix completion.
// We won't end up with underfull index results, as macros are sema-only.
if (C.SemaResult && C.SemaResult->Kind == CodeCompletionResult::RK_Macro &&
@@ -1558,8 +1482,8 @@ private:
: Scores.Quality;
dlog("CodeComplete: {0} ({1}) = {2}\n{3}{4}\n", First.Name,
- to_string(Origin), Scores.Total, to_string(Quality),
- to_string(Relevance));
+ llvm::to_string(Origin), Scores.Total, llvm::to_string(Quality),
+ llvm::to_string(Relevance));
NSema += bool(Origin & SymbolOrigin::AST);
NIndex += FromIndex;
@@ -1569,7 +1493,7 @@ private:
}
CodeCompletion toCodeCompletion(const CompletionCandidate::Bundle &Bundle) {
- Optional<CodeCompletionBuilder> Builder;
+ llvm::Optional<CodeCompletionBuilder> Builder;
for (const auto &Item : Bundle) {
CodeCompletionString *SemaCCS =
Item.SemaResult ? Recorder->codeCompletionString(*Item.SemaResult)
@@ -1585,21 +1509,44 @@ private:
}
};
-Expected<StringRef> speculateCompletionFilter(StringRef Content, Position Pos) {
+} // namespace
+
+clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const {
+ clang::CodeCompleteOptions Result;
+ Result.IncludeCodePatterns = EnableSnippets && IncludeCodePatterns;
+ Result.IncludeMacros = IncludeMacros;
+ Result.IncludeGlobals = true;
+ // We choose to include full comments and not do doxygen parsing in
+ // completion.
+ // FIXME: ideally, we should support doxygen in some form, e.g. do markdown
+ // formatting of the comments.
+ Result.IncludeBriefComments = false;
+
+ // When an is used, Sema is responsible for completing the main file,
+ // the index can provide results from the preamble.
+ // Tell Sema not to deserialize the preamble to look for results.
+ Result.LoadExternal = !Index;
+ Result.IncludeFixIts = IncludeFixIts;
+
+ return Result;
+}
+
+llvm::Expected<llvm::StringRef>
+speculateCompletionFilter(llvm::StringRef Content, Position Pos) {
auto Offset = positionToOffset(Content, Pos);
if (!Offset)
- return make_error<StringError>(
+ return llvm::make_error<llvm::StringError>(
"Failed to convert position to offset in content.",
- inconvertibleErrorCode());
+ llvm::inconvertibleErrorCode());
if (*Offset == 0)
return "";
// 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 == '_'));
+ 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) {
@@ -1611,8 +1558,8 @@ Expected<StringRef> speculateCompletionFilter(StringRef Content, Position Pos) {
CodeCompleteResult
codeComplete(PathRef FileName, const tooling::CompileCommand &Command,
- const PreambleData *Preamble, StringRef Contents, Position Pos,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+ 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,
@@ -1623,9 +1570,9 @@ codeComplete(PathRef FileName, const tooling::CompileCommand &Command,
SignatureHelp signatureHelp(PathRef FileName,
const tooling::CompileCommand &Command,
- const PreambleData *Preamble, StringRef Contents,
- Position Pos,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+ const PreambleData *Preamble,
+ llvm::StringRef Contents, Position Pos,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
std::shared_ptr<PCHContainerOperations> PCHs,
const SymbolIndex *Index) {
SignatureHelp Result;
@@ -1670,12 +1617,12 @@ CompletionItem CodeCompletion::render(const CodeCompleteOptions &Opts) const {
LSP.label = ((InsertInclude && InsertInclude->Insertion)
? Opts.IncludeIndicator.Insert
: Opts.IncludeIndicator.NoInsert) +
- (Opts.ShowOrigins ? "[" + to_string(Origin) + "]" : "") +
+ (Opts.ShowOrigins ? "[" + llvm::to_string(Origin) + "]" : "") +
RequiredQualifier + Name + Signature;
LSP.kind = Kind;
- LSP.detail =
- BundleSize > 1 ? formatv("[{0} overloads]", BundleSize) : ReturnType;
+ LSP.detail = BundleSize > 1 ? llvm::formatv("[{0} overloads]", BundleSize)
+ : ReturnType;
LSP.deprecated = Deprecated;
if (InsertInclude)
LSP.detail += "\n" + InsertInclude->Header;
@@ -1691,7 +1638,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 {
@@ -1712,12 +1659,13 @@ CompletionItem CodeCompletion::render(const CodeCompleteOptions &Opts) const {
return LSP;
}
-raw_ostream &operator<<(raw_ostream &OS, const CodeCompletion &C) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const CodeCompletion &C) {
// For now just lean on CompletionItem.
return OS << C.render(CodeCompleteOptions());
}
-raw_ostream &operator<<(raw_ostream &OS, const CodeCompleteResult &R) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const CodeCompleteResult &R) {
OS << "CodeCompleteResult: " << R.Completions.size() << (R.HasMore ? "+" : "")
<< " (" << getCompletionKindString(R.Context) << ")"
<< " items:\n";
diff --git a/clangd/CodeComplete.h b/clangd/CodeComplete.h
index 4d324142..08151379 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clangd/CodeCompletionStrings.cpp b/clangd/CodeCompletionStrings.cpp
index f7e31619..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
//
//===----------------------------------------------------------------------===//
@@ -14,17 +13,16 @@
#include "clang/Basic/SourceManager.h"
#include <utility>
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
bool isInformativeQualifierChunk(CodeCompletionString::Chunk const &Chunk) {
return Chunk.Kind == CodeCompletionString::CK_Informative &&
- StringRef(Chunk.Text).endswith("::");
+ llvm::StringRef(Chunk.Text).endswith("::");
}
-void appendEscapeSnippet(const StringRef Text, std::string *Out) {
+void appendEscapeSnippet(const llvm::StringRef Text, std::string *Out) {
for (const auto Character : Text) {
if (Character == '$' || Character == '}' || Character == '\\')
Out->push_back('\\');
@@ -32,13 +30,13 @@ void appendEscapeSnippet(const StringRef Text, std::string *Out) {
}
}
-bool looksLikeDocComment(StringRef CommentText) {
+bool looksLikeDocComment(llvm::StringRef CommentText) {
// We don't report comments that only contain "special" chars.
// This avoids reporting various delimiters, like:
// =================
// -----------------
// *****************
- return CommentText.find_first_not_of("/*-= \t\r\n") != StringRef::npos;
+ return CommentText.find_first_not_of("/*-= \t\r\n") != llvm::StringRef::npos;
}
} // namespace
@@ -69,7 +67,8 @@ std::string getDeclComment(const ASTContext &Ctx, const NamedDecl &Decl) {
// Sanity check that the comment does not come from the PCH. We choose to not
// write them into PCH, because they are racy and slow to load.
assert(!Ctx.getSourceManager().isLoadedSourceLocation(RC->getBeginLoc()));
- std::string Doc = RC->getFormattedText(Ctx.getSourceManager(), Ctx.getDiagnostics());
+ std::string Doc =
+ RC->getFormattedText(Ctx.getSourceManager(), Ctx.getDiagnostics());
return looksLikeDocComment(Doc) ? Doc : "";
}
@@ -96,12 +95,12 @@ void getSignature(const CodeCompletionString &CCS, std::string *Signature,
// treat them carefully. For Objective-C methods, all typed-text chunks
// will end in ':' (unless there are no arguments, in which case we
// can safely treat them as C++).
- if (!StringRef(Chunk.Text).endswith(":")) { // Treat as C++.
+ if (!llvm::StringRef(Chunk.Text).endswith(":")) { // Treat as C++.
if (RequiredQualifiers)
*RequiredQualifiers = std::move(*Signature);
Signature->clear();
Snippet->clear();
- } else { // Objective-C method with args.
+ } else { // Objective-C method with args.
// If this is the first TypedText to the Objective-C method, discard any
// text that we've previously seen (such as previous parameter selector,
// which will be marked as Informative text).
@@ -111,7 +110,7 @@ void getSignature(const CodeCompletionString &CCS, std::string *Signature,
if (!HadObjCArguments) {
HadObjCArguments = true;
Signature->clear();
- } else { // Subsequent argument, considered part of snippet/signature.
+ } else { // Subsequent argument, considered part of snippet/signature.
*Signature += Chunk.Text;
*Snippet += Chunk.Text;
}
@@ -170,7 +169,7 @@ void getSignature(const CodeCompletionString &CCS, std::string *Signature,
}
std::string formatDocumentation(const CodeCompletionString &CCS,
- StringRef DocComment) {
+ llvm::StringRef DocComment) {
// Things like __attribute__((nonnull(1,3))) and [[noreturn]]. Present this
// information in the documentation field.
std::string Result;
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 011841c4..1eecce98 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
//
//===----------------------------------------------------------------------===//
@@ -14,21 +13,20 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
-using namespace llvm;
namespace clang {
namespace clangd {
void IgnoreDiagnostics::log(DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic &Info) {
// FIXME: format lazily, in case vlog is off.
- SmallString<64> Message;
+ llvm::SmallString<64> Message;
Info.FormatDiagnostic(Message);
- SmallString<64> Location;
+ llvm::SmallString<64> Location;
if (Info.hasSourceManager() && Info.getLocation().isValid()) {
auto &SourceMgr = Info.getSourceManager();
auto Loc = SourceMgr.getFileLoc(Info.getLocation());
- raw_svector_ostream OS(Location);
+ llvm::raw_svector_ostream OS(Location);
Loc.print(OS, SourceMgr);
OS << ":";
}
@@ -41,11 +39,41 @@ void IgnoreDiagnostics::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
IgnoreDiagnostics::log(DiagLevel, Info);
}
-std::unique_ptr<CompilerInstance> prepareCompilerInstance(
- std::unique_ptr<clang::CompilerInvocation> CI,
- const PrecompiledPreamble *Preamble, std::unique_ptr<MemoryBuffer> Buffer,
- std::shared_ptr<PCHContainerOperations> PCHs,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS, DiagnosticConsumer &DiagsClient) {
+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");
assert(!CI->getPreprocessorOpts().RetainRemappedFileBuffers &&
"Setting RetainRemappedFileBuffers to true will cause a memory leak "
diff --git a/clangd/Compiler.h b/clangd/Compiler.h
index 7a3c43d6..9466d8e2 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 "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
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 a8bfa29e..83876217 100644
--- a/clangd/Diagnostics.cpp
+++ b/clangd/Diagnostics.cpp
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
@@ -17,7 +16,6 @@
#include "llvm/Support/Path.h"
#include <algorithm>
-using namespace llvm;
namespace clang {
namespace clangd {
@@ -57,7 +55,7 @@ Range diagnosticRange(const clang::Diagnostic &D, const LangOptions &L) {
if (locationInRange(Loc, R, M))
return halfOpenToRange(M, R);
}
- Optional<Range> FallbackRange;
+ llvm::Optional<Range> FallbackRange;
// The range may be given as a fixit hint instead.
for (const auto &F : D.getFixItHints()) {
auto R = Lexer::makeFileCharRange(F.RemoveRange, M, L);
@@ -93,7 +91,7 @@ bool isNote(DiagnosticsEngine::Level L) {
return L == DiagnosticsEngine::Note || L == DiagnosticsEngine::Remark;
}
-StringRef diagLeveltoString(DiagnosticsEngine::Level Lvl) {
+llvm::StringRef diagLeveltoString(DiagnosticsEngine::Level Lvl) {
switch (Lvl) {
case DiagnosticsEngine::Ignored:
return "ignored";
@@ -122,12 +120,12 @@ StringRef diagLeveltoString(DiagnosticsEngine::Level Lvl) {
///
/// dir1/dir2/dir3/../../dir4/header.h:12:23
/// error: undeclared identifier
-void printDiag(raw_string_ostream &OS, const DiagBase &D) {
+void printDiag(llvm::raw_string_ostream &OS, const DiagBase &D) {
if (D.InsideMainFile) {
// Paths to main files are often taken from compile_command.json, where they
// are typically absolute. To reduce noise we print only basename for them,
// it should not be confusing and saves space.
- OS << sys::path::filename(D.File) << ":";
+ OS << llvm::sys::path::filename(D.File) << ":";
} else {
OS << D.File << ":";
}
@@ -147,7 +145,7 @@ void printDiag(raw_string_ostream &OS, const DiagBase &D) {
/// Capitalizes the first word in the diagnostic's message.
std::string capitalize(std::string Message) {
if (!Message.empty())
- Message[0] = toUpper(Message[0]);
+ Message[0] = llvm::toUpper(Message[0]);
return Message;
}
@@ -165,8 +163,10 @@ std::string capitalize(std::string Message) {
/// note: candidate function not viable: requires 3 arguments
std::string mainMessage(const Diag &D) {
std::string Result;
- raw_string_ostream OS(Result);
+ llvm::raw_string_ostream OS(Result);
OS << D.Message;
+ if (!D.Fixes.empty())
+ OS << " (" << (D.Fixes.size() > 1 ? "fixes" : "fix") << " available)";
for (auto &Note : D.Notes) {
OS << "\n\n";
printDiag(OS, Note);
@@ -180,7 +180,7 @@ std::string mainMessage(const Diag &D) {
/// for the user to understand the note.
std::string noteMessage(const Diag &Main, const DiagBase &Note) {
std::string Result;
- raw_string_ostream OS(Result);
+ llvm::raw_string_ostream OS(Result);
OS << Note.Message;
OS << "\n\n";
printDiag(OS, Main);
@@ -189,7 +189,7 @@ std::string noteMessage(const Diag &Main, const DiagBase &Note) {
}
} // namespace
-raw_ostream &operator<<(raw_ostream &OS, const DiagBase &D) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const DiagBase &D) {
OS << "[";
if (!D.InsideMainFile)
OS << D.File << ":";
@@ -198,7 +198,7 @@ raw_ostream &operator<<(raw_ostream &OS, const DiagBase &D) {
return OS << D.Message;
}
-raw_ostream &operator<<(raw_ostream &OS, const Fix &F) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Fix &F) {
OS << F.Message << " {";
const char *Sep = "";
for (const auto &Edit : F.Edits) {
@@ -208,7 +208,7 @@ raw_ostream &operator<<(raw_ostream &OS, const Fix &F) {
return OS << "}";
}
-raw_ostream &operator<<(raw_ostream &OS, const Diag &D) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diag &D) {
OS << static_cast<const DiagBase &>(D);
if (!D.Notes.empty()) {
OS << ", notes: {";
@@ -242,7 +242,7 @@ CodeAction toCodeAction(const Fix &F, const URIForFile &File) {
void toLSPDiags(
const Diag &D, const URIForFile &File, const ClangdDiagnosticOptions &Opts,
- function_ref<void(clangd::Diagnostic, ArrayRef<Fix>)> OutFn) {
+ llvm::function_ref<void(clangd::Diagnostic, llvm::ArrayRef<Fix>)> OutFn) {
auto FillBasicFields = [](const DiagBase &D) -> clangd::Diagnostic {
clangd::Diagnostic Res;
Res.range = D.Range;
@@ -269,7 +269,7 @@ void toLSPDiags(
continue;
clangd::Diagnostic Res = FillBasicFields(Note);
Res.message = noteMessage(D, Note);
- OutFn(std::move(Res), ArrayRef<Fix>());
+ OutFn(std::move(Res), llvm::ArrayRef<Fix>());
}
}
@@ -315,7 +315,7 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
auto FillDiagBase = [&](DiagBase &D) {
D.Range = diagnosticRange(Info, *LangOpts);
- SmallString<64> Message;
+ llvm::SmallString<64> Message;
Info.FormatDiagnostic(Message);
D.Message = Message.str();
D.InsideMainFile = InsideMainFile;
@@ -333,7 +333,7 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
if (!InsideMainFile)
return false;
- SmallVector<TextEdit, 1> Edits;
+ llvm::SmallVector<TextEdit, 1> Edits;
for (auto &FixIt : Info.getFixItHints()) {
if (!isInsideMainFile(FixIt.RemoveRange.getBegin(),
Info.getSourceManager()))
@@ -341,16 +341,16 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
Edits.push_back(toTextEdit(FixIt, Info.getSourceManager(), *LangOpts));
}
- SmallString<64> Message;
+ llvm::SmallString<64> Message;
// If requested and possible, create a message like "change 'foo' to 'bar'".
if (SyntheticMessage && Info.getNumFixItHints() == 1) {
const auto &FixIt = Info.getFixItHint(0);
bool Invalid = false;
- StringRef Remove = Lexer::getSourceText(
+ llvm::StringRef Remove = Lexer::getSourceText(
FixIt.RemoveRange, Info.getSourceManager(), *LangOpts, &Invalid);
- StringRef Insert = FixIt.CodeToInsert;
+ llvm::StringRef Insert = FixIt.CodeToInsert;
if (!Invalid) {
- raw_svector_ostream M(Message);
+ llvm::raw_svector_ostream M(Message);
if (!Remove.empty() && !Insert.empty())
M << "change '" << Remove << "' to '" << Insert << "'";
else if (!Remove.empty())
@@ -376,6 +376,11 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
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) {
@@ -405,8 +410,8 @@ void StoreDiags::flushLastDiag() {
if (mentionsMainFile(*LastDiag))
Output.push_back(std::move(*LastDiag));
else
- log("Dropped diagnostic outside main file: {0}: {1}", LastDiag->File,
- LastDiag->Message);
+ vlog("Dropped diagnostic outside main file: {0}: {1}", LastDiag->File,
+ LastDiag->Message);
LastDiag.reset();
}
diff --git a/clangd/Diagnostics.h b/clangd/Diagnostics.h
index 6318e88f..9130ad56 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
//
//===----------------------------------------------------------------------===//
@@ -100,9 +99,15 @@ public:
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;
diff --git a/clangd/DraftStore.cpp b/clangd/DraftStore.cpp
index b5bcda81..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
//
//===----------------------------------------------------------------------===//
@@ -11,11 +10,10 @@
#include "SourceCode.h"
#include "llvm/Support/Errc.h"
-using namespace llvm;
namespace clang {
namespace clangd {
-Optional<std::string> DraftStore::getDraft(PathRef File) const {
+llvm::Optional<std::string> DraftStore::getDraft(PathRef File) const {
std::lock_guard<std::mutex> Lock(Mutex);
auto It = Drafts.find(File);
@@ -35,20 +33,19 @@ std::vector<Path> DraftStore::getActiveFiles() const {
return ResultVector;
}
-void DraftStore::addDraft(PathRef File, StringRef Contents) {
+void DraftStore::addDraft(PathRef File, llvm::StringRef Contents) {
std::lock_guard<std::mutex> Lock(Mutex);
Drafts[File] = Contents;
}
-Expected<std::string>
-DraftStore::updateDraft(PathRef File,
- ArrayRef<TextDocumentContentChangeEvent> Changes) {
+llvm::Expected<std::string> DraftStore::updateDraft(
+ PathRef File, llvm::ArrayRef<TextDocumentContentChangeEvent> Changes) {
std::lock_guard<std::mutex> Lock(Mutex);
auto EntryIt = Drafts.find(File);
if (EntryIt == Drafts.end()) {
- return make_error<StringError>(
+ return llvm::make_error<llvm::StringError>(
"Trying to do incremental update on non-added document: " + File,
llvm::errc::invalid_argument);
}
@@ -62,19 +59,21 @@ DraftStore::updateDraft(PathRef File,
}
const Position &Start = Change.range->start;
- Expected<size_t> StartIndex = positionToOffset(Contents, Start, false);
+ llvm::Expected<size_t> StartIndex =
+ positionToOffset(Contents, Start, false);
if (!StartIndex)
return StartIndex.takeError();
const Position &End = Change.range->end;
- Expected<size_t> EndIndex = positionToOffset(Contents, End, false);
+ llvm::Expected<size_t> EndIndex = positionToOffset(Contents, End, false);
if (!EndIndex)
return EndIndex.takeError();
if (*EndIndex < *StartIndex)
- return make_error<StringError>(
- formatv("Range's end position ({0}) is before start position ({1})",
- End, Start),
+ return llvm::make_error<llvm::StringError>(
+ llvm::formatv(
+ "Range's end position ({0}) is before start position ({1})", End,
+ Start),
llvm::errc::invalid_argument);
// Since the range length between two LSP positions is dependent on the
@@ -88,10 +87,10 @@ DraftStore::updateDraft(PathRef File,
lspLength(Contents.substr(*StartIndex, *EndIndex - *StartIndex));
if (Change.rangeLength && ComputedRangeLength != *Change.rangeLength)
- return make_error<StringError>(
- formatv("Change's rangeLength ({0}) doesn't match the "
- "computed range length ({1}).",
- *Change.rangeLength, *EndIndex - *StartIndex),
+ return llvm::make_error<llvm::StringError>(
+ llvm::formatv("Change's rangeLength ({0}) doesn't match the "
+ "computed range length ({1}).",
+ *Change.rangeLength, *EndIndex - *StartIndex),
llvm::errc::invalid_argument);
std::string NewContents;
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 5c9cec89..59d9e149 100644
--- a/clangd/ExpectedTypes.cpp
+++ b/clangd/ExpectedTypes.cpp
@@ -5,8 +5,6 @@
#include "clang/Sema/CodeCompleteConsumer.h"
#include "llvm/ADT/STLExtras.h"
-using namespace llvm;
-
namespace clang {
namespace clangd {
namespace {
@@ -33,11 +31,14 @@ static const Type *toEquivClass(ASTContext &Ctx, QualType T) {
return T.getTypePtr();
}
-static Optional<QualType> typeOfCompletion(const CodeCompletionResult &R) {
+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.
@@ -49,13 +50,13 @@ static Optional<QualType> typeOfCompletion(const CodeCompletionResult &R) {
}
} // namespace
-Optional<OpaqueType> OpaqueType::encode(ASTContext &Ctx, QualType T) {
+llvm::Optional<OpaqueType> OpaqueType::encode(ASTContext &Ctx, QualType T) {
if (T.isNull())
return None;
const Type *C = toEquivClass(Ctx, T);
if (!C)
return None;
- SmallString<128> Encoded;
+ llvm::SmallString<128> Encoded;
if (index::generateUSRForType(QualType(C, 0), Ctx, Encoded))
return None;
return OpaqueType(Encoded.str());
@@ -63,11 +64,12 @@ Optional<OpaqueType> OpaqueType::encode(ASTContext &Ctx, QualType T) {
OpaqueType::OpaqueType(std::string Data) : Data(std::move(Data)) {}
-Optional<OpaqueType> OpaqueType::fromType(ASTContext &Ctx, QualType Type) {
+llvm::Optional<OpaqueType> OpaqueType::fromType(ASTContext &Ctx,
+ QualType Type) {
return encode(Ctx, Type);
}
-Optional<OpaqueType>
+llvm::Optional<OpaqueType>
OpaqueType::fromCompletionResult(ASTContext &Ctx,
const CodeCompletionResult &R) {
auto T = typeOfCompletion(R);
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 e588e00b..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
//
//===----------------------------------------------------------------------===//
@@ -12,17 +11,17 @@
#include "llvm/ADT/None.h"
#include "llvm/Support/Path.h"
-using namespace llvm;
namespace clang {
namespace clangd {
-PreambleFileStatusCache::PreambleFileStatusCache(StringRef MainFilePath)
+PreambleFileStatusCache::PreambleFileStatusCache(llvm::StringRef MainFilePath)
: MainFilePath(MainFilePath) {
- assert(sys::path::is_absolute(MainFilePath));
+ assert(llvm::sys::path::is_absolute(MainFilePath));
}
-void PreambleFileStatusCache::update(const vfs::FileSystem &FS, vfs::Status S) {
- SmallString<32> PathStore(S.getName());
+void PreambleFileStatusCache::update(const llvm::vfs::FileSystem &FS,
+ llvm::vfs::Status S) {
+ llvm::SmallString<32> PathStore(S.getName());
if (FS.makeAbsolute(PathStore))
return;
// Do not cache status for the main file.
@@ -32,25 +31,27 @@ void PreambleFileStatusCache::update(const vfs::FileSystem &FS, vfs::Status S) {
StatCache.insert({PathStore, std::move(S)});
}
-Optional<vfs::Status> PreambleFileStatusCache::lookup(StringRef File) const {
+llvm::Optional<llvm::vfs::Status>
+PreambleFileStatusCache::lookup(llvm::StringRef File) const {
auto I = StatCache.find(File);
if (I != StatCache.end())
return I->getValue();
return None;
}
-IntrusiveRefCntPtr<vfs::FileSystem> PreambleFileStatusCache::getProducingFS(
- IntrusiveRefCntPtr<vfs::FileSystem> FS) {
+llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+PreambleFileStatusCache::getProducingFS(
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
// This invalidates old status in cache if files are re-`open()`ed or
// re-`stat()`ed in case file status has changed during preamble build.
- class CollectFS : public vfs::ProxyFileSystem {
+ class CollectFS : public llvm::vfs::ProxyFileSystem {
public:
- CollectFS(IntrusiveRefCntPtr<vfs::FileSystem> FS,
+ CollectFS(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
PreambleFileStatusCache &StatCache)
: ProxyFileSystem(std::move(FS)), StatCache(StatCache) {}
- ErrorOr<std::unique_ptr<vfs::File>>
- openFileForRead(const Twine &Path) override {
+ llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
+ openFileForRead(const llvm::Twine &Path) override {
auto File = getUnderlyingFS().openFileForRead(Path);
if (!File || !*File)
return File;
@@ -64,7 +65,7 @@ IntrusiveRefCntPtr<vfs::FileSystem> PreambleFileStatusCache::getProducingFS(
return File;
}
- ErrorOr<vfs::Status> status(const Twine &Path) override {
+ llvm::ErrorOr<llvm::vfs::Status> status(const llvm::Twine &Path) override {
auto S = getUnderlyingFS().status(Path);
if (S)
StatCache.update(getUnderlyingFS(), *S);
@@ -74,18 +75,20 @@ IntrusiveRefCntPtr<vfs::FileSystem> PreambleFileStatusCache::getProducingFS(
private:
PreambleFileStatusCache &StatCache;
};
- return IntrusiveRefCntPtr<CollectFS>(new CollectFS(std::move(FS), *this));
+ return llvm::IntrusiveRefCntPtr<CollectFS>(
+ new CollectFS(std::move(FS), *this));
}
-IntrusiveRefCntPtr<vfs::FileSystem> PreambleFileStatusCache::getConsumingFS(
- IntrusiveRefCntPtr<vfs::FileSystem> FS) const {
- class CacheVFS : public vfs::ProxyFileSystem {
+llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+PreambleFileStatusCache::getConsumingFS(
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) const {
+ class CacheVFS : public llvm::vfs::ProxyFileSystem {
public:
- CacheVFS(IntrusiveRefCntPtr<vfs::FileSystem> FS,
+ CacheVFS(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
const PreambleFileStatusCache &StatCache)
: ProxyFileSystem(std::move(FS)), StatCache(StatCache) {}
- ErrorOr<vfs::Status> status(const Twine &Path) override {
+ llvm::ErrorOr<llvm::vfs::Status> status(const llvm::Twine &Path) override {
if (auto S = StatCache.lookup(Path.str()))
return *S;
return getUnderlyingFS().status(Path);
@@ -94,7 +97,7 @@ IntrusiveRefCntPtr<vfs::FileSystem> PreambleFileStatusCache::getConsumingFS(
private:
const PreambleFileStatusCache &StatCache;
};
- return IntrusiveRefCntPtr<CacheVFS>(new CacheVFS(std::move(FS), *this));
+ return llvm::IntrusiveRefCntPtr<CacheVFS>(new CacheVFS(std::move(FS), *this));
}
} // namespace clangd
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 ccb64c56..be915740 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
//
//===----------------------------------------------------------------------===//
@@ -15,8 +14,6 @@
#include "llvm/Support/VirtualFileSystem.h"
#include <memory>
-using namespace llvm;
-
namespace clang {
namespace clangd {
@@ -28,9 +25,9 @@ public:
explicit VolatileFileSystem(llvm::IntrusiveRefCntPtr<FileSystem> FS)
: ProxyFileSystem(std::move(FS)) {}
- llvm::ErrorOr<std::unique_ptr<vfs::File>>
- openFileForRead(const Twine &InPath) override {
- SmallString<128> Path;
+ llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
+ openFileForRead(const llvm::Twine &InPath) override {
+ llvm::SmallString<128> Path;
InPath.toVector(Path);
auto File = getUnderlyingFS().openFileForRead(Path);
@@ -38,29 +35,30 @@ public:
return File;
// Try to guess preamble files, they can be memory-mapped even on Windows as
// clangd has exclusive access to those.
- StringRef FileName = llvm::sys::path::filename(Path);
+ llvm::StringRef FileName = llvm::sys::path::filename(Path);
if (FileName.startswith("preamble-") && FileName.endswith(".pch"))
return File;
- return std::unique_ptr<VolatileFile>(
- new VolatileFile(std::move(*File)));
+ return std::unique_ptr<VolatileFile>(new VolatileFile(std::move(*File)));
}
private:
- class VolatileFile : public vfs::File {
+ class VolatileFile : public llvm::vfs::File {
public:
- VolatileFile(std::unique_ptr<vfs::File> Wrapped)
+ VolatileFile(std::unique_ptr<llvm::vfs::File> Wrapped)
: Wrapped(std::move(Wrapped)) {
assert(this->Wrapped);
}
virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
- getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
- bool /*IsVolatile*/) override {
+ getBuffer(const llvm::Twine &Name, int64_t FileSize,
+ bool RequiresNullTerminator, bool /*IsVolatile*/) override {
return Wrapped->getBuffer(Name, FileSize, RequiresNullTerminator,
/*IsVolatile=*/true);
}
- llvm::ErrorOr<vfs::Status> status() override { return Wrapped->status(); }
+ llvm::ErrorOr<llvm::vfs::Status> status() override {
+ return Wrapped->status();
+ }
llvm::ErrorOr<std::string> getName() override { return Wrapped->getName(); }
std::error_code close() override { return Wrapped->close(); }
@@ -76,9 +74,9 @@ 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(vfs::getRealFileSystem());
+ return new VolatileFileSystem(llvm::vfs::getRealFileSystem());
#else
- return vfs::getRealFileSystem();
+ return llvm::vfs::getRealFileSystem();
#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/Features.inc.in b/clangd/Features.inc.in
new file mode 100644
index 00000000..da75aa67
--- /dev/null
+++ b/clangd/Features.inc.in
@@ -0,0 +1 @@
+#define CLANGD_BUILD_XPC @CLANGD_BUILD_XPC@
diff --git a/clangd/FileDistance.cpp b/clangd/FileDistance.cpp
index 6bd73e52..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
//
//===----------------------------------------------------------------------===//
//
@@ -36,7 +35,6 @@
#include "llvm/ADT/STLExtras.h"
#include <queue>
-using namespace llvm;
namespace clang {
namespace clangd {
@@ -45,21 +43,23 @@ namespace clangd {
// C:\foo\bar --> /c:/foo/bar
// /foo/ --> /foo
// a/b/c --> /a/b/c
-static SmallString<128> canonicalize(StringRef Path) {
- SmallString<128> Result = Path.rtrim('/');
- native(Result, sys::path::Style::posix);
+static llvm::SmallString<128> canonicalize(llvm::StringRef Path) {
+ llvm::SmallString<128> Result = Path.rtrim('/');
+ native(Result, llvm::sys::path::Style::posix);
if (Result.empty() || Result.front() != '/')
Result.insert(Result.begin(), '/');
return Result;
}
constexpr const unsigned FileDistance::Unreachable;
-const hash_code FileDistance::RootHash = hash_value(StringRef("/"));
+const llvm::hash_code FileDistance::RootHash =
+ llvm::hash_value(llvm::StringRef("/"));
-FileDistance::FileDistance(StringMap<SourceParams> Sources,
+FileDistance::FileDistance(llvm::StringMap<SourceParams> Sources,
const FileDistanceOptions &Opts)
: Opts(Opts) {
- DenseMap<hash_code, SmallVector<hash_code, 4>> DownEdges;
+ llvm::DenseMap<llvm::hash_code, llvm::SmallVector<llvm::hash_code, 4>>
+ DownEdges;
// Compute the best distance following only up edges.
// Keep track of down edges, in case we can use them to improve on this.
for (const auto &S : Sources) {
@@ -67,13 +67,13 @@ FileDistance::FileDistance(StringMap<SourceParams> Sources,
dlog("Source {0} = {1}, MaxUp = {2}", Canonical, S.second.Cost,
S.second.MaxUpTraversals);
// Walk up to ancestors of this source, assigning cost.
- StringRef Rest = Canonical;
- hash_code Hash = hash_value(Rest);
+ llvm::StringRef Rest = Canonical;
+ llvm::hash_code Hash = llvm::hash_value(Rest);
for (unsigned I = 0; !Rest.empty(); ++I) {
- Rest = parent_path(Rest, sys::path::Style::posix);
- auto NextHash = hash_value(Rest);
+ Rest = parent_path(Rest, llvm::sys::path::Style::posix);
+ auto NextHash = llvm::hash_value(Rest);
auto &Down = DownEdges[NextHash];
- if (!is_contained(Down, Hash))
+ if (!llvm::is_contained(Down, Hash))
Down.push_back(Hash);
// We can't just break after MaxUpTraversals, must still set DownEdges.
if (I > S.getValue().MaxUpTraversals) {
@@ -96,8 +96,8 @@ FileDistance::FileDistance(StringMap<SourceParams> Sources,
}
// Now propagate scores parent -> child if that's an improvement.
// BFS ensures we propagate down chains (must visit parents before children).
- std::queue<hash_code> Next;
- for (auto Child : DownEdges.lookup(hash_value(StringRef(""))))
+ std::queue<llvm::hash_code> Next;
+ for (auto Child : DownEdges.lookup(llvm::hash_value(llvm::StringRef(""))))
Next.push(Child);
while (!Next.empty()) {
auto Parent = Next.front();
@@ -115,14 +115,14 @@ FileDistance::FileDistance(StringMap<SourceParams> Sources,
}
}
-unsigned FileDistance::distance(StringRef Path) {
+unsigned FileDistance::distance(llvm::StringRef Path) {
auto Canonical = canonicalize(Path);
unsigned Cost = Unreachable;
- SmallVector<hash_code, 16> Ancestors;
+ llvm::SmallVector<llvm::hash_code, 16> Ancestors;
// Walk up ancestors until we find a path we know the distance for.
- for (StringRef Rest = Canonical; !Rest.empty();
- Rest = parent_path(Rest, sys::path::Style::posix)) {
- auto Hash = hash_value(Rest);
+ for (llvm::StringRef Rest = Canonical; !Rest.empty();
+ Rest = parent_path(Rest, llvm::sys::path::Style::posix)) {
+ auto Hash = llvm::hash_value(Rest);
if (Hash == RootHash && !Ancestors.empty() &&
!Opts.AllowDownTraversalFromRoot) {
Cost = Unreachable;
@@ -137,7 +137,7 @@ unsigned FileDistance::distance(StringRef Path) {
}
// Now we know the costs for (known node, queried node].
// Fill these in, walking down the directory tree.
- for (hash_code Hash : reverse(Ancestors)) {
+ for (llvm::hash_code Hash : llvm::reverse(Ancestors)) {
if (Cost != Unreachable)
Cost += Opts.DownCost;
Cache.try_emplace(Hash, Cost);
@@ -146,8 +146,8 @@ unsigned FileDistance::distance(StringRef Path) {
return Cost;
}
-unsigned URIDistance::distance(StringRef URI) {
- auto R = Cache.try_emplace(hash_value(URI), FileDistance::Unreachable);
+unsigned URIDistance::distance(llvm::StringRef URI) {
+ auto R = Cache.try_emplace(llvm::hash_value(URI), FileDistance::Unreachable);
if (!R.second)
return R.first->getSecond();
if (auto U = clangd::URI::parse(URI)) {
@@ -159,15 +159,15 @@ unsigned URIDistance::distance(StringRef URI) {
return R.first->second;
}
-FileDistance &URIDistance::forScheme(StringRef Scheme) {
+FileDistance &URIDistance::forScheme(llvm::StringRef Scheme) {
auto &Delegate = ByScheme[Scheme];
if (!Delegate) {
- StringMap<SourceParams> SchemeSources;
+ llvm::StringMap<SourceParams> SchemeSources;
for (const auto &Source : Sources) {
if (auto U = clangd::URI::create(Source.getKey(), Scheme))
SchemeSources.try_emplace(U->body(), Source.getValue());
else
- consumeError(U.takeError());
+ llvm::consumeError(U.takeError());
}
dlog("FileDistance for scheme {0}: {1}/{2} sources", Scheme,
SchemeSources.size(), Sources.size());
@@ -176,21 +176,23 @@ FileDistance &URIDistance::forScheme(StringRef Scheme) {
return *Delegate;
}
-static std::pair<std::string, int> scopeToPath(StringRef Scope) {
- SmallVector<StringRef, 4> Split;
+static std::pair<std::string, int> scopeToPath(llvm::StringRef Scope) {
+ llvm::SmallVector<llvm::StringRef, 4> Split;
Scope.split(Split, "::", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
- return {"/" + join(Split, "/"), Split.size()};
+ return {"/" + llvm::join(Split, "/"), Split.size()};
}
-static FileDistance createScopeFileDistance(ArrayRef<std::string> QueryScopes) {
+static FileDistance
+createScopeFileDistance(llvm::ArrayRef<std::string> QueryScopes) {
FileDistanceOptions Opts;
Opts.UpCost = 2;
Opts.DownCost = 4;
Opts.AllowDownTraversalFromRoot = false;
- StringMap<SourceParams> Sources;
- StringRef Preferred = QueryScopes.empty() ? "" : QueryScopes.front().c_str();
- for (StringRef S : QueryScopes) {
+ llvm::StringMap<SourceParams> Sources;
+ llvm::StringRef Preferred =
+ QueryScopes.empty() ? "" : QueryScopes.front().c_str();
+ for (llvm::StringRef S : QueryScopes) {
SourceParams Param;
// Penalize the global scope even it's preferred, as all projects can define
// symbols in it, and there is pattern where using-namespace is used in
@@ -209,10 +211,10 @@ static FileDistance createScopeFileDistance(ArrayRef<std::string> QueryScopes) {
return FileDistance(Sources, Opts);
}
-ScopeDistance::ScopeDistance(ArrayRef<std::string> QueryScopes)
+ScopeDistance::ScopeDistance(llvm::ArrayRef<std::string> QueryScopes)
: Distance(createScopeFileDistance(QueryScopes)) {}
-unsigned ScopeDistance::distance(StringRef SymbolScope) {
+unsigned ScopeDistance::distance(llvm::StringRef SymbolScope) {
return Distance.distance(scopeToPath(SymbolScope).first);
}
diff --git a/clangd/FileDistance.h b/clangd/FileDistance.h
index d60afa28..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
//
//===----------------------------------------------------------------------===//
//
@@ -54,9 +53,9 @@ namespace clang {
namespace clangd {
struct FileDistanceOptions {
- unsigned UpCost = 2; // |foo/bar.h -> foo|
- unsigned DownCost = 1; // |foo -> foo/bar.h|
- unsigned IncludeCost = 2; // |foo.cc -> included_header.h|
+ unsigned UpCost = 2; // |foo/bar.h -> foo|
+ unsigned DownCost = 1; // |foo -> foo/bar.h|
+ unsigned IncludeCost = 2; // |foo.cc -> included_header.h|
bool AllowDownTraversalFromRoot = true; // | / -> /a |
};
diff --git a/clangd/FindSymbols.cpp b/clangd/FindSymbols.cpp
index aca17f9e..00819550 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"
@@ -25,7 +24,6 @@
#define DEBUG_TYPE "FindSymbols"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -100,9 +98,9 @@ struct ScoredSymbolGreater {
} // namespace
-Expected<std::vector<SymbolInformation>>
-getWorkspaceSymbols(StringRef Query, int Limit, const SymbolIndex *const Index,
- StringRef HintPath) {
+llvm::Expected<std::vector<SymbolInformation>>
+getWorkspaceSymbols(llvm::StringRef Query, int Limit,
+ const SymbolIndex *const Index, llvm::StringRef HintPath) {
std::vector<SymbolInformation> Result;
if (Query.empty() || !Index)
return Result;
@@ -153,7 +151,7 @@ getWorkspaceSymbols(StringRef Query, int Limit, const SymbolIndex *const Index,
L.range = {Start, End};
SymbolKind SK = indexSymbolKindToSymbolKind(Sym.SymInfo.Kind);
std::string Scope = Sym.Scope;
- StringRef ScopeRef = Scope;
+ llvm::StringRef ScopeRef = Scope;
ScopeRef.consume_back("::");
SymbolInformation Info = {Sym.Name, SK, L, ScopeRef};
@@ -190,7 +188,7 @@ llvm::Optional<DocumentSymbol> declToSym(ASTContext &Ctx, const NamedDecl &ND) {
// 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 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;
diff --git a/clangd/FindSymbols.h b/clangd/FindSymbols.h
index a9c8c998..78bdbd33 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clangd/Function.h b/clangd/Function.h
index 52effe0d..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
//
//===----------------------------------------------------------------------===//
//
@@ -133,7 +132,6 @@ public:
std::lock_guard<std::recursive_mutex> Lock(ListenersMu);
Listeners.push_back({std::move(L), ++ListenerCount});
return Subscription(this, ListenerCount);
- ;
}
// Synchronously sends an event to all registered listeners.
diff --git a/clangd/FuzzyMatch.cpp b/clangd/FuzzyMatch.cpp
index c16712fa..bc613868 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
//
//===----------------------------------------------------------------------===//
//
@@ -60,7 +59,6 @@
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Format.h"
-using namespace llvm;
namespace clang {
namespace clangd {
@@ -75,7 +73,7 @@ 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.
-FuzzyMatcher::FuzzyMatcher(StringRef Pattern)
+FuzzyMatcher::FuzzyMatcher(llvm::StringRef Pattern)
: PatN(std::min<int>(MaxPat, Pattern.size())),
ScoreScale(PatN ? float{1} / (PerfectBonus * PatN) : 0), WordN(0) {
std::copy(Pattern.begin(), Pattern.begin() + PatN, Pat);
@@ -87,20 +85,20 @@ FuzzyMatcher::FuzzyMatcher(StringRef Pattern)
for (int W = 0; W < P; ++W)
for (Action A : {Miss, Match})
Scores[P][W][A] = {AwfulScore, Miss};
- PatTypeSet =
- calculateRoles(StringRef(Pat, PatN), makeMutableArrayRef(PatRole, PatN));
+ PatTypeSet = calculateRoles(llvm::StringRef(Pat, PatN),
+ llvm::makeMutableArrayRef(PatRole, PatN));
}
-Optional<float> FuzzyMatcher::match(StringRef Word) {
+llvm::Optional<float> FuzzyMatcher::match(llvm::StringRef Word) {
if (!(WordContainsPattern = init(Word)))
- return None;
+ return llvm::None;
if (!PatN)
return 1;
buildGraph();
auto Best = std::max(Scores[PatN][WordN][Miss].Score,
Scores[PatN][WordN][Match].Score);
if (isAwful(Best))
- return None;
+ return llvm::None;
float Score =
ScoreScale * std::min(PerfectBonus * PatN, std::max<int>(0, Best));
// If the pattern is as long as the word, we have an exact string match,
@@ -153,7 +151,8 @@ constexpr static uint8_t CharRoles[] = {
template <typename T> static T packedLookup(const uint8_t *Data, int I) {
return static_cast<T>((Data[I >> 2] >> ((I & 3) * 2)) & 3);
}
-CharTypeSet calculateRoles(StringRef Text, MutableArrayRef<CharRole> Roles) {
+CharTypeSet calculateRoles(llvm::StringRef Text,
+ llvm::MutableArrayRef<CharRole> Roles) {
assert(Text.size() == Roles.size());
if (Text.size() == 0)
return 0;
@@ -179,7 +178,7 @@ CharTypeSet calculateRoles(StringRef Text, MutableArrayRef<CharRole> Roles) {
// Sets up the data structures matching Word.
// Returns false if we can cheaply determine that no match is possible.
-bool FuzzyMatcher::init(StringRef NewWord) {
+bool FuzzyMatcher::init(llvm::StringRef NewWord) {
WordN = std::min<int>(MaxWord, NewWord.size());
if (PatN > WordN)
return false;
@@ -200,8 +199,8 @@ bool FuzzyMatcher::init(StringRef NewWord) {
// FIXME: some words are hard to tokenize algorithmically.
// e.g. vsprintf is V S Print F, and should match [pri] but not [int].
// We could add a tokenization dictionary for common stdlib names.
- WordTypeSet = calculateRoles(StringRef(Word, WordN),
- makeMutableArrayRef(WordRole, WordN));
+ WordTypeSet = calculateRoles(llvm::StringRef(Word, WordN),
+ llvm::makeMutableArrayRef(WordRole, WordN));
return true;
}
@@ -299,13 +298,13 @@ int FuzzyMatcher::matchBonus(int P, int W, Action Last) const {
return S;
}
-SmallString<256> FuzzyMatcher::dumpLast(raw_ostream &OS) const {
- SmallString<256> Result;
- OS << "=== Match \"" << StringRef(Word, WordN) << "\" against ["
- << StringRef(Pat, PatN) << "] ===\n";
+llvm::SmallString<256> FuzzyMatcher::dumpLast(llvm::raw_ostream &OS) const {
+ llvm::SmallString<256> Result;
+ OS << "=== Match \"" << llvm::StringRef(Word, WordN) << "\" against ["
+ << llvm::StringRef(Pat, PatN) << "] ===\n";
if (PatN == 0) {
OS << "Pattern is empty: perfect match.\n";
- return Result = StringRef(Word, WordN);
+ return Result = llvm::StringRef(Word, WordN);
}
if (WordN == 0) {
OS << "Word is empty: no match.\n";
@@ -349,28 +348,28 @@ SmallString<256> FuzzyMatcher::dumpLast(raw_ostream &OS) const {
if (A[WordN - 1] == Match)
Result.push_back(']');
- for (char C : StringRef(Word, WordN))
+ for (char C : llvm::StringRef(Word, WordN))
OS << " " << C << " ";
OS << "\n";
for (int I = 0, J = 0; I < WordN; I++)
OS << " " << (A[I] == Match ? Pat[J++] : ' ') << " ";
OS << "\n";
for (int I = 0; I < WordN; I++)
- OS << format("%2d ", S[I]);
+ OS << llvm::format("%2d ", S[I]);
OS << "\n";
OS << "\nSegmentation:";
- OS << "\n'" << StringRef(Word, WordN) << "'\n ";
+ OS << "\n'" << llvm::StringRef(Word, WordN) << "'\n ";
for (int I = 0; I < WordN; ++I)
OS << "?-+ "[static_cast<int>(WordRole[I])];
- OS << "\n[" << StringRef(Pat, PatN) << "]\n ";
+ OS << "\n[" << llvm::StringRef(Pat, PatN) << "]\n ";
for (int I = 0; I < PatN; ++I)
OS << "?-+ "[static_cast<int>(PatRole[I])];
OS << "\n";
OS << "\nScoring table (last-Miss, last-Match):\n";
OS << " | ";
- for (char C : StringRef(Word, WordN))
+ for (char C : llvm::StringRef(Word, WordN))
OS << " " << C << " ";
OS << "\n";
OS << "-+----" << std::string(WordN * 4, '-') << "\n";
@@ -379,8 +378,8 @@ SmallString<256> FuzzyMatcher::dumpLast(raw_ostream &OS) const {
OS << ((I && A == Miss) ? Pat[I - 1] : ' ') << "|";
for (int J = 0; J <= WordN; ++J) {
if (!isAwful(Scores[I][J][A].Score))
- OS << format("%3d%c", Scores[I][J][A].Score,
- Scores[I][J][A].Prev == Match ? '*' : ' ');
+ OS << llvm::format("%3d%c", Scores[I][J][A].Score,
+ Scores[I][J][A].Prev == Match ? '*' : ' ');
else
OS << " ";
}
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 055f92c4..a9161972 100644
--- a/clangd/GlobalCompilationDatabase.cpp
+++ b/clangd/GlobalCompilationDatabase.cpp
@@ -1,43 +1,77 @@
//===--- 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"
-using namespace llvm;
namespace clang {
namespace clangd {
+namespace {
+
+void adjustArguments(tooling::CompileCommand &Cmd,
+ llvm::StringRef ResourceDir) {
+ // Strip plugin related command line arguments. Clangd does
+ // not support plugins currently. Therefore it breaks if
+ // compiler tries to load plugins.
+ Cmd.CommandLine =
+ tooling::getStripPluginsAdjuster()(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;
+ std::string ClangdExecutable =
+ llvm::sys::fs::getMainExecutable("clangd", (void *)&Dummy);
+ SmallString<128> ClangPath;
+ ClangPath = llvm::sys::path::parent_path(ClangdExecutable);
+ llvm::sys::path::append(ClangPath, "clang");
+ return ClangPath.str();
+}
tooling::CompileCommand
GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
- std::vector<std::string> Argv = {"clang"};
+ std::vector<std::string> Argv = {getFallbackClangPath()};
// Clang treats .h files as C by default, resulting in unhelpful diagnostics.
// Parsing as Objective C++ is friendly to more cases.
- if (sys::path::extension(File) == ".h")
+ if (llvm::sys::path::extension(File) == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(File);
- return tooling::CompileCommand(sys::path::parent_path(File),
- sys::path::filename(File), std::move(Argv),
+ return tooling::CompileCommand(llvm::sys::path::parent_path(File),
+ llvm::sys::path::filename(File),
+ std::move(Argv),
/*Output=*/"");
}
DirectoryBasedGlobalCompilationDatabase::
- DirectoryBasedGlobalCompilationDatabase(Optional<Path> CompileCommandsDir)
+ DirectoryBasedGlobalCompilationDatabase(
+ llvm::Optional<Path> CompileCommandsDir)
: CompileCommandsDir(std::move(CompileCommandsDir)) {}
DirectoryBasedGlobalCompilationDatabase::
~DirectoryBasedGlobalCompilationDatabase() = default;
-Optional<tooling::CompileCommand>
+llvm::Optional<tooling::CompileCommand>
DirectoryBasedGlobalCompilationDatabase::getCompileCommand(
PathRef File, ProjectInfo *Project) const {
if (auto CDB = getCDBForFile(File, Project)) {
@@ -67,7 +101,7 @@ DirectoryBasedGlobalCompilationDatabase::getCDBInDirLocked(PathRef Dir) const {
tooling::CompilationDatabase *
DirectoryBasedGlobalCompilationDatabase::getCDBForFile(
PathRef File, ProjectInfo *Project) const {
- namespace path = sys::path;
+ namespace path = llvm::sys::path;
assert((path::is_absolute(File, path::Style::posix) ||
path::is_absolute(File, path::Style::windows)) &&
"path must be absolute");
@@ -95,26 +129,35 @@ 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);
});
}
-Optional<tooling::CompileCommand>
+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 c43d72c4..a5759a4e 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
//
//===----------------------------------------------------------------------===//
@@ -17,7 +16,6 @@
#include "clang/Lex/HeaderSearch.h"
#include "llvm/Support/Path.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -30,9 +28,10 @@ public:
// Record existing #includes - both written and resolved paths. Only #includes
// in the main file are collected.
void InclusionDirective(SourceLocation HashLoc, const Token & /*IncludeTok*/,
- StringRef FileName, bool IsAngled,
+ llvm::StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange, const FileEntry *File,
- StringRef /*SearchPath*/, StringRef /*RelativePath*/,
+ llvm::StringRef /*SearchPath*/,
+ llvm::StringRef /*RelativePath*/,
const Module * /*Imported*/,
SrcMgr::CharacteristicKind FileKind) override {
if (SM.isWrittenInMainFile(HashLoc)) {
@@ -65,13 +64,48 @@ private:
} // namespace
-bool isLiteralInclude(StringRef Include) {
+bool isLiteralInclude(llvm::StringRef Include) {
return Include.startswith("<") || Include.startswith("\"");
}
bool HeaderFile::valid() const {
return (Verbatim && isLiteralInclude(File)) ||
- (!Verbatim && sys::path::is_absolute(File));
+ (!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>
@@ -80,9 +114,9 @@ collectIncludeStructureCallback(const SourceManager &SM,
return llvm::make_unique<RecordHeaders>(SM, Out);
}
-void IncludeStructure::recordInclude(StringRef IncludingName,
- StringRef IncludedName,
- StringRef IncludedRealName) {
+void IncludeStructure::recordInclude(llvm::StringRef IncludingName,
+ llvm::StringRef IncludedName,
+ llvm::StringRef IncludedRealName) {
auto Child = fileIndex(IncludedName);
if (!IncludedRealName.empty() && RealPathNames[Child].empty())
RealPathNames[Child] = IncludedRealName;
@@ -90,19 +124,20 @@ void IncludeStructure::recordInclude(StringRef IncludingName,
IncludeChildren[Parent].push_back(Child);
}
-unsigned IncludeStructure::fileIndex(StringRef Name) {
+unsigned IncludeStructure::fileIndex(llvm::StringRef Name) {
auto R = NameToIndex.try_emplace(Name, RealPathNames.size());
if (R.second)
RealPathNames.emplace_back();
return R.first->getValue();
}
-StringMap<unsigned> IncludeStructure::includeDepth(StringRef Root) const {
+llvm::StringMap<unsigned>
+IncludeStructure::includeDepth(llvm::StringRef Root) const {
// Include depth 0 is the main file only.
- StringMap<unsigned> Result;
+ llvm::StringMap<unsigned> Result;
Result[Root] = 0;
std::vector<unsigned> CurrentLevel;
- DenseSet<unsigned> Seen;
+ llvm::DenseSet<unsigned> Seen;
auto It = NameToIndex.find(Root);
if (It != NameToIndex.end()) {
CurrentLevel.push_back(It->second);
@@ -142,7 +177,7 @@ bool IncludeInserter::shouldInsertInclude(
assert(DeclaringHeader.valid() && InsertedHeader.valid());
if (FileName == DeclaringHeader.File || FileName == InsertedHeader.File)
return false;
- auto Included = [&](StringRef Header) {
+ auto Included = [&](llvm::StringRef Header) {
return IncludedHeaders.find(Header) != IncludedHeaders.end();
};
return !Included(DeclaringHeader.File) && !Included(InsertedHeader.File);
@@ -164,8 +199,9 @@ IncludeInserter::calculateIncludePath(const HeaderFile &DeclaringHeader,
return Suggested;
}
-Optional<TextEdit> IncludeInserter::insert(StringRef VerbatimHeader) const {
- Optional<TextEdit> Edit = None;
+llvm::Optional<TextEdit>
+IncludeInserter::insert(llvm::StringRef VerbatimHeader) const {
+ llvm::Optional<TextEdit> Edit = None;
if (auto Insertion = Inserter.insert(VerbatimHeader.trim("\"<>"),
VerbatimHeader.startswith("<")))
Edit = replacementToEdit(Code, *Insertion);
diff --git a/clangd/Headers.h b/clangd/Headers.h
index 6f0eb807..e29f7f6b 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/Index.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.
diff --git a/clangd/IncludeFixer.cpp b/clangd/IncludeFixer.cpp
new file mode 100644
index 00000000..177d5774
--- /dev/null
+++ b/clangd/IncludeFixer.cpp
@@ -0,0 +1,304 @@
+//===--- 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 "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/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/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 {
+ if (IndexRequestCount >= IndexRequestLimit)
+ return {}; // Avoid querying index too many times in a single parse.
+ switch (Info.getID()) {
+ case diag::err_incomplete_type:
+ case diag::err_incomplete_member_access:
+ case diag::err_incomplete_base_class:
+ // 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 {};
+ ++IndexRequestCount;
+ // FIXME: consider batching the requests for all diagnostics.
+ // FIXME: consider caching the lookup results.
+ LookupRequest Req;
+ Req.IDs.insert(*ID);
+ llvm::Optional<Symbol> Matched;
+ Index.lookup(Req, [&](const Symbol &Sym) {
+ if (Matched)
+ return;
+ Matched = Sym;
+ });
+
+ if (!Matched || Matched->IncludeHeaders.empty() || !Matched->Definition ||
+ Matched->CanonicalDeclaration.FileURI != Matched->Definition.FileURI)
+ return {};
+ return fixesForSymbols({*Matched});
+}
+
+std::vector<Fix>
+IncludeFixer::fixesForSymbols(llvm::ArrayRef<Symbol> Syms) const {
+ auto Inserted = [&](const Symbol &Sym, llvm::StringRef Header)
+ -> llvm::Expected<std::pair<std::string, bool>> {
+ auto ResolvedDeclaring =
+ toHeaderFile(Sym.CanonicalDeclaration.FileURI, File);
+ if (!ResolvedDeclaring)
+ return ResolvedDeclaring.takeError();
+ auto ResolvedInserted = toHeaderFile(Header, File);
+ if (!ResolvedInserted)
+ return ResolvedInserted.takeError();
+ return std::make_pair(
+ Inserter->calculateIncludePath(*ResolvedDeclaring, *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}",
+ File, Inc, ToInclude.takeError());
+ }
+ }
+ }
+ return Fixes;
+}
+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();
+
+ // FIXME: support invalid scope before a type name. In the following
+ // example, namespace "clang::tidy::" hasn't been declared/imported.
+ // namespace clang {
+ // void f() {
+ // tidy::Check c;
+ // ~~~~
+ // // or
+ // clang::tidy::Check c;
+ // ~~~~
+ // }
+ // }
+ // For both cases, the typo and the diagnostic are both on "tidy", and no
+ // diagnostic is generated for "Check". However, what we want to fix is
+ // "clang::tidy::Check".
+
+ // Extract the typed scope. This is not done lazily because `SS` can get
+ // out of scope and it's relatively cheap.
+ llvm::Optional<std::string> SpecifiedScope;
+ if (SS && SS->isNotEmpty()) { // "::" or "ns::"
+ if (auto *Nested = SS->getScopeRep()) {
+ if (Nested->getKind() == NestedNameSpecifier::Global)
+ SpecifiedScope = "";
+ else if (const auto *NS = Nested->getAsNamespace())
+ SpecifiedScope = printNamespaceScope(*NS);
+ 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 TypoCorrection();
+ }
+ }
+ if (!SpecifiedScope && !S) // Give up if no scope available.
+ return TypoCorrection();
+
+ UnresolvedName Unresolved;
+ Unresolved.Name = Typo.getAsString();
+ Unresolved.Loc = Typo.getBeginLoc();
+
+ auto *Sem = SemaPtr; // Avoid capturing `this`.
+ Unresolved.GetScopes = [Sem, SpecifiedScope, S, LookupKind]() {
+ std::vector<std::string> Scopes;
+ if (SpecifiedScope) {
+ Scopes.push_back(*SpecifiedScope);
+ } else {
+ assert(S);
+ // No scope qualifier 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));
+ }
+ 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;
+
+ 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();
+ return fixesForSymbols(std::vector<Symbol>(Syms.begin(), Syms.end()));
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/clangd/IncludeFixer.h b/clangd/IncludeFixer.h
new file mode 100644
index 00000000..da292b56
--- /dev/null
+++ b/clangd/IncludeFixer.h
@@ -0,0 +1,87 @@
+//===--- 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 "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/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(llvm::ArrayRef<Symbol> 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;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDE_FIXER_H
diff --git a/clangd/JSONTransport.cpp b/clangd/JSONTransport.cpp
index 83ef49b0..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"
@@ -11,66 +10,68 @@
#include "Transport.h"
#include "llvm/Support/Errno.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
-json::Object encodeError(Error E) {
+llvm::json::Object encodeError(llvm::Error E) {
std::string Message;
ErrorCode Code = ErrorCode::UnknownErrorCode;
- if (Error Unhandled =
- handleErrors(std::move(E), [&](const LSPError &L) -> Error {
+ if (llvm::Error Unhandled = llvm::handleErrors(
+ std::move(E), [&](const LSPError &L) -> llvm::Error {
Message = L.Message;
Code = L.Code;
- return Error::success();
+ return llvm::Error::success();
}))
- Message = toString(std::move(Unhandled));
+ Message = llvm::toString(std::move(Unhandled));
- return json::Object{
+ return llvm::json::Object{
{"message", std::move(Message)},
{"code", int64_t(Code)},
};
}
-Error decodeError(const json::Object &O) {
+llvm::Error decodeError(const llvm::json::Object &O) {
std::string Msg = O.getString("message").getValueOr("Unspecified error");
if (auto Code = O.getInteger("code"))
- return make_error<LSPError>(std::move(Msg), ErrorCode(*Code));
- return make_error<StringError>(std::move(Msg), inconvertibleErrorCode());
+ return llvm::make_error<LSPError>(std::move(Msg), ErrorCode(*Code));
+ return llvm::make_error<llvm::StringError>(std::move(Msg),
+ llvm::inconvertibleErrorCode());
}
class JSONTransport : public Transport {
public:
- JSONTransport(std::FILE *In, raw_ostream &Out, raw_ostream *InMirror,
- bool Pretty, JSONStreamStyle Style)
- : In(In), Out(Out), InMirror(InMirror ? *InMirror : nulls()),
+ JSONTransport(std::FILE *In, llvm::raw_ostream &Out,
+ llvm::raw_ostream *InMirror, bool Pretty, JSONStreamStyle Style)
+ : In(In), Out(Out), InMirror(InMirror ? *InMirror : llvm::nulls()),
Pretty(Pretty), Style(Style) {}
- void notify(StringRef Method, json::Value Params) override {
- sendMessage(json::Object{
+ void notify(llvm::StringRef Method, llvm::json::Value Params) override {
+ sendMessage(llvm::json::Object{
{"jsonrpc", "2.0"},
{"method", Method},
{"params", std::move(Params)},
});
}
- void call(StringRef Method, json::Value Params, json::Value ID) override {
- sendMessage(json::Object{
+ void call(llvm::StringRef Method, llvm::json::Value Params,
+ llvm::json::Value ID) override {
+ sendMessage(llvm::json::Object{
{"jsonrpc", "2.0"},
{"id", std::move(ID)},
{"method", Method},
{"params", std::move(Params)},
});
}
- void reply(json::Value ID, Expected<json::Value> Result) override {
+ void reply(llvm::json::Value ID,
+ llvm::Expected<llvm::json::Value> Result) override {
if (Result) {
- sendMessage(json::Object{
+ sendMessage(llvm::json::Object{
{"jsonrpc", "2.0"},
{"id", std::move(ID)},
{"result", std::move(*Result)},
});
} else {
- sendMessage(json::Object{
+ sendMessage(llvm::json::Object{
{"jsonrpc", "2.0"},
{"id", std::move(ID)},
{"error", encodeError(Result.takeError())},
@@ -78,33 +79,34 @@ public:
}
}
- Error loop(MessageHandler &Handler) override {
+ llvm::Error loop(MessageHandler &Handler) override {
while (!feof(In)) {
if (ferror(In))
- return errorCodeToError(std::error_code(errno, std::system_category()));
+ return llvm::errorCodeToError(
+ std::error_code(errno, std::system_category()));
if (auto JSON = readRawMessage()) {
- if (auto Doc = json::parse(*JSON)) {
+ if (auto Doc = llvm::json::parse(*JSON)) {
vlog(Pretty ? "<<< {0:2}\n" : "<<< {0}\n", *Doc);
if (!handleMessage(std::move(*Doc), Handler))
- return Error::success(); // we saw the "exit" notification.
+ return llvm::Error::success(); // we saw the "exit" notification.
} else {
// Parse error. Log the raw message.
vlog("<<< {0}\n", *JSON);
- elog("JSON parse error: {0}", toString(Doc.takeError()));
+ elog("JSON parse error: {0}", llvm::toString(Doc.takeError()));
}
}
}
- return errorCodeToError(std::make_error_code(std::errc::io_error));
+ return llvm::errorCodeToError(std::make_error_code(std::errc::io_error));
}
private:
// Dispatches incoming message to Handler onNotify/onCall/onReply.
- bool handleMessage(json::Value Message, MessageHandler &Handler);
+ bool handleMessage(llvm::json::Value Message, MessageHandler &Handler);
// Writes outgoing message to Out stream.
- void sendMessage(json::Value Message) {
+ void sendMessage(llvm::json::Value Message) {
std::string S;
- raw_string_ostream OS(S);
- OS << formatv(Pretty ? "{0:2}" : "{0}", Message);
+ llvm::raw_string_ostream OS(S);
+ OS << llvm::formatv(Pretty ? "{0:2}" : "{0}", Message);
OS.flush();
Out << "Content-Length: " << S.size() << "\r\n\r\n" << S;
Out.flush();
@@ -112,30 +114,31 @@ private:
}
// Read raw string messages from input stream.
- Optional<std::string> readRawMessage() {
+ llvm::Optional<std::string> readRawMessage() {
return Style == JSONStreamStyle::Delimited ? readDelimitedMessage()
: readStandardMessage();
}
- Optional<std::string> readDelimitedMessage();
- Optional<std::string> readStandardMessage();
+ llvm::Optional<std::string> readDelimitedMessage();
+ llvm::Optional<std::string> readStandardMessage();
std::FILE *In;
- raw_ostream &Out;
- raw_ostream &InMirror;
+ llvm::raw_ostream &Out;
+ llvm::raw_ostream &InMirror;
bool Pretty;
JSONStreamStyle Style;
};
-bool JSONTransport::handleMessage(json::Value Message,
+bool JSONTransport::handleMessage(llvm::json::Value Message,
MessageHandler &Handler) {
// Message must be an object with "jsonrpc":"2.0".
auto *Object = Message.getAsObject();
- if (!Object || Object->getString("jsonrpc") != Optional<StringRef>("2.0")) {
+ if (!Object ||
+ Object->getString("jsonrpc") != llvm::Optional<llvm::StringRef>("2.0")) {
elog("Not a JSON-RPC 2.0 message: {0:2}", Message);
return false;
}
// ID may be any JSON value. If absent, this is a notification.
- Optional<json::Value> ID;
+ llvm::Optional<llvm::json::Value> ID;
if (auto *I = Object->get("id"))
ID = std::move(*I);
auto Method = Object->getString("method");
@@ -147,13 +150,13 @@ bool JSONTransport::handleMessage(json::Value Message,
if (auto *Err = Object->getObject("error"))
return Handler.onReply(std::move(*ID), decodeError(*Err));
// Result should be given, use null if not.
- json::Value Result = nullptr;
+ llvm::json::Value Result = nullptr;
if (auto *R = Object->get("result"))
Result = std::move(*R);
return Handler.onReply(std::move(*ID), std::move(Result));
}
// Params should be given, use null if not.
- json::Value Params = nullptr;
+ llvm::json::Value Params = nullptr;
if (auto *P = Object->get("params"))
Params = std::move(*P);
@@ -172,7 +175,7 @@ bool readLine(std::FILE *In, std::string &Out) {
for (;;) {
Out.resize(Size + BufSize);
// Handle EINTR which is sent when a debugger attaches on some platforms.
- if (!sys::RetryAfterSignal(nullptr, ::fgets, &Out[Size], BufSize, In))
+ if (!llvm::sys::RetryAfterSignal(nullptr, ::fgets, &Out[Size], BufSize, In))
return false;
clearerr(In);
// If the line contained null bytes, anything after it (including \n) will
@@ -189,17 +192,17 @@ bool readLine(std::FILE *In, std::string &Out) {
// Returns None when:
// - ferror() or feof() are set.
// - Content-Length is missing or empty (protocol error)
-Optional<std::string> JSONTransport::readStandardMessage() {
+llvm::Optional<std::string> JSONTransport::readStandardMessage() {
// A Language Server Protocol message starts with a set of HTTP headers,
// delimited by \r\n, and terminated by an empty line (\r\n).
unsigned long long ContentLength = 0;
std::string Line;
while (true) {
if (feof(In) || ferror(In) || !readLine(In, Line))
- return None;
+ return llvm::None;
InMirror << Line;
- StringRef LineRef(Line);
+ llvm::StringRef LineRef(Line);
// We allow comments in headers. Technically this isn't part
@@ -214,7 +217,7 @@ Optional<std::string> JSONTransport::readStandardMessage() {
"The previous value for this message ({0}) was ignored.",
ContentLength);
}
- getAsUnsignedInteger(LineRef.trim(), 0, ContentLength);
+ llvm::getAsUnsignedInteger(LineRef.trim(), 0, ContentLength);
continue;
} else if (!LineRef.trim().empty()) {
// It's another header, ignore it.
@@ -231,24 +234,24 @@ Optional<std::string> JSONTransport::readStandardMessage() {
elog("Refusing to read message with long Content-Length: {0}. "
"Expect protocol errors",
ContentLength);
- return None;
+ return llvm::None;
}
if (ContentLength == 0) {
log("Warning: Missing Content-Length header, or zero-length message.");
- return None;
+ return llvm::None;
}
std::string JSON(ContentLength, '\0');
for (size_t Pos = 0, Read; Pos < ContentLength; Pos += Read) {
// Handle EINTR which is sent when a debugger attaches on some platforms.
- Read = sys::RetryAfterSignal(0u, ::fread, &JSON[Pos], 1,
- ContentLength - Pos, In);
+ Read = llvm::sys::RetryAfterSignal(0u, ::fread, &JSON[Pos], 1,
+ ContentLength - Pos, In);
if (Read == 0) {
elog("Input was aborted. Read only {0} bytes of expected {1}.", Pos,
ContentLength);
- return None;
+ return llvm::None;
}
- InMirror << StringRef(&JSON[Pos], Read);
+ InMirror << llvm::StringRef(&JSON[Pos], Read);
clearerr(In); // If we're done, the error was transient. If we're not done,
// either it was transient or we'll see it again on retry.
Pos += Read;
@@ -261,12 +264,12 @@ Optional<std::string> JSONTransport::readStandardMessage() {
// - lines starting with # are ignored.
// This is a testing path, so favor simplicity over performance here.
// When returning None, feof() or ferror() will be set.
-Optional<std::string> JSONTransport::readDelimitedMessage() {
+llvm::Optional<std::string> JSONTransport::readDelimitedMessage() {
std::string JSON;
std::string Line;
while (readLine(In, Line)) {
InMirror << Line;
- auto LineRef = StringRef(Line).trim();
+ auto LineRef = llvm::StringRef(Line).trim();
if (LineRef.startswith("#")) // comment
continue;
@@ -279,15 +282,17 @@ Optional<std::string> JSONTransport::readDelimitedMessage() {
if (ferror(In)) {
elog("Input error while reading message!");
- return None;
+ return llvm::None;
}
return std::move(JSON); // Including at EOF
}
} // namespace
-std::unique_ptr<Transport> newJSONTransport(std::FILE *In, raw_ostream &Out,
- raw_ostream *InMirror, bool Pretty,
+std::unique_ptr<Transport> newJSONTransport(std::FILE *In,
+ llvm::raw_ostream &Out,
+ llvm::raw_ostream *InMirror,
+ bool Pretty,
JSONStreamStyle Style) {
return llvm::make_unique<JSONTransport>(In, Out, InMirror, Pretty, Style);
}
diff --git a/clangd/Logger.cpp b/clangd/Logger.cpp
index 6adf45dc..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
//
//===----------------------------------------------------------------------===//
@@ -14,7 +13,6 @@
#include "llvm/Support/raw_ostream.h"
#include <mutex>
-using namespace llvm;
namespace clang {
namespace clangd {
@@ -29,13 +27,14 @@ LoggingSession::LoggingSession(clangd::Logger &Instance) {
LoggingSession::~LoggingSession() { L = nullptr; }
-void detail::log(Logger::Level Level, const formatv_object_base &Message) {
+void detail::log(Logger::Level Level,
+ const llvm::formatv_object_base &Message) {
if (L)
L->log(Level, Message);
else {
static std::mutex Mu;
std::lock_guard<std::mutex> Guard(Mu);
- errs() << Message << "\n";
+ llvm::errs() << Message << "\n";
}
}
@@ -48,14 +47,14 @@ const char *detail::debugType(const char *Filename) {
}
void StreamLogger::log(Logger::Level Level,
- const formatv_object_base &Message) {
+ const llvm::formatv_object_base &Message) {
if (Level < MinLevel)
return;
- sys::TimePoint<> Timestamp = std::chrono::system_clock::now();
+ llvm::sys::TimePoint<> Timestamp = std::chrono::system_clock::now();
trace::log(Message);
std::lock_guard<std::mutex> Guard(StreamMutex);
- Logs << formatv("{0}[{1:%H:%M:%S.%L}] {2}\n", indicator(Level), Timestamp,
- Message);
+ Logs << llvm::formatv("{0}[{1:%H:%M:%S.%L}] {2}\n", indicator(Level),
+ Timestamp, Message);
Logs.flush();
}
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 55078954..ef6f491a 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
//
//===----------------------------------------------------------------------===//
//
@@ -24,14 +23,14 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
namespace clang {
namespace clangd {
char LSPError::ID;
-URIForFile URIForFile::canonicalize(StringRef AbsPath, StringRef TUPath) {
- assert(sys::path::is_absolute(AbsPath) && "the path is relative");
+URIForFile URIForFile::canonicalize(llvm::StringRef AbsPath,
+ llvm::StringRef TUPath) {
+ assert(llvm::sys::path::is_absolute(AbsPath) && "the path is relative");
auto Resolved = URI::resolvePath(AbsPath, TUPath);
if (!Resolved) {
elog("URIForFile: failed to resolve path {0} with TU path {1}: "
@@ -42,14 +41,15 @@ URIForFile URIForFile::canonicalize(StringRef AbsPath, StringRef TUPath) {
return URIForFile(std::move(*Resolved));
}
-Expected<URIForFile> URIForFile::fromURI(const URI &U, StringRef HintPath) {
+llvm::Expected<URIForFile> URIForFile::fromURI(const URI &U,
+ llvm::StringRef HintPath) {
auto Resolved = URI::resolve(U, HintPath);
if (!Resolved)
return Resolved.takeError();
return URIForFile(std::move(*Resolved));
}
-bool fromJSON(const json::Value &E, URIForFile &R) {
+bool fromJSON(const llvm::json::Value &E, URIForFile &R) {
if (auto S = E.getAsString()) {
auto Parsed = URI::parse(*S);
if (!Parsed) {
@@ -73,89 +73,89 @@ bool fromJSON(const json::Value &E, URIForFile &R) {
return false;
}
-json::Value toJSON(const URIForFile &U) { return U.uri(); }
+llvm::json::Value toJSON(const URIForFile &U) { return U.uri(); }
-raw_ostream &operator<<(raw_ostream &OS, const URIForFile &U) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const URIForFile &U) {
return OS << U.uri();
}
-json::Value toJSON(const TextDocumentIdentifier &R) {
- return json::Object{{"uri", R.uri}};
+llvm::json::Value toJSON(const TextDocumentIdentifier &R) {
+ return llvm::json::Object{{"uri", R.uri}};
}
-bool fromJSON(const json::Value &Params, TextDocumentIdentifier &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, TextDocumentIdentifier &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("uri", R.uri);
}
-bool fromJSON(const json::Value &Params, Position &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, Position &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("line", R.line) && O.map("character", R.character);
}
-json::Value toJSON(const Position &P) {
- return json::Object{
+llvm::json::Value toJSON(const Position &P) {
+ return llvm::json::Object{
{"line", P.line},
{"character", P.character},
};
}
-raw_ostream &operator<<(raw_ostream &OS, const Position &P) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Position &P) {
return OS << P.line << ':' << P.character;
}
-bool fromJSON(const json::Value &Params, Range &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, Range &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("start", R.start) && O.map("end", R.end);
}
-json::Value toJSON(const Range &P) {
- return json::Object{
+llvm::json::Value toJSON(const Range &P) {
+ return llvm::json::Object{
{"start", P.start},
{"end", P.end},
};
}
-raw_ostream &operator<<(raw_ostream &OS, const Range &R) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Range &R) {
return OS << R.start << '-' << R.end;
}
-json::Value toJSON(const Location &P) {
- return json::Object{
+llvm::json::Value toJSON(const Location &P) {
+ return llvm::json::Object{
{"uri", P.uri},
{"range", P.range},
};
}
-raw_ostream &operator<<(raw_ostream &OS, const Location &L) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Location &L) {
return OS << L.range << '@' << L.uri;
}
-bool fromJSON(const json::Value &Params, TextDocumentItem &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, TextDocumentItem &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("uri", R.uri) && O.map("languageId", R.languageId) &&
O.map("version", R.version) && O.map("text", R.text);
}
-bool fromJSON(const json::Value &Params, TextEdit &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, TextEdit &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("range", R.range) && O.map("newText", R.newText);
}
-json::Value toJSON(const TextEdit &P) {
- return json::Object{
+llvm::json::Value toJSON(const TextEdit &P) {
+ return llvm::json::Object{
{"range", P.range},
{"newText", P.newText},
};
}
-raw_ostream &operator<<(raw_ostream &OS, const TextEdit &TE) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TextEdit &TE) {
OS << TE.range << " => \"";
- printEscapedString(TE.newText, OS);
+ llvm::printEscapedString(TE.newText, OS);
return OS << '"';
}
-bool fromJSON(const json::Value &E, TraceLevel &Out) {
+bool fromJSON(const llvm::json::Value &E, TraceLevel &Out) {
if (auto S = E.getAsString()) {
if (*S == "off") {
Out = TraceLevel::Off;
@@ -171,7 +171,7 @@ bool fromJSON(const json::Value &E, TraceLevel &Out) {
return false;
}
-bool fromJSON(const json::Value &E, SymbolKind &Out) {
+bool fromJSON(const llvm::json::Value &E, SymbolKind &Out) {
if (auto T = E.getAsInteger()) {
if (*T < static_cast<int>(SymbolKind::File) ||
*T > static_cast<int>(SymbolKind::TypeParameter))
@@ -182,7 +182,7 @@ bool fromJSON(const json::Value &E, SymbolKind &Out) {
return false;
}
-bool fromJSON(const json::Value &E, SymbolKindBitset &Out) {
+bool fromJSON(const llvm::json::Value &E, SymbolKindBitset &Out) {
if (auto *A = E.getAsArray()) {
for (size_t I = 0; I < A->size(); ++I) {
SymbolKind KindOut;
@@ -212,8 +212,8 @@ SymbolKind adjustKindToCapability(SymbolKind Kind,
}
}
-bool fromJSON(const json::Value &Params, ClientCapabilities &R) {
- const json::Object *O = Params.getAsObject();
+bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R) {
+ const llvm::json::Object *O = Params.getAsObject();
if (!O)
return false;
if (auto *TextDocument = O->getObject("textDocument")) {
@@ -260,8 +260,8 @@ bool fromJSON(const json::Value &Params, ClientCapabilities &R) {
return true;
}
-bool fromJSON(const json::Value &Params, InitializeParams &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, InitializeParams &R) {
+ llvm::json::ObjectMapper O(Params);
if (!O)
return false;
// We deliberately don't fail if we can't parse individual fields.
@@ -275,24 +275,24 @@ bool fromJSON(const json::Value &Params, InitializeParams &R) {
return true;
}
-bool fromJSON(const json::Value &Params, DidOpenTextDocumentParams &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, DidOpenTextDocumentParams &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("textDocument", R.textDocument);
}
-bool fromJSON(const json::Value &Params, DidCloseTextDocumentParams &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, DidCloseTextDocumentParams &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("textDocument", R.textDocument);
}
-bool fromJSON(const json::Value &Params, DidChangeTextDocumentParams &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, DidChangeTextDocumentParams &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("textDocument", R.textDocument) &&
O.map("contentChanges", R.contentChanges) &&
O.map("wantDiagnostics", R.wantDiagnostics);
}
-bool fromJSON(const json::Value &E, FileChangeType &Out) {
+bool fromJSON(const llvm::json::Value &E, FileChangeType &Out) {
if (auto T = E.getAsInteger()) {
if (*T < static_cast<int>(FileChangeType::Created) ||
*T > static_cast<int>(FileChangeType::Deleted))
@@ -303,61 +303,64 @@ bool fromJSON(const json::Value &E, FileChangeType &Out) {
return false;
}
-bool fromJSON(const json::Value &Params, FileEvent &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, FileEvent &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("uri", R.uri) && O.map("type", R.type);
}
-bool fromJSON(const json::Value &Params, DidChangeWatchedFilesParams &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, DidChangeWatchedFilesParams &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("changes", R.changes);
}
-bool fromJSON(const json::Value &Params, TextDocumentContentChangeEvent &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params,
+ TextDocumentContentChangeEvent &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("range", R.range) && O.map("rangeLength", R.rangeLength) &&
O.map("text", R.text);
}
-bool fromJSON(const json::Value &Params, FormattingOptions &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, FormattingOptions &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("tabSize", R.tabSize) &&
O.map("insertSpaces", R.insertSpaces);
}
-json::Value toJSON(const FormattingOptions &P) {
- return json::Object{
+llvm::json::Value toJSON(const FormattingOptions &P) {
+ return llvm::json::Object{
{"tabSize", P.tabSize},
{"insertSpaces", P.insertSpaces},
};
}
-bool fromJSON(const json::Value &Params, DocumentRangeFormattingParams &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params,
+ DocumentRangeFormattingParams &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("textDocument", R.textDocument) &&
O.map("range", R.range) && O.map("options", R.options);
}
-bool fromJSON(const json::Value &Params, DocumentOnTypeFormattingParams &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params,
+ DocumentOnTypeFormattingParams &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("textDocument", R.textDocument) &&
O.map("position", R.position) && O.map("ch", R.ch) &&
O.map("options", R.options);
}
-bool fromJSON(const json::Value &Params, DocumentFormattingParams &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, DocumentFormattingParams &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("textDocument", R.textDocument) &&
O.map("options", R.options);
}
-bool fromJSON(const json::Value &Params, DocumentSymbolParams &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, DocumentSymbolParams &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("textDocument", R.textDocument);
}
-json::Value toJSON(const Diagnostic &D) {
- json::Object Diag{
+llvm::json::Value toJSON(const Diagnostic &D) {
+ llvm::json::Object Diag{
{"range", D.range},
{"severity", D.severity},
{"message", D.message},
@@ -369,8 +372,8 @@ json::Value toJSON(const Diagnostic &D) {
return std::move(Diag);
}
-bool fromJSON(const json::Value &Params, Diagnostic &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, Diagnostic &R) {
+ llvm::json::ObjectMapper O(Params);
if (!O || !O.map("range", R.range) || !O.map("message", R.message))
return false;
O.map("severity", R.severity);
@@ -378,48 +381,51 @@ bool fromJSON(const json::Value &Params, Diagnostic &R) {
return true;
}
-bool fromJSON(const json::Value &Params, CodeActionContext &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, CodeActionContext &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("diagnostics", R.diagnostics);
}
-raw_ostream &operator<<(raw_ostream &OS, const Diagnostic &D) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diagnostic &D) {
OS << D.range << " [";
switch (D.severity) {
- case 1:
- OS << "error";
- break;
- case 2:
- OS << "warning";
- break;
- case 3:
- OS << "note";
- break;
- case 4:
- OS << "remark";
- break;
- default:
- OS << "diagnostic";
- break;
+ case 1:
+ OS << "error";
+ break;
+ case 2:
+ OS << "warning";
+ break;
+ case 3:
+ OS << "note";
+ break;
+ case 4:
+ OS << "remark";
+ break;
+ default:
+ OS << "diagnostic";
+ break;
}
return OS << '(' << D.severity << "): " << D.message << "]";
}
-bool fromJSON(const json::Value &Params, CodeActionParams &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, CodeActionParams &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("textDocument", R.textDocument) &&
O.map("range", R.range) && O.map("context", R.context);
}
-bool fromJSON(const json::Value &Params, WorkspaceEdit &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, WorkspaceEdit &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("changes", R.changes);
}
-const StringLiteral ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND =
+const llvm::StringLiteral ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND =
"clangd.applyFix";
-bool fromJSON(const json::Value &Params, ExecuteCommandParams &R) {
- json::ObjectMapper O(Params);
+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))
return false;
@@ -428,11 +434,13 @@ bool fromJSON(const 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.
}
-json::Value toJSON(const SymbolInformation &P) {
- return json::Object{
+llvm::json::Value toJSON(const SymbolInformation &P) {
+ return llvm::json::Object{
{"name", P.name},
{"kind", static_cast<int>(P.kind)},
{"location", P.location},
@@ -440,7 +448,8 @@ json::Value toJSON(const SymbolInformation &P) {
};
}
-raw_ostream &operator<<(raw_ostream &O, const SymbolInformation &SI) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
+ const SymbolInformation &SI) {
O << SI.containerName << "::" << SI.name << " - " << toJSON(SI);
return O;
}
@@ -451,31 +460,31 @@ bool operator==(const SymbolDetails &LHS, const SymbolDetails &RHS) {
}
llvm::json::Value toJSON(const SymbolDetails &P) {
- json::Object result{{"name", llvm::json::Value(nullptr)},
- {"containerName", llvm::json::Value(nullptr)},
- {"usr", llvm::json::Value(nullptr)},
- {"id", 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 json::Value(std::move(result));
+ return llvm::json::Value(std::move(Result));
}
llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const SymbolDetails &S) {
if (!S.containerName.empty()) {
O << S.containerName;
- StringRef ContNameRef;
+ llvm::StringRef ContNameRef;
if (!ContNameRef.endswith("::")) {
O << " ";
}
@@ -484,26 +493,29 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const SymbolDetails &S) {
return O;
}
-bool fromJSON(const json::Value &Params, WorkspaceSymbolParams &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, WorkspaceSymbolParams &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("query", R.query);
}
-json::Value toJSON(const Command &C) {
- auto Cmd = json::Object{{"title", C.title}, {"command", C.command}};
+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 StringLiteral CodeAction::QUICKFIX_KIND = "quickfix";
+const llvm::StringLiteral CodeAction::QUICKFIX_KIND = "quickfix";
+const llvm::StringLiteral CodeAction::REFACTOR_KIND = "refactor";
-json::Value toJSON(const CodeAction &CA) {
- auto CodeAction = json::Object{{"title", CA.title}};
+llvm::json::Value toJSON(const CodeAction &CA) {
+ auto CodeAction = llvm::json::Object{{"title", CA.title}};
if (CA.kind)
CodeAction["kind"] = *CA.kind;
if (CA.diagnostics)
- CodeAction["diagnostics"] = json::Array(*CA.diagnostics);
+ CodeAction["diagnostics"] = llvm::json::Array(*CA.diagnostics);
if (CA.edit)
CodeAction["edit"] = *CA.edit;
if (CA.command)
@@ -511,15 +523,15 @@ json::Value toJSON(const CodeAction &CA) {
return std::move(CodeAction);
}
-raw_ostream &operator<<(raw_ostream &O, const DocumentSymbol &S) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const DocumentSymbol &S) {
return O << S.name << " - " << toJSON(S);
}
-json::Value toJSON(const DocumentSymbol &S) {
- json::Object Result{{"name", S.name},
- {"kind", static_cast<int>(S.kind)},
- {"range", S.range},
- {"selectionRange", S.selectionRange}};
+llvm::json::Value toJSON(const DocumentSymbol &S) {
+ llvm::json::Object Result{{"name", S.name},
+ {"kind", static_cast<int>(S.kind)},
+ {"range", S.range},
+ {"selectionRange", S.selectionRange}};
if (!S.detail.empty())
Result["detail"] = S.detail;
@@ -528,29 +540,63 @@ json::Value toJSON(const DocumentSymbol &S) {
if (S.deprecated)
Result["deprecated"] = true;
// Older gcc cannot compile 'return Result', even though it is legal.
- return json::Value(std::move(Result));
+ return llvm::json::Value(std::move(Result));
}
-json::Value toJSON(const WorkspaceEdit &WE) {
+llvm::json::Value toJSON(const WorkspaceEdit &WE) {
if (!WE.changes)
- return json::Object{};
- json::Object FileChanges;
+ return llvm::json::Object{};
+ llvm::json::Object FileChanges;
for (auto &Change : *WE.changes)
- FileChanges[Change.first] = json::Array(Change.second);
- return json::Object{{"changes", std::move(FileChanges)}};
+ FileChanges[Change.first] = llvm::json::Array(Change.second);
+ return llvm::json::Object{{"changes", std::move(FileChanges)}};
}
-json::Value toJSON(const ApplyWorkspaceEditParams &Params) {
- return json::Object{{"edit", Params.edit}};
+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);
}
-bool fromJSON(const json::Value &Params, TextDocumentPositionParams &R) {
- json::ObjectMapper O(Params);
+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}};
+}
+
+bool fromJSON(const llvm::json::Value &Params, TextDocumentPositionParams &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("textDocument", R.textDocument) &&
O.map("position", R.position);
}
-static StringRef toTextKind(MarkupKind Kind) {
+bool fromJSON(const llvm::json::Value &Params, CompletionContext &R) {
+ llvm::json::ObjectMapper O(Params);
+ if (!O)
+ return false;
+
+ int TriggerKind;
+ if (!O.map("triggerKind", TriggerKind))
+ return false;
+ R.triggerKind = static_cast<CompletionTriggerKind>(TriggerKind);
+
+ if (auto *TC = Params.getAsObject()->get("triggerCharacter"))
+ return fromJSON(*TC, R.triggerCharacter);
+ return true;
+}
+
+bool fromJSON(const llvm::json::Value &Params, CompletionParams &R) {
+ if (!fromJSON(Params, static_cast<TextDocumentPositionParams &>(R)))
+ return false;
+ if (auto *Context = Params.getAsObject()->get("context"))
+ return fromJSON(*Context, R.context);
+ return true;
+}
+
+static llvm::StringRef toTextKind(MarkupKind Kind) {
switch (Kind) {
case MarkupKind::PlainText:
return "plaintext";
@@ -560,18 +606,18 @@ static StringRef toTextKind(MarkupKind Kind) {
llvm_unreachable("Invalid MarkupKind");
}
-json::Value toJSON(const MarkupContent &MC) {
+llvm::json::Value toJSON(const MarkupContent &MC) {
if (MC.value.empty())
return nullptr;
- return json::Object{
+ return llvm::json::Object{
{"kind", toTextKind(MC.kind)},
{"value", MC.value},
};
}
-json::Value toJSON(const Hover &H) {
- json::Object Result{{"contents", toJSON(H.contents)}};
+llvm::json::Value toJSON(const Hover &H) {
+ llvm::json::Object Result{{"contents", toJSON(H.contents)}};
if (H.range.hasValue())
Result["range"] = toJSON(*H.range);
@@ -579,7 +625,7 @@ json::Value toJSON(const Hover &H) {
return std::move(Result);
}
-bool fromJSON(const json::Value &E, CompletionItemKind &Out) {
+bool fromJSON(const llvm::json::Value &E, CompletionItemKind &Out) {
if (auto T = E.getAsInteger()) {
if (*T < static_cast<int>(CompletionItemKind::Text) ||
*T > static_cast<int>(CompletionItemKind::TypeParameter))
@@ -592,11 +638,11 @@ bool fromJSON(const 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) {
@@ -612,7 +658,7 @@ adjustKindToCapability(CompletionItemKind Kind,
}
}
-bool fromJSON(const json::Value &E, CompletionItemKindBitset &Out) {
+bool fromJSON(const llvm::json::Value &E, CompletionItemKindBitset &Out) {
if (auto *A = E.getAsArray()) {
for (size_t I = 0; I < A->size(); ++I) {
CompletionItemKind KindOut;
@@ -624,9 +670,9 @@ bool fromJSON(const json::Value &E, CompletionItemKindBitset &Out) {
return false;
}
-json::Value toJSON(const CompletionItem &CI) {
+llvm::json::Value toJSON(const CompletionItem &CI) {
assert(!CI.label.empty() && "completion item label is required");
- json::Object Result{{"label", CI.label}};
+ llvm::json::Object Result{{"label", CI.label}};
if (CI.kind != CompletionItemKind::Missing)
Result["kind"] = static_cast<int>(CI.kind);
if (!CI.detail.empty())
@@ -644,13 +690,13 @@ json::Value toJSON(const CompletionItem &CI) {
if (CI.textEdit)
Result["textEdit"] = *CI.textEdit;
if (!CI.additionalTextEdits.empty())
- Result["additionalTextEdits"] = json::Array(CI.additionalTextEdits);
+ Result["additionalTextEdits"] = llvm::json::Array(CI.additionalTextEdits);
if (CI.deprecated)
Result["deprecated"] = CI.deprecated;
return std::move(Result);
}
-raw_ostream &operator<<(raw_ostream &O, const CompletionItem &I) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const CompletionItem &I) {
O << I.label << " - " << toJSON(I);
return O;
}
@@ -660,63 +706,72 @@ bool operator<(const CompletionItem &L, const CompletionItem &R) {
(R.sortText.empty() ? R.label : R.sortText);
}
-json::Value toJSON(const CompletionList &L) {
- return json::Object{
+llvm::json::Value toJSON(const CompletionList &L) {
+ return llvm::json::Object{
{"isIncomplete", L.isIncomplete},
- {"items", json::Array(L.items)},
+ {"items", llvm::json::Array(L.items)},
};
}
-json::Value toJSON(const ParameterInformation &PI) {
+llvm::json::Value toJSON(const ParameterInformation &PI) {
assert(!PI.label.empty() && "parameter information label is required");
- json::Object Result{{"label", PI.label}};
+ llvm::json::Object Result{{"label", PI.label}};
if (!PI.documentation.empty())
Result["documentation"] = PI.documentation;
return std::move(Result);
}
-json::Value toJSON(const SignatureInformation &SI) {
+llvm::json::Value toJSON(const SignatureInformation &SI) {
assert(!SI.label.empty() && "signature information label is required");
- json::Object Result{
+ llvm::json::Object Result{
{"label", SI.label},
- {"parameters", json::Array(SI.parameters)},
+ {"parameters", llvm::json::Array(SI.parameters)},
};
if (!SI.documentation.empty())
Result["documentation"] = SI.documentation;
return std::move(Result);
}
-raw_ostream &operator<<(raw_ostream &O, const SignatureInformation &I) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
+ const SignatureInformation &I) {
O << I.label << " - " << toJSON(I);
return O;
}
-json::Value toJSON(const SignatureHelp &SH) {
+llvm::json::Value toJSON(const SignatureHelp &SH) {
assert(SH.activeSignature >= 0 &&
"Unexpected negative value for number of active signatures.");
assert(SH.activeParameter >= 0 &&
"Unexpected negative value for active parameter index");
- return json::Object{
+ return llvm::json::Object{
{"activeSignature", SH.activeSignature},
{"activeParameter", SH.activeParameter},
- {"signatures", json::Array(SH.signatures)},
+ {"signatures", llvm::json::Array(SH.signatures)},
};
}
-bool fromJSON(const json::Value &Params, RenameParams &R) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, RenameParams &R) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("textDocument", R.textDocument) &&
O.map("position", R.position) && O.map("newName", R.newName);
}
-json::Value toJSON(const DocumentHighlight &DH) {
- return json::Object{
+llvm::json::Value toJSON(const DocumentHighlight &DH) {
+ return llvm::json::Object{
{"range", toJSON(DH.range)},
{"kind", static_cast<int>(DH.kind)},
};
}
-raw_ostream &operator<<(raw_ostream &O, const DocumentHighlight &V) {
+llvm::json::Value toJSON(const FileStatus &FStatus) {
+ return llvm::json::Object{
+ {"uri", FStatus.uri},
+ {"state", FStatus.state},
+ };
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
+ const DocumentHighlight &V) {
O << V.range;
if (V.kind == DocumentHighlightKind::Read)
O << "(r)";
@@ -725,37 +780,40 @@ raw_ostream &operator<<(raw_ostream &O, const DocumentHighlight &V) {
return O;
}
-bool fromJSON(const json::Value &Params, DidChangeConfigurationParams &CCP) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params,
+ DidChangeConfigurationParams &CCP) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("settings", CCP.settings);
}
-bool fromJSON(const json::Value &Params, ClangdCompileCommand &CDbUpdate) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params,
+ ClangdCompileCommand &CDbUpdate) {
+ llvm::json::ObjectMapper O(Params);
return O && O.map("workingDirectory", CDbUpdate.workingDirectory) &&
O.map("compilationCommand", CDbUpdate.compilationCommand);
}
-bool fromJSON(const json::Value &Params, ConfigurationSettings &S) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, ConfigurationSettings &S) {
+ llvm::json::ObjectMapper O(Params);
if (!O)
return true; // 'any' type in LSP.
O.map("compilationDatabaseChanges", S.compilationDatabaseChanges);
return true;
}
-bool fromJSON(const json::Value &Params, InitializationOptions &Opts) {
- json::ObjectMapper O(Params);
+bool fromJSON(const llvm::json::Value &Params, InitializationOptions &Opts) {
+ llvm::json::ObjectMapper O(Params);
if (!O)
return true; // 'any' type in LSP.
fromJSON(Params, Opts.ConfigSettings);
O.map("compilationDatabasePath", Opts.compilationDatabasePath);
O.map("fallbackFlags", Opts.fallbackFlags);
+ O.map("clangdFileStatus", Opts.FileStatus);
return true;
}
-bool fromJSON(const json::Value &Params, ReferenceParams &R) {
+bool fromJSON(const llvm::json::Value &Params, ReferenceParams &R) {
TextDocumentPositionParams &Base = R;
return fromJSON(Params, Base);
}
diff --git a/clangd/Protocol.h b/clangd/Protocol.h
index 76dcf52a..95a66711 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
//
//===----------------------------------------------------------------------===//
//
@@ -397,6 +396,9 @@ struct InitializationOptions {
// the compilation database doesn't describe an opened file.
// The command used will be approximately `clang $FILE $fallbackFlags`.
std::vector<std::string> fallbackFlags;
+
+ /// Clients supports show file status for textDocument/clangd.fileStatus.
+ bool FileStatus = false;
};
bool fromJSON(const llvm::json::Value &, InitializationOptions &);
@@ -629,6 +631,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
@@ -640,12 +657,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 &);
@@ -667,6 +687,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;
@@ -772,6 +793,31 @@ struct TextDocumentPositionParams {
};
bool fromJSON(const llvm::json::Value &, TextDocumentPositionParams &);
+enum class CompletionTriggerKind {
+ /// Completion was triggered by typing an identifier (24x7 code
+ /// complete), manual invocation (e.g Ctrl+Space) or via API.
+ Invoked = 1,
+ /// Completion was triggered by a trigger character specified by
+ /// the `triggerCharacters` properties of the `CompletionRegistrationOptions`.
+ TriggerCharacter = 2,
+ /// Completion was re-triggered as the current completion list is incomplete.
+ TriggerTriggerForIncompleteCompletions = 3
+};
+
+struct CompletionContext {
+ /// How the completion was triggered.
+ CompletionTriggerKind triggerKind = CompletionTriggerKind::Invoked;
+ /// The trigger character (a single character) that has trigger code complete.
+ /// Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`
+ std::string triggerCharacter;
+};
+bool fromJSON(const llvm::json::Value &, CompletionContext &);
+
+struct CompletionParams : TextDocumentPositionParams {
+ CompletionContext context;
+};
+bool fromJSON(const llvm::json::Value &, CompletionParams &);
+
enum class MarkupKind {
PlainText,
Markdown,
@@ -973,6 +1019,18 @@ struct ReferenceParams : public TextDocumentPositionParams {
};
bool fromJSON(const llvm::json::Value &, ReferenceParams &);
+/// Clangd extension: indicates the current state of the file in clangd,
+/// sent from server via the `textDocument/clangd.fileStatus` notification.
+struct FileStatus {
+ /// The text document's URI.
+ URIForFile uri;
+ /// The human-readable string presents the current state of the file, can be
+ /// shown in the UI (e.g. status bar).
+ std::string state;
+ // FIXME: add detail messages.
+};
+llvm::json::Value toJSON(const FileStatus &FStatus);
+
} // namespace clangd
} // namespace clang
diff --git a/clangd/Quality.cpp b/clangd/Quality.cpp
index fe7a969e..50e3f7ee 100644
--- a/clangd/Quality.cpp
+++ b/clangd/Quality.cpp
@@ -1,9 +1,8 @@
//===--- 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"
@@ -31,10 +30,9 @@
#include <algorithm>
#include <cmath>
-using namespace llvm;
namespace clang {
namespace clangd {
-static bool isReserved(StringRef Name) {
+static bool isReserved(llvm::StringRef Name) {
// FIXME: Should we exclude _Bool and others recognized by the standard?
return Name.size() >= 2 && Name[0] == '_' &&
(isUppercase(Name[1]) || Name[1] == '_');
@@ -249,12 +247,13 @@ float SymbolQualitySignals::evaluate() const {
return Score;
}
-raw_ostream &operator<<(raw_ostream &OS, const SymbolQualitySignals &S) {
- OS << formatv("=== Symbol quality: {0}\n", S.evaluate());
- OS << formatv("\tReferences: {0}\n", S.References);
- OS << formatv("\tDeprecated: {0}\n", S.Deprecated);
- OS << formatv("\tReserved name: {0}\n", S.ReservedName);
- OS << formatv("\tCategory: {0}\n", static_cast<int>(S.Category));
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const SymbolQualitySignals &S) {
+ OS << llvm::formatv("=== Symbol quality: {0}\n", S.evaluate());
+ OS << llvm::formatv("\tReferences: {0}\n", S.References);
+ OS << llvm::formatv("\tDeprecated: {0}\n", S.Deprecated);
+ OS << llvm::formatv("\tReserved name: {0}\n", S.ReservedName);
+ OS << llvm::formatv("\tCategory: {0}\n", static_cast<int>(S.Category));
return OS;
}
@@ -283,12 +282,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) {
@@ -317,7 +316,7 @@ void SymbolRelevanceSignals::merge(const CodeCompletionResult &SemaCCResult) {
NeedsFixIts = !SemaCCResult.FixIts.empty();
}
-static std::pair<float, unsigned> uriProximity(StringRef SymbolURI,
+static std::pair<float, unsigned> uriProximity(llvm::StringRef SymbolURI,
URIDistance *D) {
if (!D || SymbolURI.empty())
return {0.f, 0u};
@@ -327,7 +326,7 @@ static std::pair<float, unsigned> uriProximity(StringRef SymbolURI,
}
static float scopeBoost(ScopeDistance &Distance,
- Optional<StringRef> SymbolScope) {
+ llvm::Optional<llvm::StringRef> SymbolScope) {
if (!SymbolScope)
return 1;
auto D = Distance.distance(*SymbolScope);
@@ -366,7 +365,7 @@ float SymbolRelevanceSignals::evaluate() const {
case GlobalScope:
break;
case FileScope:
- Score *= 1.5;
+ Score *= 1.5f;
break;
case ClassScope:
Score *= 2;
@@ -375,6 +374,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)
@@ -397,33 +409,34 @@ float SymbolRelevanceSignals::evaluate() const {
return Score;
}
-raw_ostream &operator<<(raw_ostream &OS, const SymbolRelevanceSignals &S) {
- OS << formatv("=== Symbol relevance: {0}\n", S.evaluate());
- OS << formatv("\tName match: {0}\n", S.NameMatch);
- OS << formatv("\tForbidden: {0}\n", S.Forbidden);
- OS << formatv("\tNeedsFixIts: {0}\n", S.NeedsFixIts);
- OS << formatv("\tIsInstanceMember: {0}\n", S.IsInstanceMember);
- OS << formatv("\tContext: {0}\n", getCompletionKindString(S.Context));
- OS << formatv("\tQuery type: {0}\n", static_cast<int>(S.Query));
- OS << formatv("\tScope: {0}\n", static_cast<int>(S.Scope));
-
- OS << formatv("\tSymbol URI: {0}\n", S.SymbolURI);
- OS << formatv("\tSymbol scope: {0}\n",
- S.SymbolScope ? *S.SymbolScope : "<None>");
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const SymbolRelevanceSignals &S) {
+ OS << llvm::formatv("=== Symbol relevance: {0}\n", S.evaluate());
+ OS << llvm::formatv("\tName match: {0}\n", S.NameMatch);
+ OS << llvm::formatv("\tForbidden: {0}\n", S.Forbidden);
+ OS << llvm::formatv("\tNeedsFixIts: {0}\n", S.NeedsFixIts);
+ OS << llvm::formatv("\tIsInstanceMember: {0}\n", S.IsInstanceMember);
+ OS << llvm::formatv("\tContext: {0}\n", getCompletionKindString(S.Context));
+ OS << llvm::formatv("\tQuery type: {0}\n", static_cast<int>(S.Query));
+ OS << llvm::formatv("\tScope: {0}\n", static_cast<int>(S.Scope));
+
+ OS << llvm::formatv("\tSymbol URI: {0}\n", S.SymbolURI);
+ OS << llvm::formatv("\tSymbol scope: {0}\n",
+ S.SymbolScope ? *S.SymbolScope : "<None>");
if (S.FileProximityMatch) {
auto Score = uriProximity(S.SymbolURI, S.FileProximityMatch);
- OS << formatv("\tIndex URI proximity: {0} (distance={1})\n", Score.first,
- Score.second);
+ OS << llvm::formatv("\tIndex URI proximity: {0} (distance={1})\n",
+ Score.first, Score.second);
}
- OS << formatv("\tSema file proximity: {0}\n", S.SemaFileProximityScore);
+ OS << llvm::formatv("\tSema file proximity: {0}\n", S.SemaFileProximityScore);
- OS << formatv("\tSema says in scope: {0}\n", S.SemaSaysInScope);
+ OS << llvm::formatv("\tSema says in scope: {0}\n", S.SemaSaysInScope);
if (S.ScopeProximityMatch)
- OS << formatv("\tIndex scope boost: {0}\n",
- scopeBoost(*S.ScopeProximityMatch, S.SymbolScope));
+ OS << llvm::formatv("\tIndex scope boost: {0}\n",
+ scopeBoost(*S.ScopeProximityMatch, S.SymbolScope));
- OS << formatv(
+ OS << llvm::formatv(
"\tType matched preferred: {0} (Context type: {1}, Symbol type: {2}\n",
S.TypeMatchesPreferred, S.HadContextType, S.HadSymbolType);
@@ -441,33 +454,34 @@ static uint32_t encodeFloat(float F) {
constexpr uint32_t TopBit = ~(~uint32_t{0} >> 1);
// Get the bits of the float. Endianness is the same as for integers.
- uint32_t U = FloatToBits(F);
+ uint32_t U = llvm::FloatToBits(F);
// IEEE 754 floats compare like sign-magnitude integers.
if (U & TopBit) // Negative float.
return 0 - U; // Map onto the low half of integers, order reversed.
return U + TopBit; // Positive floats map onto the high half of integers.
}
-std::string sortText(float Score, StringRef Name) {
+std::string sortText(float Score, llvm::StringRef Name) {
// We convert -Score to an integer, and hex-encode for readability.
// Example: [0.5, "foo"] -> "41000000foo"
std::string S;
- raw_string_ostream OS(S);
- write_hex(OS, encodeFloat(-Score), HexPrintStyle::Lower,
- /*Width=*/2 * sizeof(Score));
+ llvm::raw_string_ostream OS(S);
+ llvm::write_hex(OS, encodeFloat(-Score), llvm::HexPrintStyle::Lower,
+ /*Width=*/2 * sizeof(Score));
OS << Name;
OS.flush();
return S;
}
-raw_ostream &operator<<(raw_ostream &OS, const SignatureQualitySignals &S) {
- OS << formatv("=== Signature Quality:\n");
- OS << formatv("\tNumber of parameters: {0}\n", S.NumberOfParameters);
- OS << formatv("\tNumber of optional parameters: {0}\n",
- S.NumberOfOptionalParameters);
- OS << formatv("\tContains active parameter: {0}\n",
- S.ContainsActiveParameter);
- OS << formatv("\tKind: {0}\n", S.Kind);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const SignatureQualitySignals &S) {
+ OS << llvm::formatv("=== Signature Quality:\n");
+ OS << llvm::formatv("\tNumber of parameters: {0}\n", S.NumberOfParameters);
+ OS << llvm::formatv("\tNumber of optional parameters: {0}\n",
+ S.NumberOfOptionalParameters);
+ OS << llvm::formatv("\tContains active parameter: {0}\n",
+ S.ContainsActiveParameter);
+ OS << llvm::formatv("\tKind: {0}\n", S.Kind);
return OS;
}
diff --git a/clangd/Quality.h b/clangd/Quality.h
index 9cb0c2f3..5eea7dbc 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
//
//===----------------------------------------------------------------------===//
///
diff --git a/clangd/RIFF.cpp b/clangd/RIFF.cpp
index 19722b62..cdbae4f7 100644
--- a/clangd/RIFF.cpp
+++ b/clangd/RIFF.cpp
@@ -1,31 +1,29 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
#include "RIFF.h"
#include "llvm/Support/Endian.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace riff {
-static Error makeError(const char *Msg) {
- return createStringError(inconvertibleErrorCode(), Msg);
+static llvm::Error makeError(const char *Msg) {
+ return llvm::createStringError(llvm::inconvertibleErrorCode(), Msg);
}
-Expected<Chunk> readChunk(StringRef &Stream) {
+llvm::Expected<Chunk> readChunk(llvm::StringRef &Stream) {
if (Stream.size() < 8)
return makeError("incomplete chunk header");
Chunk C;
std::copy(Stream.begin(), Stream.begin() + 4, C.ID.begin());
Stream = Stream.drop_front(4);
- uint32_t Len = support::endian::read32le(Stream.take_front(4).begin());
+ uint32_t Len = llvm::support::endian::read32le(Stream.take_front(4).begin());
Stream = Stream.drop_front(4);
if (Stream.size() < Len)
return makeError("truncated chunk");
@@ -39,10 +37,10 @@ Expected<Chunk> readChunk(StringRef &Stream) {
return std::move(C);
}
-raw_ostream &operator<<(raw_ostream &OS, const Chunk &C) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Chunk &C) {
OS.write(C.ID.data(), C.ID.size());
char Size[4];
- support::endian::write32le(Size, C.Data.size());
+ llvm::support::endian::write32le(Size, C.Data.size());
OS.write(Size, sizeof(Size));
OS << C.Data;
if (C.Data.size() % 2)
@@ -50,7 +48,7 @@ raw_ostream &operator<<(raw_ostream &OS, const Chunk &C) {
return OS;
}
-Expected<File> readFile(StringRef Stream) {
+llvm::Expected<File> readFile(llvm::StringRef Stream) {
auto RIFF = readChunk(Stream);
if (!RIFF)
return RIFF.takeError();
@@ -60,7 +58,7 @@ Expected<File> readFile(StringRef Stream) {
return makeError("RIFF chunk too short");
File F;
std::copy(RIFF->Data.begin(), RIFF->Data.begin() + 4, F.Type.begin());
- for (StringRef Body = RIFF->Data.drop_front(4); !Body.empty();)
+ for (llvm::StringRef Body = RIFF->Data.drop_front(4); !Body.empty();)
if (auto Chunk = readChunk(Body)) {
F.Chunks.push_back(*Chunk);
} else
@@ -68,14 +66,14 @@ Expected<File> readFile(StringRef Stream) {
return std::move(F);
}
-raw_ostream &operator<<(raw_ostream &OS, const File &F) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const File &F) {
// To avoid copies, we serialize the outer RIFF chunk "by hand".
size_t DataLen = 4; // Predict length of RIFF chunk data.
for (const auto &C : F.Chunks)
DataLen += 4 + 4 + C.Data.size() + (C.Data.size() % 2);
OS << "RIFF";
char Size[4];
- support::endian::write32le(Size, DataLen);
+ llvm::support::endian::write32le(Size, DataLen);
OS.write(Size, sizeof(Size));
OS.write(F.Type.data(), F.Type.size());
for (const auto &C : F.Chunks)
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..d1ea30e7
--- /dev/null
+++ b/clangd/Selection.cpp
@@ -0,0 +1,301 @@
+//===--- 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;
+ assert(R.isTokenRange());
+ // 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
+ 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 4d276ef2..86146758 100644
--- a/clangd/SourceCode.cpp
+++ b/clangd/SourceCode.cpp
@@ -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
//
//===----------------------------------------------------------------------===//
#include "SourceCode.h"
@@ -12,11 +11,12 @@
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Path.h"
-using namespace llvm;
namespace clang {
namespace clangd {
@@ -27,7 +27,7 @@ namespace clangd {
// invokes CB(UTF-8 length, UTF-16 length), and breaks if it returns true.
// Returns true if CB returned true, false if we hit the end of string.
template <typename Callback>
-static bool iterateCodepoints(StringRef U8, const Callback &CB) {
+static bool iterateCodepoints(llvm::StringRef U8, const Callback &CB) {
for (size_t I = 0; I < U8.size();) {
unsigned char C = static_cast<unsigned char>(U8[I]);
if (LLVM_LIKELY(!(C & 0x80))) { // ASCII character.
@@ -37,7 +37,7 @@ static bool iterateCodepoints(StringRef U8, const Callback &CB) {
continue;
}
// This convenient property of UTF-8 holds for all non-ASCII characters.
- size_t UTF8Length = countLeadingOnes(C);
+ size_t UTF8Length = llvm::countLeadingOnes(C);
// 0xxx is ASCII, handled above. 10xxx is a trailing byte, invalid here.
// 11111xxx is not valid UTF-8 at all. Assert because it's probably our bug.
assert((UTF8Length >= 2 && UTF8Length <= 4) &&
@@ -54,7 +54,7 @@ static bool iterateCodepoints(StringRef U8, const Callback &CB) {
// 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(StringRef U8, int U16Units, bool &Valid) {
+static size_t measureUTF16(llvm::StringRef U8, int U16Units, bool &Valid) {
size_t Result = 0;
Valid = U16Units == 0 || iterateCodepoints(U8, [&](int U8Len, int U16Len) {
Result += U8Len;
@@ -68,7 +68,7 @@ static size_t measureUTF16(StringRef U8, int U16Units, bool &Valid) {
}
// Like most strings in clangd, the input is UTF-8 encoded.
-size_t lspLength(StringRef Code) {
+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;
@@ -79,47 +79,47 @@ size_t lspLength(StringRef Code) {
return Count;
}
-Expected<size_t> positionToOffset(StringRef Code, Position P,
- bool AllowColumnsBeyondLineLength) {
+llvm::Expected<size_t> positionToOffset(llvm::StringRef Code, Position P,
+ bool AllowColumnsBeyondLineLength) {
if (P.line < 0)
- return make_error<StringError>(
- formatv("Line value can't be negative ({0})", P.line),
- errc::invalid_argument);
+ return llvm::make_error<llvm::StringError>(
+ llvm::formatv("Line value can't be negative ({0})", P.line),
+ llvm::errc::invalid_argument);
if (P.character < 0)
- return make_error<StringError>(
- formatv("Character value can't be negative ({0})", P.character),
- errc::invalid_argument);
+ return llvm::make_error<llvm::StringError>(
+ llvm::formatv("Character value can't be negative ({0})", P.character),
+ llvm::errc::invalid_argument);
size_t StartOfLine = 0;
for (int I = 0; I != P.line; ++I) {
size_t NextNL = Code.find('\n', StartOfLine);
- if (NextNL == StringRef::npos)
- return make_error<StringError>(
- formatv("Line value is out of range ({0})", P.line),
- errc::invalid_argument);
+ if (NextNL == llvm::StringRef::npos)
+ return llvm::make_error<llvm::StringError>(
+ llvm::formatv("Line value is out of range ({0})", P.line),
+ llvm::errc::invalid_argument);
StartOfLine = NextNL + 1;
}
size_t NextNL = Code.find('\n', StartOfLine);
- if (NextNL == StringRef::npos)
+ if (NextNL == llvm::StringRef::npos)
NextNL = Code.size();
bool Valid;
size_t ByteOffsetInLine = measureUTF16(
Code.substr(StartOfLine, NextNL - StartOfLine), P.character, Valid);
if (!Valid && !AllowColumnsBeyondLineLength)
- return make_error<StringError>(
- formatv("UTF-16 offset {0} is invalid for line {1}", P.character,
- P.line),
- errc::invalid_argument);
+ return llvm::make_error<llvm::StringError>(
+ llvm::formatv("UTF-16 offset {0} is invalid for line {1}", P.character,
+ P.line),
+ llvm::errc::invalid_argument);
return StartOfLine + ByteOffsetInLine;
}
-Position offsetToPosition(StringRef Code, size_t Offset) {
+Position offsetToPosition(llvm::StringRef Code, size_t Offset) {
Offset = std::min(Code.size(), Offset);
- StringRef Before = Code.substr(0, Offset);
+ llvm::StringRef Before = Code.substr(0, Offset);
int Lines = Before.count('\n');
size_t PrevNL = Before.rfind('\n');
- size_t StartOfLine = (PrevNL == StringRef::npos) ? 0 : (PrevNL + 1);
+ size_t StartOfLine = (PrevNL == llvm::StringRef::npos) ? 0 : (PrevNL + 1);
Position Pos;
Pos.line = Lines;
Pos.character = lspLength(Before.substr(StartOfLine));
@@ -134,7 +134,7 @@ Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc) {
Position P;
P.line = static_cast<int>(SM.getLineNumber(FID, Offset)) - 1;
bool Invalid = false;
- StringRef Code = SM.getBufferData(FID, &Invalid);
+ llvm::StringRef Code = SM.getBufferData(FID, &Invalid);
if (!Invalid) {
auto ColumnInBytes = SM.getColumnNumber(FID, Offset) - 1;
auto LineSoFar = Code.substr(Offset - ColumnInBytes, ColumnInBytes);
@@ -143,6 +143,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());
@@ -151,31 +224,32 @@ Range halfOpenToRange(const SourceManager &SM, CharSourceRange R) {
return {Begin, End};
}
-std::pair<size_t, size_t> offsetToClangLineColumn(StringRef Code,
+std::pair<size_t, size_t> offsetToClangLineColumn(llvm::StringRef Code,
size_t Offset) {
Offset = std::min(Code.size(), Offset);
- StringRef Before = Code.substr(0, Offset);
+ llvm::StringRef Before = Code.substr(0, Offset);
int Lines = Before.count('\n');
size_t PrevNL = Before.rfind('\n');
- size_t StartOfLine = (PrevNL == StringRef::npos) ? 0 : (PrevNL + 1);
+ size_t StartOfLine = (PrevNL == llvm::StringRef::npos) ? 0 : (PrevNL + 1);
return {Lines + 1, Offset - StartOfLine + 1};
}
std::pair<StringRef, StringRef> splitQualifiedName(StringRef QName) {
size_t Pos = QName.rfind("::");
- if (Pos == StringRef::npos)
- return {StringRef(), QName};
+ if (Pos == llvm::StringRef::npos)
+ return {llvm::StringRef(), QName};
return {QName.substr(0, Pos + 2), QName.substr(Pos + 2)};
}
-TextEdit replacementToEdit(StringRef Code, const tooling::Replacement &R) {
+TextEdit replacementToEdit(llvm::StringRef Code,
+ const tooling::Replacement &R) {
Range ReplacementRange = {
offsetToPosition(Code, R.getOffset()),
offsetToPosition(Code, R.getOffset() + R.getLength())};
return {ReplacementRange, R.getReplacementText()};
}
-std::vector<TextEdit> replacementsToEdits(StringRef Code,
+std::vector<TextEdit> replacementsToEdits(llvm::StringRef Code,
const tooling::Replacements &Repls) {
std::vector<TextEdit> Edits;
for (const auto &R : Repls)
@@ -183,34 +257,43 @@ std::vector<TextEdit> replacementsToEdits(StringRef Code,
return Edits;
}
-Optional<std::string> getRealPath(const FileEntry *F,
- const SourceManager &SourceMgr) {
- // Ideally, we get the real path from the FileEntry object.
- SmallString<128> FilePath = F->tryGetRealPathName();
- if (!FilePath.empty()) {
- return FilePath.str().str();
- }
-
- // Otherwise, we try to compute ourselves.
- vlog("FileEntry for {0} did not contain the real path.", F->getName());
-
- SmallString<128> Path = F->getName();
+llvm::Optional<std::string> getCanonicalPath(const FileEntry *F,
+ const SourceManager &SourceMgr) {
+ if (!F)
+ return None;
- if (!sys::path::is_absolute(Path)) {
- if (!SourceMgr.getFileManager().makeAbsolutePath(Path)) {
- log("Could not turn relative path to absolute: {0}", Path);
+ llvm::SmallString<128> FilePath = F->getName();
+ if (!llvm::sys::path::is_absolute(FilePath)) {
+ if (auto EC =
+ SourceMgr.getFileManager().getVirtualFileSystem()->makeAbsolute(
+ FilePath)) {
+ elog("Could not turn relative path '{0}' to absolute: {1}", FilePath,
+ EC.message());
return None;
}
}
- SmallString<128> RealPath;
- if (SourceMgr.getFileManager().getVirtualFileSystem()->getRealPath(
- Path, RealPath)) {
- log("Could not compute real path: {0}", Path);
- return Path.str().str();
+ // Handle the symbolic link path case where the current working directory
+ // (getCurrentWorkingDirectory) is a symlink./ We always want to the real
+ // file path (instead of the symlink path) for the C++ symbols.
+ //
+ // Consider the following example:
+ //
+ // src dir: /project/src/foo.h
+ // current working directory (symlink): /tmp/build -> /project/src/
+ //
+ // The file path of Symbol is "/project/src/foo.h" instead of
+ // "/tmp/build/foo.h"
+ if (const DirectoryEntry *Dir = SourceMgr.getFileManager().getDirectory(
+ llvm::sys::path::parent_path(FilePath))) {
+ llvm::SmallString<128> RealPath;
+ llvm::StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
+ llvm::sys::path::append(RealPath, DirName,
+ llvm::sys::path::filename(FilePath));
+ return RealPath.str().str();
}
- return RealPath.str().str();
+ return FilePath.str().str();
}
TextEdit toTextEdit(const FixItHint &FixIt, const SourceManager &M,
@@ -222,22 +305,44 @@ 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;
}
-FileDigest digest(StringRef Content) {
+FileDigest digest(llvm::StringRef Content) {
return llvm::SHA1::hash({(const uint8_t *)Content.data(), Content.size()});
}
-Optional<FileDigest> digestFile(const SourceManager &SM, FileID FID) {
+llvm::Optional<FileDigest> digestFile(const SourceManager &SM, FileID FID) {
bool Invalid = false;
- StringRef Content = SM.getBufferData(FID, &Invalid);
+ llvm::StringRef Content = SM.getBufferData(FID, &Invalid);
if (Invalid)
return None;
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);
+}
+
} // namespace clangd
} // namespace clang
diff --git a/clangd/SourceCode.h b/clangd/SourceCode.h
index 769d0afc..e6ce8c3b 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
//
//===----------------------------------------------------------------------===//
//
@@ -15,9 +14,12 @@
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SOURCECODE_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/StringRef.h"
#include "llvm/Support/SHA1.h"
namespace clang {
@@ -55,6 +57,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);
@@ -78,19 +125,30 @@ std::vector<TextEdit> replacementsToEdits(StringRef Code,
TextEdit toTextEdit(const FixItHint &FixIt, const SourceManager &M,
const LangOptions &L);
-/// Get the real/canonical path of \p F. This means:
+/// Get the canonical path of \p F. This means:
///
/// - Absolute path
/// - Symlinks resolved
/// - No "." or ".." component
/// - No duplicate or trailing directory separator
///
-/// This function should be used when sending paths to clients, so that paths
-/// are normalized as much as possible.
-llvm::Optional<std::string> getRealPath(const FileEntry *F,
- const SourceManager &SourceMgr);
+/// This function should be used when paths needs to be used outside the
+/// component that generate it, so that paths are normalized as much as
+/// possible.
+llvm::Optional<std::string> getCanonicalPath(const FileEntry *F,
+ const SourceManager &SourceMgr);
+
+bool isRangeConsecutive(const Range &Left, const Range &Right);
+
+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);
-bool IsRangeConsecutive(const Range &Left, const Range &Right);
} // namespace clangd
} // namespace clang
#endif
diff --git a/clangd/TUScheduler.cpp b/clangd/TUScheduler.cpp
index 764bc26a..c7730827 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
@@ -18,8 +17,8 @@
// preamble. However, unlike AST, the same preamble can be read concurrently, so
// we run each of async preamble reads on its own thread.
//
-// To limit the concurrent load that clangd produces we maintain a semaphore that
-// keeps more than a fixed number of threads from running concurrently.
+// To limit the concurrent load that clangd produces we maintain a semaphore
+// that keeps more than a fixed number of threads from running concurrently.
//
// Rationale for cancelling updates.
// LSP clients can send updates to clangd on each keystroke. Some files take
@@ -46,6 +45,7 @@
#include "Cancellation.h"
#include "Logger.h"
#include "Trace.h"
+#include "index/CanonicalIncludes.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/PCHContainerOperations.h"
#include "llvm/ADT/ScopeExit.h"
@@ -56,20 +56,19 @@
#include <queue>
#include <thread>
-using namespace llvm;
namespace clang {
namespace clangd {
using std::chrono::steady_clock;
namespace {
class ASTWorker;
-}
+} // namespace
static clang::clangd::Key<std::string> kFileBeingProcessed;
-Optional<StringRef> TUScheduler::getFileBeingProcessedInContext() {
+llvm::Optional<llvm::StringRef> TUScheduler::getFileBeingProcessedInContext() {
if (auto *File = Context::current().get(kFileBeingProcessed))
- return StringRef(*File);
+ return llvm::StringRef(*File);
return None;
}
@@ -113,7 +112,7 @@ public:
/// Returns the cached value for \p K, or llvm::None if the value is not in
/// the cache anymore. If nullptr was cached for \p K, this function will
/// return a null unique_ptr wrapped into an optional.
- Optional<std::unique_ptr<ParsedAST>> take(Key K) {
+ llvm::Optional<std::unique_ptr<ParsedAST>> take(Key K) {
std::unique_lock<std::mutex> Lock(Mut);
auto Existing = findByKey(K);
if (Existing == LRU.end())
@@ -123,7 +122,7 @@ public:
// GCC 4.8 fails to compile `return V;`, as it tries to call the copy
// constructor of unique_ptr, so we call the move ctor explicitly to avoid
// this miscompile.
- return Optional<std::unique_ptr<ParsedAST>>(std::move(V));
+ return llvm::Optional<std::unique_ptr<ParsedAST>>(std::move(V));
}
private:
@@ -177,15 +176,16 @@ public:
~ASTWorker();
void update(ParseInputs Inputs, WantDiagnostics);
- void runWithAST(StringRef Name,
- unique_function<void(Expected<InputsAndAST>)> Action);
+ void
+ runWithAST(llvm::StringRef Name,
+ llvm::unique_function<void(llvm::Expected<InputsAndAST>)> Action);
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(
- unique_function<void(std::shared_ptr<const PreambleData>)>);
+ llvm::unique_function<void(std::shared_ptr<const PreambleData>)>);
/// 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
@@ -203,8 +203,8 @@ private:
/// Signal that run() should finish processing pending requests and exit.
void stop();
/// Adds a new task to the end of the request queue.
- void startTask(StringRef Name, unique_function<void()> Task,
- Optional<WantDiagnostics> UpdateType);
+ void startTask(llvm::StringRef Name, llvm::unique_function<void()> Task,
+ llvm::Optional<WantDiagnostics> UpdateType);
/// Updates the TUStatus and emits it. Only called in the worker thread.
void emitTUStatus(TUAction FAction,
const TUStatus::BuildDetails *Detail = nullptr);
@@ -218,11 +218,11 @@ private:
bool shouldSkipHeadLocked() const;
struct Request {
- unique_function<void()> Action;
+ llvm::unique_function<void()> Action;
std::string Name;
steady_clock::time_point AddTime;
Context Ctx;
- Optional<WantDiagnostics> UpdateType;
+ llvm::Optional<WantDiagnostics> UpdateType;
};
/// Handles retention of ASTs.
@@ -321,7 +321,7 @@ ASTWorkerHandle ASTWorker::create(PathRef FileName,
FileName, IdleASTs, Barrier, /*RunSync=*/!Tasks, UpdateDebounce,
std::move(PCHs), StorePreamblesInMemory, Callbacks));
if (Tasks)
- Tasks->runAsync("worker:" + sys::path::filename(FileName),
+ Tasks->runAsync("worker:" + llvm::sys::path::filename(FileName),
[Worker]() { Worker->run(); });
return ASTWorkerHandle(std::move(Worker));
@@ -334,8 +334,9 @@ ASTWorker::ASTWorker(PathRef FileName, TUScheduler::ASTCache &LRUCache,
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()},
+ Callbacks(Callbacks),
+ PCHs(std::move(PCHs)), Status{TUAction(TUAction::Idle, ""),
+ TUStatus::BuildDetails()},
Barrier(Barrier), Done(false) {}
ASTWorker::~ASTWorker() {
@@ -349,7 +350,7 @@ ASTWorker::~ASTWorker() {
}
void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
- StringRef TaskName = "Update";
+ llvm::StringRef TaskName = "Update";
auto Task = [=]() mutable {
// Will be used to check if we can avoid rebuilding the AST.
bool InputsAreTheSame =
@@ -363,7 +364,7 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
emitTUStatus({TUAction::BuildingPreamble, TaskName});
log("Updating file {0} with command [{1}] {2}", FileName,
Inputs.CompileCommand.Directory,
- join(Inputs.CompileCommand.CommandLine, " "));
+ llvm::join(Inputs.CompileCommand.CommandLine, " "));
// Rebuild the preamble and the AST.
std::unique_ptr<CompilerInvocation> Invocation =
buildCompilerInvocation(Inputs);
@@ -385,8 +386,9 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
std::shared_ptr<const PreambleData> NewPreamble = buildPreamble(
FileName, *Invocation, OldPreamble, OldCommand, Inputs, PCHs,
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);
@@ -436,9 +438,9 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
}
// Get the AST for diagnostics.
- Optional<std::unique_ptr<ParsedAST>> AST = IdleASTs.take(this);
+ llvm::Optional<std::unique_ptr<ParsedAST>> AST = IdleASTs.take(this);
if (!AST) {
- Optional<ParsedAST> NewAST =
+ llvm::Optional<ParsedAST> NewAST =
buildAST(FileName, std::move(Invocation), Inputs, NewPreamble, PCHs);
AST = NewAST ? llvm::make_unique<ParsedAST>(std::move(*NewAST)) : nullptr;
if (!(*AST)) { // buildAST fails.
@@ -473,16 +475,17 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
}
void ASTWorker::runWithAST(
- StringRef Name, unique_function<void(Expected<InputsAndAST>)> Action) {
+ llvm::StringRef Name,
+ llvm::unique_function<void(llvm::Expected<InputsAndAST>)> Action) {
auto Task = [=](decltype(Action) Action) {
if (isCancelled())
- return Action(make_error<CancelledError>());
- Optional<std::unique_ptr<ParsedAST>> AST = IdleASTs.take(this);
+ return Action(llvm::make_error<CancelledError>());
+ llvm::Optional<std::unique_ptr<ParsedAST>> AST = IdleASTs.take(this);
if (!AST) {
std::unique_ptr<CompilerInvocation> Invocation =
buildCompilerInvocation(FileInputs);
// Try rebuilding the AST.
- Optional<ParsedAST> NewAST =
+ llvm::Optional<ParsedAST> NewAST =
Invocation
? buildAST(FileName,
llvm::make_unique<CompilerInvocation>(*Invocation),
@@ -491,12 +494,12 @@ void ASTWorker::runWithAST(
AST = NewAST ? llvm::make_unique<ParsedAST>(std::move(*NewAST)) : nullptr;
}
// Make sure we put the AST back into the LRU cache.
- auto _ = make_scope_exit(
+ auto _ = llvm::make_scope_exit(
[&AST, this]() { IdleASTs.put(this, std::move(*AST)); });
// Run the user-provided action.
if (!*AST)
- return Action(
- make_error<StringError>("invalid AST", errc::invalid_argument));
+ return Action(llvm::make_error<llvm::StringError>(
+ "invalid AST", llvm::errc::invalid_argument));
Action(InputsAndAST{FileInputs, **AST});
};
startTask(Name, Bind(Task, std::move(Action)),
@@ -510,7 +513,7 @@ ASTWorker::getPossiblyStalePreamble() const {
}
void ASTWorker::getCurrentPreamble(
- unique_function<void(std::shared_ptr<const PreambleData>)> Callback) {
+ llvm::unique_function<void(std::shared_ptr<const PreambleData>)> Callback) {
// We could just call startTask() to throw the read on the queue, knowing
// it will run after any updates. But we know this task is cheap, so to
// improve latency we cheat: insert it on the queue after the last update.
@@ -537,9 +540,7 @@ void ASTWorker::getCurrentPreamble(
RequestsCV.notify_all();
}
-void ASTWorker::waitForFirstPreamble() const {
- PreambleWasBuilt.wait();
-}
+void ASTWorker::waitForFirstPreamble() const { PreambleWasBuilt.wait(); }
std::size_t ASTWorker::getUsedBytes() const {
// Note that we don't report the size of ASTs currently used for processing
@@ -566,11 +567,12 @@ void ASTWorker::stop() {
RequestsCV.notify_all();
}
-void ASTWorker::startTask(StringRef Name, unique_function<void()> Task,
- Optional<WantDiagnostics> UpdateType) {
+void ASTWorker::startTask(llvm::StringRef Name,
+ llvm::unique_function<void()> Task,
+ llvm::Optional<WantDiagnostics> UpdateType) {
if (RunSync) {
assert(!Done && "running a task after stop()");
- trace::Span Tracer(Name + ":" + sys::path::filename(FileName));
+ trace::Span Tracer(Name + ":" + llvm::sys::path::filename(FileName));
Task();
return;
}
@@ -612,8 +614,8 @@ void ASTWorker::run() {
}
// Tracing: we have a next request, attribute this sleep to it.
- Optional<WithContext> Ctx;
- Optional<trace::Span> Tracer;
+ llvm::Optional<WithContext> Ctx;
+ llvm::Optional<trace::Span> Tracer;
if (!Requests.empty()) {
Ctx.emplace(Requests.front().Ctx.clone());
Tracer.emplace("Debounce");
@@ -729,6 +731,33 @@ bool ASTWorker::blockUntilIdle(Deadline Timeout) const {
return wait(Lock, RequestsCV, Timeout, [&] { return Requests.empty(); });
}
+// Render a TUAction to a user-facing string representation.
+// TUAction represents clangd-internal states, we don't intend to expose them
+// to users (say C++ programmers) directly to avoid confusion, we use terms that
+// are familiar by C++ programmers.
+std::string renderTUAction(const TUAction &Action) {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+ switch (Action.S) {
+ case TUAction::Queued:
+ OS << "file is queued";
+ break;
+ case TUAction::RunningAction:
+ OS << "running " << Action.Name;
+ break;
+ case TUAction::BuildingPreamble:
+ OS << "parsing includes";
+ break;
+ case TUAction::BuildingFile:
+ OS << "parsing main file";
+ break;
+ case TUAction::Idle:
+ OS << "idle";
+ break;
+ }
+ return OS.str();
+}
+
} // namespace
unsigned getDefaultAsyncThreadsCount() {
@@ -741,6 +770,13 @@ unsigned getDefaultAsyncThreadsCount() {
return HardwareConcurrency;
}
+FileStatus TUStatus::render(PathRef File) const {
+ FileStatus FStatus;
+ FStatus.uri = URIForFile::canonicalize(File, /*TUPath=*/File);
+ FStatus.state = renderTUAction(Action);
+ return FStatus;
+}
+
struct TUScheduler::FileData {
/// Latest inputs, passed to TUScheduler::update().
std::string Contents;
@@ -811,19 +847,20 @@ void TUScheduler::remove(PathRef File) {
File);
}
-void TUScheduler::run(StringRef Name, unique_function<void()> Action) {
+void TUScheduler::run(llvm::StringRef Name,
+ llvm::unique_function<void()> Action) {
if (!PreambleTasks)
return Action();
PreambleTasks->runAsync(Name, std::move(Action));
}
void TUScheduler::runWithAST(
- StringRef Name, PathRef File,
- unique_function<void(Expected<InputsAndAST>)> Action) {
+ llvm::StringRef Name, PathRef File,
+ llvm::unique_function<void(llvm::Expected<InputsAndAST>)> Action) {
auto It = Files.find(File);
if (It == Files.end()) {
- Action(make_error<LSPError>("trying to get AST for non-added document",
- ErrorCode::InvalidParams));
+ Action(llvm::make_error<LSPError>(
+ "trying to get AST for non-added document", ErrorCode::InvalidParams));
return;
}
@@ -831,12 +868,13 @@ void TUScheduler::runWithAST(
}
void TUScheduler::runWithPreamble(
- StringRef Name, PathRef File, PreambleConsistency Consistency,
- unique_function<void(Expected<InputsAndPreamble>)> Action) {
+ llvm::StringRef Name, PathRef File, PreambleConsistency Consistency,
+ llvm::unique_function<void(llvm::Expected<InputsAndPreamble>)> Action) {
auto It = Files.find(File);
if (It == Files.end()) {
- Action(make_error<LSPError>("trying to get preamble for non-added document",
- ErrorCode::InvalidParams));
+ Action(llvm::make_error<LSPError>(
+ "trying to get preamble for non-added document",
+ ErrorCode::InvalidParams));
return;
}
@@ -888,7 +926,7 @@ void TUScheduler::runWithPreamble(
};
PreambleTasks->runAsync(
- "task:" + sys::path::filename(File),
+ "task:" + llvm::sys::path::filename(File),
Bind(Task, std::string(Name), std::string(File), It->second->Contents,
It->second->Command,
Context::current().derive(kFileBeingProcessed, File),
diff --git a/clangd/TUScheduler.h b/clangd/TUScheduler.h
index cf04c1f9..abcf4aa3 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
//
//===----------------------------------------------------------------------===//
@@ -13,6 +12,7 @@
#include "ClangdUnit.h"
#include "Function.h"
#include "Threading.h"
+#include "index/CanonicalIncludes.h"
#include "llvm/ADT/StringMap.h"
#include <future>
@@ -62,7 +62,7 @@ struct TUAction {
Idle, // Indicates the worker thread is idle, and ready to run any upcoming
// actions.
};
- TUAction(State S, llvm::StringRef Name) : S(S), Name(Name){};
+ TUAction(State S, llvm::StringRef Name) : S(S), Name(Name) {}
State S;
/// The name of the action currently running, e.g. Update, GoToDef, Hover.
/// Empty if we are in the idle state.
@@ -77,6 +77,8 @@ struct TUStatus {
/// Indicates whether we reused the prebuilt AST.
bool ReuseAST = false;
};
+ /// Serialize this to an LSP file status item.
+ FileStatus render(PathRef File) const;
TUAction Action;
BuildDetails Details;
@@ -90,7 +92,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.
@@ -224,12 +227,13 @@ private:
/// propagated.
template <typename T>
std::future<T> runAsync(llvm::unique_function<T()> Action) {
- return std::async(std::launch::async,
- [](llvm::unique_function<T()> &&Action, Context Ctx) {
- WithContext WithCtx(std::move(Ctx));
- return Action();
- },
- std::move(Action), Context::current().clone());
+ return std::async(
+ std::launch::async,
+ [](llvm::unique_function<T()> &&Action, Context Ctx) {
+ WithContext WithCtx(std::move(Ctx));
+ return Action();
+ },
+ std::move(Action), Context::current().clone());
}
} // namespace clangd
diff --git a/clangd/Threading.cpp b/clangd/Threading.cpp
index abfe0f49..139fcc2f 100644
--- a/clangd/Threading.cpp
+++ b/clangd/Threading.cpp
@@ -9,7 +9,6 @@
#include <pthread.h>
#endif
-using namespace llvm;
namespace clang {
namespace clangd {
@@ -64,14 +63,14 @@ bool AsyncTaskRunner::wait(Deadline D) const {
[&] { return InFlightTasks == 0; });
}
-void AsyncTaskRunner::runAsync(const Twine &Name,
- unique_function<void()> Action) {
+void AsyncTaskRunner::runAsync(const llvm::Twine &Name,
+ llvm::unique_function<void()> Action) {
{
std::lock_guard<std::mutex> Lock(Mutex);
++InFlightTasks;
}
- auto CleanupTask = make_scope_exit([this]() {
+ auto CleanupTask = llvm::make_scope_exit([this]() {
std::lock_guard<std::mutex> Lock(Mutex);
int NewTasksCnt = --InFlightTasks;
if (NewTasksCnt == 0) {
@@ -83,7 +82,7 @@ void AsyncTaskRunner::runAsync(const Twine &Name,
std::thread(
[](std::string Name, decltype(Action) Action, decltype(CleanupTask)) {
- set_thread_name(Name);
+ llvm::set_thread_name(Name);
Action();
// Make sure function stored by Action is destroyed before CleanupTask
// is run.
@@ -93,7 +92,7 @@ void AsyncTaskRunner::runAsync(const Twine &Name,
.detach();
}
-Deadline timeoutSeconds(Optional<double> Seconds) {
+Deadline timeoutSeconds(llvm::Optional<double> Seconds) {
using namespace std::chrono;
if (!Seconds)
return Deadline::infinity();
diff --git a/clangd/Threading.h b/clangd/Threading.h
index 4c553288..3c1f8916 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/Trace.cpp b/clangd/Trace.cpp
index 8fb19cc8..d650013b 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
//
//===----------------------------------------------------------------------===//
@@ -19,7 +18,6 @@
#include <atomic>
#include <mutex>
-using namespace llvm;
namespace clang {
namespace clangd {
namespace trace {
@@ -29,16 +27,16 @@ namespace {
// Perhaps we should replace this by something that disturbs performance less.
class JSONTracer : public EventTracer {
public:
- JSONTracer(raw_ostream &Out, bool Pretty)
+ JSONTracer(llvm::raw_ostream &Out, bool Pretty)
: Out(Out), Sep(""), Start(std::chrono::system_clock::now()),
JSONFormat(Pretty ? "{0:2}" : "{0}") {
// The displayTimeUnit must be ns to avoid low-precision overlap
// calculations!
Out << R"({"displayTimeUnit":"ns","traceEvents":[)"
<< "\n";
- rawEvent("M", json::Object{
+ rawEvent("M", llvm::json::Object{
{"name", "process_name"},
- {"args", json::Object{{"name", "clangd"}}},
+ {"args", llvm::json::Object{{"name", "clangd"}}},
});
}
@@ -49,7 +47,7 @@ public:
// We stash a Span object in the context. It will record the start/end,
// and this also allows us to look up the parent Span's information.
- Context beginSpan(StringRef Name, json::Object *Args) override {
+ Context beginSpan(llvm::StringRef Name, llvm::json::Object *Args) override {
return Context::current().derive(
SpanKey, llvm::make_unique<JSONSpan>(this, Name, Args));
}
@@ -62,15 +60,16 @@ public:
Context::current().getExisting(SpanKey)->markEnded();
}
- void instant(StringRef Name, json::Object &&Args) override {
+ void instant(llvm::StringRef Name, llvm::json::Object &&Args) override {
captureThreadMetadata();
- jsonEvent("i", json::Object{{"name", Name}, {"args", std::move(Args)}});
+ jsonEvent("i",
+ llvm::json::Object{{"name", Name}, {"args", std::move(Args)}});
}
// Record an event on the current thread. ph, pid, tid, ts are set.
// Contents must be a list of the other JSON key/values.
- void jsonEvent(StringRef Phase, json::Object &&Contents,
- uint64_t TID = get_threadid(), double Timestamp = 0) {
+ void jsonEvent(llvm::StringRef Phase, llvm::json::Object &&Contents,
+ uint64_t TID = llvm::get_threadid(), double Timestamp = 0) {
Contents["ts"] = Timestamp ? Timestamp : timestamp();
Contents["tid"] = int64_t(TID);
std::lock_guard<std::mutex> Lock(Mu);
@@ -80,9 +79,9 @@ public:
private:
class JSONSpan {
public:
- JSONSpan(JSONTracer *Tracer, StringRef Name, json::Object *Args)
+ JSONSpan(JSONTracer *Tracer, llvm::StringRef Name, llvm::json::Object *Args)
: StartTime(Tracer->timestamp()), EndTime(0), Name(Name),
- TID(get_threadid()), Tracer(Tracer), Args(Args) {
+ TID(llvm::get_threadid()), Tracer(Tracer), Args(Args) {
// ~JSONSpan() may run in a different thread, so we need to capture now.
Tracer->captureThreadMetadata();
@@ -100,33 +99,33 @@ private:
OriginTime = (*Parent)->StartTime;
auto FlowID = nextID();
- Tracer->jsonEvent("s",
- json::Object{{"id", FlowID},
- {"name", "Context crosses threads"},
- {"cat", "dummy"}},
- (*Parent)->TID, (*Parent)->StartTime);
- Tracer->jsonEvent("f",
- json::Object{{"id", FlowID},
- {"bp", "e"},
- {"name", "Context crosses threads"},
- {"cat", "dummy"}},
- TID);
+ Tracer->jsonEvent(
+ "s",
+ llvm::json::Object{{"id", FlowID},
+ {"name", "Context crosses threads"},
+ {"cat", "dummy"}},
+ (*Parent)->TID, (*Parent)->StartTime);
+ Tracer->jsonEvent(
+ "f",
+ llvm::json::Object{{"id", FlowID},
+ {"bp", "e"},
+ {"name", "Context crosses threads"},
+ {"cat", "dummy"}},
+ TID);
}
}
~JSONSpan() {
// Finally, record the event (ending at EndTime, not timestamp())!
Tracer->jsonEvent("X",
- json::Object{{"name", std::move(Name)},
- {"args", std::move(*Args)},
- {"dur", EndTime - StartTime}},
+ llvm::json::Object{{"name", std::move(Name)},
+ {"args", std::move(*Args)},
+ {"dur", EndTime - StartTime}},
TID, StartTime);
}
// May be called by any thread.
- void markEnded() {
- EndTime = Tracer->timestamp();
- }
+ void markEnded() { EndTime = Tracer->timestamp(); }
private:
static int64_t nextID() {
@@ -139,32 +138,34 @@ private:
std::string Name;
uint64_t TID;
JSONTracer *Tracer;
- json::Object *Args;
+ llvm::json::Object *Args;
};
static Key<std::unique_ptr<JSONSpan>> SpanKey;
// Record an event. ph and pid are set.
// Contents must be a list of the other JSON key/values.
- void rawEvent(StringRef Phase, json::Object &&Event) /*REQUIRES(Mu)*/ {
+ void rawEvent(llvm::StringRef Phase,
+ llvm::json::Object &&Event) /*REQUIRES(Mu)*/ {
// PID 0 represents the clangd process.
Event["pid"] = 0;
Event["ph"] = Phase;
- Out << Sep << formatv(JSONFormat, json::Value(std::move(Event)));
+ Out << Sep
+ << llvm::formatv(JSONFormat, llvm::json::Value(std::move(Event)));
Sep = ",\n";
}
// If we haven't already, emit metadata describing this thread.
void captureThreadMetadata() {
- uint64_t TID = get_threadid();
+ uint64_t TID = llvm::get_threadid();
std::lock_guard<std::mutex> Lock(Mu);
if (ThreadsWithMD.insert(TID).second) {
- SmallString<32> Name;
- get_thread_name(Name);
+ llvm::SmallString<32> Name;
+ llvm::get_thread_name(Name);
if (!Name.empty()) {
- rawEvent("M", json::Object{
+ rawEvent("M", llvm::json::Object{
{"tid", int64_t(TID)},
{"name", "thread_name"},
- {"args", json::Object{{"name", Name}}},
+ {"args", llvm::json::Object{{"name", Name}}},
});
}
}
@@ -176,10 +177,10 @@ private:
}
std::mutex Mu;
- raw_ostream &Out /*GUARDED_BY(Mu)*/;
+ llvm::raw_ostream &Out /*GUARDED_BY(Mu)*/;
const char *Sep /*GUARDED_BY(Mu)*/;
- DenseSet<uint64_t> ThreadsWithMD /*GUARDED_BY(Mu)*/;
- const sys::TimePoint<> Start;
+ llvm::DenseSet<uint64_t> ThreadsWithMD /*GUARDED_BY(Mu)*/;
+ const llvm::sys::TimePoint<> Start;
const char *JSONFormat;
};
@@ -195,31 +196,32 @@ Session::Session(EventTracer &Tracer) {
Session::~Session() { T = nullptr; }
-std::unique_ptr<EventTracer> createJSONTracer(raw_ostream &OS, bool Pretty) {
+std::unique_ptr<EventTracer> createJSONTracer(llvm::raw_ostream &OS,
+ bool Pretty) {
return llvm::make_unique<JSONTracer>(OS, Pretty);
}
-void log(const Twine &Message) {
+void log(const llvm::Twine &Message) {
if (!T)
return;
- T->instant("Log", json::Object{{"Message", Message.str()}});
+ T->instant("Log", llvm::json::Object{{"Message", Message.str()}});
}
// Returned context owns Args.
-static Context makeSpanContext(Twine Name, json::Object *Args) {
+static Context makeSpanContext(llvm::Twine Name, llvm::json::Object *Args) {
if (!T)
return Context::current().clone();
- WithContextValue WithArgs{std::unique_ptr<json::Object>(Args)};
+ WithContextValue WithArgs{std::unique_ptr<llvm::json::Object>(Args)};
return T->beginSpan(Name.isSingleStringRef() ? Name.getSingleStringRef()
- : StringRef(Name.str()),
+ : llvm::StringRef(Name.str()),
Args);
}
// Span keeps a non-owning pointer to the args, which is how users access them.
// The args are owned by the context though. They stick around until the
// beginSpan() context is destroyed, when the tracing engine will consume them.
-Span::Span(Twine Name)
- : Args(T ? new json::Object() : nullptr),
+Span::Span(llvm::Twine Name)
+ : Args(T ? new llvm::json::Object() : nullptr),
RestoreCtx(makeSpanContext(Name, Args)) {}
Span::~Span() {
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 2de95657..fab51d17 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,6 +85,12 @@ newJSONTransport(std::FILE *In, llvm::raw_ostream &Out,
llvm::raw_ostream *InMirror, bool Pretty,
JSONStreamStyle = JSONStreamStyle::Standard);
+#ifdef 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();
+#endif
+
} // namespace clangd
} // namespace clang
diff --git a/clangd/URI.cpp b/clangd/URI.cpp
index 2a838624..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
//
//===----------------------------------------------------------------------===//
@@ -20,13 +19,13 @@
LLVM_INSTANTIATE_REGISTRY(clang::clangd::URISchemeRegistry)
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
-inline Error make_string_error(const Twine &Message) {
- return make_error<StringError>(Message, inconvertibleErrorCode());
+inline llvm::Error make_string_error(const llvm::Twine &Message) {
+ return llvm::make_error<llvm::StringError>(Message,
+ llvm::inconvertibleErrorCode());
}
/// \brief This manages file paths in the file system. All paths in the scheme
@@ -35,8 +34,9 @@ inline Error make_string_error(const Twine &Message) {
/// registry.
class FileSystemScheme : public URIScheme {
public:
- Expected<std::string> getAbsolutePath(StringRef /*Authority*/, StringRef Body,
- StringRef /*HintPath*/) const override {
+ llvm::Expected<std::string>
+ getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body,
+ llvm::StringRef /*HintPath*/) const override {
if (!Body.startswith("/"))
return make_string_error("File scheme: expect body to be an absolute "
"path starting with '/': " +
@@ -44,26 +44,26 @@ public:
// For Windows paths e.g. /X:
if (Body.size() > 2 && Body[0] == '/' && Body[2] == ':')
Body.consume_front("/");
- SmallVector<char, 16> Path(Body.begin(), Body.end());
- sys::path::native(Path);
+ llvm::SmallVector<char, 16> Path(Body.begin(), Body.end());
+ llvm::sys::path::native(Path);
return std::string(Path.begin(), Path.end());
}
- Expected<URI> uriFromAbsolutePath(StringRef AbsolutePath) const override {
- using namespace llvm::sys;
-
+ llvm::Expected<URI>
+ uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override {
std::string Body;
// For Windows paths e.g. X:
if (AbsolutePath.size() > 1 && AbsolutePath[1] == ':')
Body = "/";
- Body += path::convert_to_slash(AbsolutePath);
+ Body += llvm::sys::path::convert_to_slash(AbsolutePath);
return URI("file", /*Authority=*/"", Body);
}
};
-Expected<std::unique_ptr<URIScheme>> findSchemeByName(StringRef Scheme) {
+llvm::Expected<std::unique_ptr<URIScheme>>
+findSchemeByName(llvm::StringRef Scheme) {
if (Scheme == "file")
- return make_unique<FileSystemScheme>();
+ return llvm::make_unique<FileSystemScheme>();
for (auto I = URISchemeRegistry::begin(), E = URISchemeRegistry::end();
I != E; ++I) {
@@ -96,12 +96,12 @@ bool shouldEscape(unsigned char C) {
/// - Unreserved characters are not escaped.
/// - Reserved characters always escaped with exceptions like '/'.
/// - All other characters are escaped.
-std::string percentEncode(StringRef Content) {
+std::string percentEncode(llvm::StringRef Content) {
std::string Result;
- raw_string_ostream OS(Result);
+ llvm::raw_string_ostream OS(Result);
for (unsigned char C : Content)
if (shouldEscape(C))
- OS << '%' << format_hex_no_prefix(C, 2, /*Upper = */ true);
+ OS << '%' << llvm::format_hex_no_prefix(C, 2, /*Upper = */ true);
else
OS << C;
@@ -110,16 +110,16 @@ std::string percentEncode(StringRef Content) {
}
/// Decodes a string according to percent-encoding.
-std::string percentDecode(StringRef Content) {
+std::string percentDecode(llvm::StringRef Content) {
std::string Result;
for (auto I = Content.begin(), E = Content.end(); I != E; ++I) {
if (*I != '%') {
Result += *I;
continue;
}
- if (*I == '%' && I + 2 < Content.end() && isHexDigit(*(I + 1)) &&
- isHexDigit(*(I + 2))) {
- Result.push_back(hexFromNibbles(*(I + 1), *(I + 2)));
+ if (*I == '%' && I + 2 < Content.end() && llvm::isHexDigit(*(I + 1)) &&
+ llvm::isHexDigit(*(I + 2))) {
+ Result.push_back(llvm::hexFromNibbles(*(I + 1), *(I + 2)));
I += 2;
} else
Result.push_back(*I);
@@ -127,19 +127,20 @@ std::string percentDecode(StringRef Content) {
return Result;
}
-bool isValidScheme(StringRef Scheme) {
+bool isValidScheme(llvm::StringRef Scheme) {
if (Scheme.empty())
return false;
- if (!isAlpha(Scheme[0]))
+ if (!llvm::isAlpha(Scheme[0]))
return false;
return std::all_of(Scheme.begin() + 1, Scheme.end(), [](char C) {
- return isAlnum(C) || C == '+' || C == '.' || C == '-';
+ return llvm::isAlnum(C) || C == '+' || C == '.' || C == '-';
});
}
} // namespace
-URI::URI(StringRef Scheme, StringRef Authority, StringRef Body)
+URI::URI(llvm::StringRef Scheme, llvm::StringRef Authority,
+ llvm::StringRef Body)
: Scheme(Scheme), Authority(Authority), Body(Body) {
assert(!Scheme.empty());
assert((Authority.empty() || Body.startswith("/")) &&
@@ -148,31 +149,31 @@ URI::URI(StringRef Scheme, StringRef Authority, StringRef Body)
std::string URI::toString() const {
std::string Result;
- raw_string_ostream OS(Result);
+ llvm::raw_string_ostream OS(Result);
OS << percentEncode(Scheme) << ":";
if (Authority.empty() && Body.empty())
return OS.str();
// If authority if empty, we only print body if it starts with "/"; otherwise,
// the URI is invalid.
- if (!Authority.empty() || StringRef(Body).startswith("/"))
+ if (!Authority.empty() || llvm::StringRef(Body).startswith("/"))
OS << "//" << percentEncode(Authority);
OS << percentEncode(Body);
OS.flush();
return Result;
}
-Expected<URI> URI::parse(StringRef OrigUri) {
+llvm::Expected<URI> URI::parse(llvm::StringRef OrigUri) {
URI U;
- StringRef Uri = OrigUri;
+ llvm::StringRef Uri = OrigUri;
auto Pos = Uri.find(':');
- if (Pos == StringRef::npos)
+ if (Pos == llvm::StringRef::npos)
return make_string_error("Scheme must be provided in URI: " + OrigUri);
auto SchemeStr = Uri.substr(0, Pos);
U.Scheme = percentDecode(SchemeStr);
if (!isValidScheme(U.Scheme))
- return make_string_error(
- formatv("Invalid scheme: {0} (decoded: {1})", SchemeStr, U.Scheme));
+ return make_string_error(llvm::formatv("Invalid scheme: {0} (decoded: {1})",
+ SchemeStr, U.Scheme));
Uri = Uri.substr(Pos + 1);
if (Uri.consume_front("//")) {
Pos = Uri.find('/');
@@ -183,8 +184,9 @@ Expected<URI> URI::parse(StringRef OrigUri) {
return U;
}
-Expected<URI> URI::create(StringRef AbsolutePath, StringRef Scheme) {
- if (!sys::path::is_absolute(AbsolutePath))
+llvm::Expected<URI> URI::create(llvm::StringRef AbsolutePath,
+ llvm::StringRef Scheme) {
+ if (!llvm::sys::path::is_absolute(AbsolutePath))
return make_string_error("Not a valid absolute path: " + AbsolutePath);
auto S = findSchemeByName(Scheme);
if (!S)
@@ -192,8 +194,8 @@ Expected<URI> URI::create(StringRef AbsolutePath, StringRef Scheme) {
return S->get()->uriFromAbsolutePath(AbsolutePath);
}
-URI URI::create(StringRef AbsolutePath) {
- if (!sys::path::is_absolute(AbsolutePath))
+URI URI::create(llvm::StringRef AbsolutePath) {
+ if (!llvm::sys::path::is_absolute(AbsolutePath))
llvm_unreachable(
("Not a valid absolute path: " + AbsolutePath).str().c_str());
for (auto &Entry : URISchemeRegistry::entries()) {
@@ -202,7 +204,7 @@ URI URI::create(StringRef AbsolutePath) {
// should be just skipped.
if (!URI) {
// Ignore the error.
- consumeError(URI.takeError());
+ llvm::consumeError(URI.takeError());
continue;
}
return std::move(*URI);
@@ -211,31 +213,33 @@ URI URI::create(StringRef AbsolutePath) {
return URI::createFile(AbsolutePath);
}
-URI URI::createFile(StringRef AbsolutePath) {
+URI URI::createFile(llvm::StringRef AbsolutePath) {
auto U = FileSystemScheme().uriFromAbsolutePath(AbsolutePath);
if (!U)
llvm_unreachable(llvm::toString(U.takeError()).c_str());
return std::move(*U);
}
-Expected<std::string> URI::resolve(const URI &Uri, StringRef HintPath) {
+llvm::Expected<std::string> URI::resolve(const URI &Uri,
+ llvm::StringRef HintPath) {
auto S = findSchemeByName(Uri.Scheme);
if (!S)
return S.takeError();
return S->get()->getAbsolutePath(Uri.Authority, Uri.Body, HintPath);
}
-Expected<std::string> URI::resolvePath(StringRef AbsPath, StringRef HintPath) {
- if (!sys::path::is_absolute(AbsPath))
+llvm::Expected<std::string> URI::resolvePath(llvm::StringRef AbsPath,
+ llvm::StringRef HintPath) {
+ if (!llvm::sys::path::is_absolute(AbsPath))
llvm_unreachable(("Not a valid absolute path: " + AbsPath).str().c_str());
for (auto &Entry : URISchemeRegistry::entries()) {
- auto S = Entry.instantiate();
+ auto S = Entry.instantiate();
auto U = S->uriFromAbsolutePath(AbsPath);
// For some paths, conversion to different URI schemes is impossible. These
// should be just skipped.
if (!U) {
// Ignore the error.
- consumeError(U.takeError());
+ llvm::consumeError(U.takeError());
continue;
}
return S->getAbsolutePath(U->Authority, U->Body, HintPath);
@@ -244,7 +248,7 @@ Expected<std::string> URI::resolvePath(StringRef AbsPath, StringRef HintPath) {
return AbsPath;
}
-Expected<std::string> URI::includeSpelling(const URI &Uri) {
+llvm::Expected<std::string> URI::includeSpelling(const URI &Uri) {
auto S = findSchemeByName(Uri.Scheme);
if (!S)
return S.takeError();
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 bdae8a35..b296a056 100644
--- a/clangd/XRefs.cpp
+++ b/clangd/XRefs.cpp
@@ -1,9 +1,8 @@
//===--- 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"
@@ -11,6 +10,8 @@
#include "Logger.h"
#include "SourceCode.h"
#include "URI.h"
+#include "index/Index.h"
+#include "index/Merge.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Index/IndexDataConsumer.h"
@@ -18,23 +19,30 @@
#include "clang/Index/USRGeneration.h"
#include "llvm/Support/Path.h"
-using namespace llvm;
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)) // except cases above
+ return D;
+ // Multiple definitions are allowed.
+ return nullptr; // except cases above
}
void logIfOverflow(const SymbolLocation &Loc) {
@@ -46,8 +54,8 @@ void logIfOverflow(const SymbolLocation &Loc) {
// TUPath is used to resolve the path of URI.
// FIXME: figure out a good home for it, and share the implementation with
// FindSymbols.
-Optional<Location> toLSPLocation(const SymbolLocation &Loc,
- StringRef TUPath) {
+llvm::Optional<Location> toLSPLocation(const SymbolLocation &Loc,
+ llvm::StringRef TUPath) {
if (!Loc)
return None;
auto Uri = URI::parse(Loc.FileURI);
@@ -71,8 +79,33 @@ 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 {
- StringRef Name;
+ llvm::StringRef Name;
const MacroInfo *Info;
};
@@ -89,7 +122,7 @@ class DeclarationAndMacrosFinder : public index::IndexDataConsumer {
// explicitly in the code.
// True means the declaration is explicitly referenced at least once; false
// otherwise.
- DenseMap<const Decl *, bool> Decls;
+ llvm::DenseMap<const Decl *, bool> Decls;
const SourceLocation &SearchedLocation;
const ASTContext &AST;
Preprocessor &PP;
@@ -135,11 +168,11 @@ public:
bool
handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
- ArrayRef<index::SymbolRelation> Relations,
+ llvm::ArrayRef<index::SymbolRelation> Relations,
SourceLocation Loc,
index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
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
@@ -151,7 +184,7 @@ public:
return isa<ImplicitCastExpr>(E);
};
- bool IsExplicit = !isImplicitExpr(ASTNode.OrigE);
+ bool IsExplicit = !IsImplicitExpr(ASTNode.OrigE);
// 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
@@ -209,6 +242,7 @@ IdentifiedSymbol getSymbolAtPosition(ParsedAST &AST, SourceLocation Pos) {
IndexOpts.SystemSymbolFilter =
index::IndexingOptions::SystemSymbolFilterKind::All;
IndexOpts.IndexFunctionLocals = true;
+ IndexOpts.IndexParametersInDeclarations = true;
indexTopLevelDecls(AST.getASTContext(), AST.getPreprocessor(),
AST.getLocalTopLevelDecls(), DeclMacrosFinder, IndexOpts);
@@ -223,13 +257,13 @@ Range getTokenRange(ParsedAST &AST, SourceLocation TokLoc) {
sourceLocToPosition(SourceMgr, LocEnd)};
}
-Optional<Location> makeLocation(ParsedAST &AST, SourceLocation TokLoc,
- StringRef TUPath) {
+llvm::Optional<Location> makeLocation(ParsedAST &AST, SourceLocation TokLoc,
+ llvm::StringRef TUPath) {
const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
const FileEntry *F = SourceMgr.getFileEntryForID(SourceMgr.getFileID(TokLoc));
if (!F)
return None;
- auto FilePath = getRealPath(F, SourceMgr);
+ auto FilePath = getCanonicalPath(F, SourceMgr);
if (!FilePath) {
log("failed to get path!");
return None;
@@ -242,126 +276,107 @@ 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 = getRealPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
+ auto MainFilePath =
+ getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
if (!MainFilePath) {
elog("Failed to get a path for the main file, so no references");
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);
+ // 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));
+ }
}
- // 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 {
- Optional<Location> Def;
- Optional<Location> Decl;
- };
- // We respect the order in Symbols.Decls.
- SmallVector<CandidateLocation, 8> ResultCandidates;
- DenseMap<SymbolID, size_t> CandidatesIndex;
+ // 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("");
+ 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 = getRealPath(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)];
+
+ // Special case: if the AST yielded a definition, then it may not be
+ // the right *declaration*. Prefer the one from the index.
+ if (R.Definition) { // from AST
+ if (auto Loc = toLSPLocation(Sym.CanonicalDeclaration, *MainFilePath))
+ R.PreferredDeclaration = *Loc;
+ } else {
+ R.Definition = toLSPLocation(Sym.Definition, *MainFilePath);
+
+ if (Sym.CanonicalDeclaration) {
+ // Use merge logic to choose AST or index declaration.
+ // We only do this for declarations as definitions from AST
+ // is generally preferred (e.g. definitions in main file).
+ 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;
}
@@ -401,7 +416,7 @@ public:
bool
handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
- ArrayRef<index::SymbolRelation> Relations,
+ llvm::ArrayRef<index::SymbolRelation> Relations,
SourceLocation Loc,
index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
assert(D->isCanonicalDecl() && "expect D to be a canonical declaration");
@@ -413,7 +428,7 @@ public:
}
private:
- SmallSet<const Decl *, 4> CanonicalTargets;
+ llvm::SmallSet<const Decl *, 4> CanonicalTargets;
std::vector<Reference> References;
const ASTContext &AST;
};
@@ -425,6 +440,7 @@ findRefs(const std::vector<const Decl *> &Decls, ParsedAST &AST) {
IndexOpts.SystemSymbolFilter =
index::IndexingOptions::SystemSymbolFilterKind::All;
IndexOpts.IndexFunctionLocals = true;
+ IndexOpts.IndexParametersInDeclarations = true;
indexTopLevelDecls(AST.getASTContext(), AST.getPreprocessor(),
AST.getLocalTopLevelDecls(), RefFinder, IndexOpts);
return std::move(RefFinder).take();
@@ -479,7 +495,7 @@ static std::string typeDeclToString(const TypeDecl *TD) {
printingPolicyForDecls(TD->getASTContext().getPrintingPolicy());
std::string Name;
- raw_string_ostream Stream(Name);
+ llvm::raw_string_ostream Stream(Name);
Type.print(Stream, Policy);
return Stream.str();
@@ -488,12 +504,12 @@ static std::string typeDeclToString(const TypeDecl *TD) {
/// Return a string representation (e.g. "namespace ns1::ns2") of
/// the named declaration \p ND.
static std::string namedDeclQualifiedName(const NamedDecl *ND,
- StringRef Prefix) {
+ llvm::StringRef Prefix) {
PrintingPolicy Policy =
printingPolicyForDecls(ND->getASTContext().getPrintingPolicy());
std::string Name;
- raw_string_ostream Stream(Name);
+ llvm::raw_string_ostream Stream(Name);
Stream << Prefix << ' ';
ND->printQualifiedName(Stream, Policy);
@@ -503,7 +519,7 @@ static std::string namedDeclQualifiedName(const NamedDecl *ND,
/// Given a declaration \p D, return a human-readable string representing the
/// scope in which it is declared. If the declaration is in the global scope,
/// return the string "global namespace".
-static Optional<std::string> getScopeName(const Decl *D) {
+static llvm::Optional<std::string> getScopeName(const Decl *D) {
const DeclContext *DC = D->getDeclContext();
if (isa<TranslationUnitDecl>(DC))
@@ -521,7 +537,7 @@ static Optional<std::string> getScopeName(const Decl *D) {
/// Generate a \p Hover object given the declaration \p D.
static Hover getHoverContents(const Decl *D) {
Hover H;
- Optional<std::string> NamedScope = getScopeName(D);
+ llvm::Optional<std::string> NamedScope = getScopeName(D);
// Generate the "Declared in" section.
if (NamedScope) {
@@ -537,7 +553,7 @@ static Hover getHoverContents(const Decl *D) {
D = TD;
std::string DeclText;
- raw_string_ostream OS(DeclText);
+ llvm::raw_string_ostream OS(DeclText);
PrintingPolicy Policy =
printingPolicyForDecls(D->getASTContext().getPrintingPolicy());
@@ -554,7 +570,7 @@ static Hover getHoverContents(const Decl *D) {
static Hover getHoverContents(QualType T, ASTContext &ASTCtx) {
Hover H;
std::string TypeText;
- raw_string_ostream OS(TypeText);
+ llvm::raw_string_ostream OS(TypeText);
PrintingPolicy Policy = printingPolicyForDecls(ASTCtx.getPrintingPolicy());
T.print(OS, Policy);
OS.flush();
@@ -563,7 +579,7 @@ static Hover getHoverContents(QualType T, ASTContext &ASTCtx) {
}
/// Generate a \p Hover object given the macro \p MacroInf.
-static Hover getHoverContents(StringRef MacroName) {
+static Hover getHoverContents(llvm::StringRef MacroName) {
Hover H;
H.contents.value = "#define ";
@@ -583,13 +599,13 @@ namespace {
/// a deduced type set. The AST should be improved to simplify this scenario.
class DeducedTypeVisitor : public RecursiveASTVisitor<DeducedTypeVisitor> {
SourceLocation SearchedLocation;
- Optional<QualType> DeducedType;
+ llvm::Optional<QualType> DeducedType;
public:
DeducedTypeVisitor(SourceLocation SearchedLocation)
: SearchedLocation(SearchedLocation) {}
- Optional<QualType> getDeducedType() { return DeducedType; }
+ llvm::Optional<QualType> getDeducedType() { return DeducedType; }
// Handle auto initializers:
//- auto i = 1;
@@ -664,8 +680,8 @@ public:
} // namespace
/// Retrieves the deduced type at a given location (auto, decltype).
-Optional<QualType> getDeducedType(ParsedAST &AST,
- SourceLocation SourceLocationBeg) {
+llvm::Optional<QualType> getDeducedType(ParsedAST &AST,
+ SourceLocation SourceLocationBeg) {
Token Tok;
auto &ASTCtx = AST.getASTContext();
// Only try to find a deduced type if the token is auto or decltype.
@@ -684,7 +700,7 @@ Optional<QualType> getDeducedType(ParsedAST &AST,
return V.getDeducedType();
}
-Optional<Hover> getHover(ParsedAST &AST, Position Pos) {
+llvm::Optional<Hover> getHover(ParsedAST &AST, Position Pos) {
const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
SourceLocation SourceLocationBeg =
getBeginningOfIdentifier(AST, Pos, SourceMgr.getMainFileID());
@@ -705,10 +721,13 @@ Optional<Hover> getHover(ParsedAST &AST, Position Pos) {
}
std::vector<Location> findReferences(ParsedAST &AST, Position Pos,
- const SymbolIndex *Index) {
+ uint32_t Limit, const SymbolIndex *Index) {
+ if (!Limit)
+ Limit = std::numeric_limits<uint32_t>::max();
std::vector<Location> Results;
const SourceManager &SM = AST.getASTContext().getSourceManager();
- auto MainFilePath = getRealPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
+ auto MainFilePath =
+ getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
if (!MainFilePath) {
elog("Failed to get a path for the main file, so no references");
return Results;
@@ -733,26 +752,30 @@ std::vector<Location> findReferences(ParsedAST &AST, Position Pos,
}
// Now query the index for references from other files.
- if (!Index)
- return Results;
- RefsRequest Req;
- for (const Decl *D : TargetDecls) {
- // 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.
- if (D->getParentFunctionOrMethod())
- continue;
- if (auto ID = getSymbolID(D))
- Req.IDs.insert(*ID);
+ if (Index && Results.size() < Limit) {
+ RefsRequest Req;
+ Req.Limit = Limit;
+
+ for (const Decl *D : TargetDecls) {
+ // 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.
+ if (D->getParentFunctionOrMethod())
+ continue;
+ if (auto ID = getSymbolID(D))
+ Req.IDs.insert(*ID);
+ }
+ if (Req.IDs.empty())
+ return Results;
+ Index->refs(Req, [&](const Ref &R) {
+ auto LSPLoc = toLSPLocation(R.Location, *MainFilePath);
+ // Avoid indexed results for the main file - the AST is authoritative.
+ if (LSPLoc && LSPLoc->uri.file() != *MainFilePath)
+ Results.push_back(std::move(*LSPLoc));
+ });
}
- if (Req.IDs.empty())
- return Results;
- Index->refs(Req, [&](const Ref &R) {
- auto LSPLoc = toLSPLocation(R.Location, *MainFilePath);
- // Avoid indexed results for the main file - the AST is authoritative.
- if (LSPLoc && LSPLoc->uri.file() != *MainFilePath)
- Results.push_back(std::move(*LSPLoc));
- });
+ if (Results.size() > Limit)
+ Results.resize(Limit);
return Results;
}
@@ -789,7 +812,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);
}
@@ -799,5 +823,12 @@ 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;
+}
+
} // namespace clangd
} // namespace clang
diff --git a/clangd/XRefs.h b/clangd/XRefs.h
index 77d60248..25e5d867 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,
@@ -35,7 +50,9 @@ std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST,
llvm::Optional<Hover> getHover(ParsedAST &AST, Position Pos);
/// Returns reference locations of the symbol at a specified \p Pos.
+/// \p Limit limits the number of results returned (0 means no limit).
std::vector<Location> findReferences(ParsedAST &AST, Position Pos,
+ uint32_t Limit,
const SymbolIndex *Index = nullptr);
/// Get info about symbols at \p Pos.
diff --git a/clangd/benchmarks/IndexBenchmark.cpp b/clangd/benchmarks/IndexBenchmark.cpp
index baedca2f..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
//
//===----------------------------------------------------------------------===//
@@ -21,7 +20,6 @@
const char *IndexFilename;
const char *RequestsFilename;
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -41,16 +39,17 @@ std::vector<FuzzyFindRequest> extractQueriesFromLogs() {
std::istreambuf_iterator<char>());
std::vector<FuzzyFindRequest> Requests;
- auto JSONArray = json::parse(Log);
+ auto JSONArray = llvm::json::parse(Log);
// Panic if the provided file couldn't be parsed.
if (!JSONArray) {
- errs() << "Error when parsing JSON requests file: "
- << toString(JSONArray.takeError());
+ llvm::errs() << "Error when parsing JSON requests file: "
+ << llvm::toString(JSONArray.takeError());
exit(1);
}
if (!JSONArray->getAsArray()) {
- errs() << "Error: top-level value is not a JSON array: " << Log << '\n';
+ llvm::errs() << "Error: top-level value is not a JSON array: " << Log
+ << '\n';
exit(1);
}
@@ -58,7 +57,7 @@ std::vector<FuzzyFindRequest> extractQueriesFromLogs() {
FuzzyFindRequest Request;
// Panic if the provided file couldn't be parsed.
if (!fromJSON(Item, Request)) {
- errs() << "Error when deserializing request: " << Item << '\n';
+ llvm::errs() << "Error when deserializing request: " << Item << '\n';
exit(1);
}
Requests.push_back(Request);
@@ -94,9 +93,9 @@ BENCHMARK(DexQueries);
// FIXME(kbobyrev): Create a logger wrapper to suppress debugging info printer.
int main(int argc, char *argv[]) {
if (argc < 3) {
- errs() << "Usage: " << argv[0]
- << " global-symbol-index.yaml requests.json "
- "BENCHMARK_OPTIONS...\n";
+ llvm::errs() << "Usage: " << argv[0]
+ << " global-symbol-index.yaml requests.json "
+ "BENCHMARK_OPTIONS...\n";
return -1;
}
IndexFilename = argv[1];
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/LICENSE b/clangd/clients/clangd-vscode/LICENSE
index c558158d..6a18483d 100644
--- a/clangd/clients/clangd-vscode/LICENSE
+++ b/clangd/clients/clangd-vscode/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2017 The LLVM Developers
+Copyright (c) 2019 The LLVM Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
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 f1dcb6e1..f9ac9222 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.8",
+ "version": "0.0.11",
"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,10 @@
"LLVM"
],
"activationEvents": [
+ "onLanguage:c",
"onLanguage:cpp",
- "onLanguage:c"
+ "onLanguage:objective-c",
+ "onLanguage:objective-cpp"
],
"main": "./out/src/extension",
"scripts": {
@@ -32,15 +34,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",
diff --git a/clangd/clients/clangd-vscode/src/extension.ts b/clangd/clients/clangd-vscode/src/extension.ts
index 1191bb47..d4ab6787 100644
--- a/clangd/clients/clangd-vscode/src/extension.ts
+++ b/clangd/clients/clangd-vscode/src/extension.ts
@@ -18,6 +18,38 @@ export const type =
void, void>('textDocument/switchSourceHeader');
}
+class FileStatus {
+ private statuses = new Map<string, any>();
+ private readonly statusBarItem =
+ vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 10);
+
+ onFileUpdated(fileStatus: any) {
+ const filePath = vscode.Uri.parse(fileStatus.uri);
+ this.statuses.set(filePath.fsPath, fileStatus);
+ this.updateStatus();
+ }
+
+ updateStatus() {
+ const path = vscode.window.activeTextEditor.document.fileName;
+ const status = this.statuses.get(path);
+ if (!status) {
+ this.statusBarItem.hide();
+ return;
+ }
+ this.statusBarItem.text = `clangd: ` + status.state;
+ this.statusBarItem.show();
+ }
+
+ clear() {
+ this.statuses.clear();
+ this.statusBarItem.hide();
+ }
+
+ dispose() {
+ this.statusBarItem.dispose();
+ }
+}
+
/**
* this method is called when your extension is activate
* your extension is activated the very first time the command is executed
@@ -44,6 +76,7 @@ export function activate(context: vscode.ExtensionContext) {
synchronize: !syncFileEvents ? undefined : {
fileEvents: vscode.workspace.createFileSystemWatcher(filePattern)
},
+ initializationOptions: { clangdFileStatus: true },
// Resolve symlinks for all files provided by clangd.
// This is a workaround for a bazel + clangd issue - bazel produces a symlink tree to build in,
// and when navigating to the included file, clangd passes its path inside the symlink tree
@@ -80,4 +113,20 @@ export function activate(context: vscode.ExtensionContext) {
vscode.Uri.parse(sourceUri));
vscode.window.showTextDocument(doc);
}));
+ const status = new FileStatus();
+ context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(() => {
+ status.updateStatus();
+ }));
+ 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();
+ }
+ })
}
diff --git a/clangd/fuzzer/ClangdFuzzer.cpp b/clangd/fuzzer/ClangdFuzzer.cpp
index 8c9c7bdb..eba98261 100644
--- a/clangd/fuzzer/ClangdFuzzer.cpp
+++ b/clangd/fuzzer/ClangdFuzzer.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,8 +15,9 @@
#include "ClangdLSPServer.h"
#include "ClangdServer.h"
#include "CodeComplete.h"
+#include "FSProvider.h"
+#include <cstdio>
#include <sstream>
-#include <stdio.h>
using namespace clang::clangd;
@@ -29,13 +29,14 @@ 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, Opts);
LSPServer.run();
return 0;
}
diff --git a/clangd/index/Background.cpp b/clangd/index/Background.cpp
index 1d678197..ddb0ec43 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
//
//===----------------------------------------------------------------------===//
@@ -35,7 +34,6 @@
#include <string>
#include <thread>
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -92,46 +90,48 @@ IncludeGraph getSubGraph(const URI &U, const IncludeGraph &FullGraph) {
// Creates a filter to not collect index results from files with unchanged
// digests.
-// \p FileDigests contains file digests for the current indexed files, and all
-// changed files will be added to \p FilesToUpdate.
+// \p FileDigests contains file digests for the current indexed files.
decltype(SymbolCollector::Options::FileFilter)
-createFileFilter(const llvm::StringMap<FileDigest> &FileDigests,
- llvm::StringMap<FileDigest> &FilesToUpdate) {
- return [&FileDigests, &FilesToUpdate](const SourceManager &SM, FileID FID) {
- StringRef Path;
- if (const auto *F = SM.getFileEntryForID(FID))
- Path = F->getName();
- if (Path.empty())
+createFileFilter(const llvm::StringMap<FileDigest> &FileDigests) {
+ return [&FileDigests](const SourceManager &SM, FileID FID) {
+ const auto *F = SM.getFileEntryForID(FID);
+ if (!F)
return false; // Skip invalid files.
- SmallString<128> AbsPath(Path);
- if (std::error_code EC =
- SM.getFileManager().getVirtualFileSystem()->makeAbsolute(AbsPath)) {
- elog("Warning: could not make absolute file: {0}", EC.message());
+ auto AbsPath = getCanonicalPath(F, SM);
+ if (!AbsPath)
return false; // Skip files without absolute path.
- }
- sys::path::remove_dots(AbsPath, /*remove_dot_dot=*/true);
auto Digest = digestFile(SM, FID);
if (!Digest)
return false;
- auto D = FileDigests.find(AbsPath);
+ auto D = FileDigests.find(*AbsPath);
if (D != FileDigests.end() && D->second == Digest)
return false; // Skip files that haven't changed.
-
- FilesToUpdate[AbsPath] = *Digest;
return true;
};
}
+// We cannot use vfs->makeAbsolute because Cmd.FileName is either absolute or
+// relative to Cmd.Directory, which might not be the same as current working
+// directory.
+llvm::SmallString<128> getAbsolutePath(const tooling::CompileCommand &Cmd) {
+ llvm::SmallString<128> AbsolutePath;
+ if (llvm::sys::path::is_absolute(Cmd.Filename)) {
+ AbsolutePath = Cmd.Filename;
+ } else {
+ AbsolutePath = Cmd.Directory;
+ llvm::sys::path::append(AbsolutePath, Cmd.Filename);
+ }
+ return AbsolutePath;
+}
} // namespace
BackgroundIndex::BackgroundIndex(
- Context BackgroundContext, 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(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)),
@@ -169,7 +169,7 @@ void BackgroundIndex::stop() {
void BackgroundIndex::run() {
WithContext Background(BackgroundContext.clone());
while (true) {
- Optional<Task> Task;
+ llvm::Optional<Task> Task;
ThreadPriority Priority;
{
std::unique_lock<std::mutex> Lock(QueueMu);
@@ -211,40 +211,32 @@ void BackgroundIndex::enqueue(const std::vector<std::string> &ChangedFiles) {
[this, ChangedFiles] {
trace::Span Tracer("BackgroundIndexEnqueue");
// We're doing this asynchronously, because we'll read shards here too.
- // FIXME: read shards here too.
-
log("Enqueueing {0} commands for indexing", ChangedFiles.size());
SPAN_ATTACH(Tracer, "files", int64_t(ChangedFiles.size()));
- // We shuffle the files because processing them in a random order should
- // quickly give us good coverage of headers in the project.
- std::vector<unsigned> Permutation(ChangedFiles.size());
- std::iota(Permutation.begin(), Permutation.end(), 0);
- std::mt19937 Generator(std::random_device{}());
- std::shuffle(Permutation.begin(), Permutation.end(), Generator);
-
- for (const unsigned I : Permutation)
- enqueue(ChangedFiles[I]);
+ auto NeedsReIndexing = loadShards(std::move(ChangedFiles));
+ // Run indexing for files that need to be updated.
+ std::shuffle(NeedsReIndexing.begin(), NeedsReIndexing.end(),
+ std::mt19937(std::random_device{}()));
+ for (auto &Elem : NeedsReIndexing)
+ enqueue(std::move(Elem.first), Elem.second);
},
ThreadPriority::Normal);
}
-void BackgroundIndex::enqueue(const std::string &File) {
- ProjectInfo Project;
- if (auto Cmd = CDB.getCompileCommand(File, &Project)) {
- auto *Storage = IndexStorageFactory(Project.SourceRoot);
- // Set priority to low, since background indexing is a long running
- // task we do not want to eat up cpu when there are any other high
- // priority threads.
- enqueueTask(Bind(
- [this, File, Storage](tooling::CompileCommand Cmd) {
- Cmd.CommandLine.push_back("-resource-dir=" + ResourceDir);
- if (auto Error = index(std::move(Cmd), Storage))
- log("Indexing {0} failed: {1}", File, std::move(Error));
- },
- std::move(*Cmd)),
- ThreadPriority::Low);
- }
+void BackgroundIndex::enqueue(tooling::CompileCommand Cmd,
+ BackgroundIndexStorage *Storage) {
+ enqueueTask(Bind(
+ [this, Storage](tooling::CompileCommand Cmd) {
+ // 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;
+ if (auto Error = index(std::move(Cmd), Storage))
+ elog("Indexing {0} failed: {1}", FileName,
+ std::move(Error));
+ },
+ std::move(Cmd)),
+ ThreadPriority::Low);
}
void BackgroundIndex::enqueueTask(Task T, ThreadPriority Priority) {
@@ -265,22 +257,34 @@ void BackgroundIndex::enqueueTask(Task T, ThreadPriority Priority) {
QueueCV.notify_all();
}
-/// Given index results from a TU, only update files in \p FilesToUpdate.
-void BackgroundIndex::update(StringRef MainFile, IndexFileIn Index,
- const StringMap<FileDigest> &FilesToUpdate,
+/// Given index results from a TU, only update symbols coming from files that
+/// are different or missing from than \p DigestsSnapshot. Also stores new index
+/// information on IndexStorage.
+void BackgroundIndex::update(llvm::StringRef MainFile, IndexFileIn Index,
+ const llvm::StringMap<FileDigest> &DigestsSnapshot,
BackgroundIndexStorage *IndexStorage) {
// Partition symbols/references into files.
struct File {
- DenseSet<const Symbol *> Symbols;
- DenseSet<const Ref *> Refs;
+ llvm::DenseSet<const Symbol *> Symbols;
+ llvm::DenseSet<const Ref *> Refs;
+ FileDigest Digest;
};
- StringMap<File> Files;
+ llvm::StringMap<File> Files;
URIToFileCache URICache(MainFile);
+ for (const auto &IndexIt : *Index.Sources) {
+ const auto &IGN = IndexIt.getValue();
+ const auto AbsPath = URICache.resolve(IGN.URI);
+ const auto DigestIt = DigestsSnapshot.find(AbsPath);
+ // File has different contents.
+ if (DigestIt == DigestsSnapshot.end() || DigestIt->getValue() != IGN.Digest)
+ Files.try_emplace(AbsPath).first->getValue().Digest = IGN.Digest;
+ }
for (const auto &Sym : *Index.Symbols) {
if (Sym.CanonicalDeclaration) {
auto DeclPath = URICache.resolve(Sym.CanonicalDeclaration.FileURI);
- if (FilesToUpdate.count(DeclPath) != 0)
- Files[DeclPath].Symbols.insert(&Sym);
+ const auto FileIt = Files.find(DeclPath);
+ if (FileIt != Files.end())
+ FileIt->second.Symbols.insert(&Sym);
}
// For symbols with different declaration and definition locations, we store
// the full symbol in both the header file and the implementation file, so
@@ -289,16 +293,18 @@ void BackgroundIndex::update(StringRef MainFile, IndexFileIn Index,
if (Sym.Definition &&
Sym.Definition.FileURI != Sym.CanonicalDeclaration.FileURI) {
auto DefPath = URICache.resolve(Sym.Definition.FileURI);
- if (FilesToUpdate.count(DefPath) != 0)
- Files[DefPath].Symbols.insert(&Sym);
+ const auto FileIt = Files.find(DefPath);
+ if (FileIt != Files.end())
+ FileIt->second.Symbols.insert(&Sym);
}
}
- DenseMap<const Ref *, SymbolID> RefToIDs;
+ llvm::DenseMap<const Ref *, SymbolID> RefToIDs;
for (const auto &SymRefs : *Index.Refs) {
for (const auto &R : SymRefs.second) {
auto Path = URICache.resolve(R.Location.FileURI);
- if (FilesToUpdate.count(Path) != 0) {
- auto &F = Files[Path];
+ const auto FileIt = Files.find(Path);
+ if (FileIt != Files.end()) {
+ auto &F = FileIt->getValue();
RefToIDs[&R] = SymRefs.first;
F.Refs.insert(&R);
}
@@ -306,22 +312,18 @@ void BackgroundIndex::update(StringRef MainFile, IndexFileIn Index,
}
// Build and store new slabs for each updated file.
- for (const auto &F : Files) {
- StringRef Path = F.first();
- vlog("Update symbols in {0}", Path);
+ for (const auto &FileIt : Files) {
+ llvm::StringRef Path = FileIt.getKey();
SymbolSlab::Builder Syms;
RefSlab::Builder Refs;
- for (const auto *S : F.second.Symbols)
+ for (const auto *S : FileIt.second.Symbols)
Syms.insert(*S);
- for (const auto *R : F.second.Refs)
+ for (const auto *R : FileIt.second.Refs)
Refs.insert(RefToIDs[R], *R);
-
auto SS = llvm::make_unique<SymbolSlab>(std::move(Syms).build());
auto RS = llvm::make_unique<RefSlab>(std::move(Refs).build());
auto IG = llvm::make_unique<IncludeGraph>(
getSubGraph(URI::create(Path), Index.Sources.getValue()));
-
- auto Hash = FilesToUpdate.lookup(Path);
// We need to store shards before updating the index, since the latter
// consumes slabs.
if (IndexStorage) {
@@ -334,13 +336,19 @@ void BackgroundIndex::update(StringRef MainFile, IndexFileIn Index,
elog("Failed to write background-index shard for file {0}: {1}", Path,
std::move(Error));
}
-
- std::lock_guard<std::mutex> Lock(DigestsMu);
- // This can override a newer version that is added in another thread,
- // if this thread sees the older version but finishes later. This should be
- // rare in practice.
- IndexedFileDigests[Path] = Hash;
- IndexedSymbols.update(Path, std::move(SS), std::move(RS));
+ {
+ std::lock_guard<std::mutex> Lock(DigestsMu);
+ auto Hash = FileIt.second.Digest;
+ // Skip if file is already up to date.
+ auto DigestIt = IndexedFileDigests.try_emplace(Path);
+ if (!DigestIt.second && DigestIt.first->second == Hash)
+ continue;
+ DigestIt.first->second = Hash;
+ // This can override a newer version that is added in another thread, if
+ // this thread sees the older version but finishes later. This should be
+ // rare in practice.
+ IndexedSymbols.update(Path, std::move(SS), std::move(RS));
+ }
}
}
@@ -349,11 +357,11 @@ void BackgroundIndex::buildIndex() {
while (true) {
{
std::unique_lock<std::mutex> Lock(IndexMu);
- if (ShouldStop) // Avoid waiting if stopped.
+ if (ShouldStop) // Avoid waiting if stopped.
break;
// Wait until this is notified to stop or `BuildIndexPeriodMs` has past.
IndexCV.wait_for(Lock, std::chrono::milliseconds(BuildIndexPeriodMs));
- if (ShouldStop) // Avoid rebuilding index if stopped.
+ if (ShouldStop) // Avoid rebuilding index if stopped.
break;
}
if (!SymbolsUpdatedSinceLastIndex.exchange(false))
@@ -368,56 +376,44 @@ void BackgroundIndex::buildIndex() {
}
}
-Error BackgroundIndex::index(tooling::CompileCommand Cmd,
- BackgroundIndexStorage *IndexStorage) {
+llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd,
+ BackgroundIndexStorage *IndexStorage) {
trace::Span Tracer("BackgroundIndex");
SPAN_ATTACH(Tracer, "file", Cmd.Filename);
- SmallString<128> AbsolutePath;
- if (sys::path::is_absolute(Cmd.Filename)) {
- AbsolutePath = Cmd.Filename;
- } else {
- AbsolutePath = Cmd.Directory;
- sys::path::append(AbsolutePath, Cmd.Filename);
- }
+ auto AbsolutePath = getAbsolutePath(Cmd);
auto FS = FSProvider.getFileSystem();
auto Buf = FS->getBufferForFile(AbsolutePath);
if (!Buf)
- return errorCodeToError(Buf.getError());
+ return llvm::errorCodeToError(Buf.getError());
auto Hash = digest(Buf->get()->getBuffer());
// Take a snapshot of the digests to avoid locking for each file in the TU.
llvm::StringMap<FileDigest> DigestsSnapshot;
{
std::lock_guard<std::mutex> Lock(DigestsMu);
- if (IndexedFileDigests.lookup(AbsolutePath) == Hash) {
- vlog("No need to index {0}, already up to date", AbsolutePath);
- return Error::success();
- }
-
DigestsSnapshot = IndexedFileDigests;
}
- log("Indexing {0} (digest:={1})", Cmd.Filename, toHex(Hash));
+ vlog("Indexing {0} (digest:={1})", Cmd.Filename, llvm::toHex(Hash));
ParseInputs Inputs;
Inputs.FS = std::move(FS);
Inputs.FS->setCurrentWorkingDirectory(Cmd.Directory);
Inputs.CompileCommand = std::move(Cmd);
auto CI = buildCompilerInvocation(Inputs);
if (!CI)
- return createStringError(inconvertibleErrorCode(),
- "Couldn't build compiler invocation");
+ 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);
if (!Clang)
- return createStringError(inconvertibleErrorCode(),
- "Couldn't build compiler instance");
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Couldn't build compiler instance");
SymbolCollector::Options IndexOpts;
- StringMap<FileDigest> FilesToUpdate;
- IndexOpts.FileFilter = createFileFilter(DigestsSnapshot, FilesToUpdate);
+ IndexOpts.FileFilter = createFileFilter(DigestsSnapshot);
IndexFileIn Index;
auto Action = createStaticIndexingAction(
IndexOpts, [&](SymbolSlab S) { Index.Symbols = std::move(S); },
@@ -431,19 +427,21 @@ Error BackgroundIndex::index(tooling::CompileCommand Cmd,
const FrontendInputFile &Input = Clang->getFrontendOpts().Inputs.front();
if (!Action->BeginSourceFile(*Clang, Input))
- return createStringError(inconvertibleErrorCode(),
- "BeginSourceFile() failed");
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "BeginSourceFile() failed");
if (!Action->Execute())
- return createStringError(inconvertibleErrorCode(), "Execute() failed");
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Execute() failed");
Action->EndSourceFile();
if (Clang->hasDiagnostics() &&
Clang->getDiagnostics().hasUncompilableErrorOccurred()) {
- return createStringError(inconvertibleErrorCode(),
- "IndexingAction failed: has uncompilable errors");
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "IndexingAction failed: has uncompilable errors");
}
- assert(Index.Symbols && Index.Refs && Index.Sources
- && "Symbols, Refs and Sources must be set.");
+ assert(Index.Symbols && Index.Refs && Index.Sources &&
+ "Symbols, Refs and Sources must be set.");
log("Indexed {0} ({1} symbols, {2} refs, {3} files)",
Inputs.CompileCommand.Filename, Index.Symbols->size(),
@@ -452,13 +450,7 @@ Error BackgroundIndex::index(tooling::CompileCommand Cmd,
SPAN_ATTACH(Tracer, "refs", int(Index.Refs->numRefs()));
SPAN_ATTACH(Tracer, "sources", int(Index.Sources->size()));
- update(AbsolutePath, std::move(Index), FilesToUpdate, IndexStorage);
- {
- // Make sure hash for the main file is always updated even if there is no
- // index data in it.
- std::lock_guard<std::mutex> Lock(DigestsMu);
- IndexedFileDigests[AbsolutePath] = Hash;
- }
+ update(AbsolutePath, std::move(Index), DigestsSnapshot, IndexStorage);
if (BuildIndexPeriodMs > 0)
SymbolsUpdatedSinceLastIndex = true;
@@ -466,7 +458,152 @@ Error BackgroundIndex::index(tooling::CompileCommand Cmd,
reset(
IndexedSymbols.buildIndex(IndexType::Light, DuplicateHandling::Merge));
- return Error::success();
+ return llvm::Error::success();
+}
+
+std::vector<BackgroundIndex::Source>
+BackgroundIndex::loadShard(const tooling::CompileCommand &Cmd,
+ BackgroundIndexStorage *IndexStorage,
+ llvm::StringSet<> &LoadedShards) {
+ struct ShardInfo {
+ std::string AbsolutePath;
+ std::unique_ptr<IndexFileIn> Shard;
+ FileDigest Digest;
+ };
+ std::vector<ShardInfo> IntermediateSymbols;
+ // Make sure we don't have duplicate elements in the queue. Keys are absolute
+ // paths.
+ llvm::StringSet<> InQueue;
+ auto FS = FSProvider.getFileSystem();
+ // Dependencies of this TU, paired with the information about whether they
+ // need to be re-indexed or not.
+ std::vector<Source> Dependencies;
+ std::queue<Source> ToVisit;
+ std::string AbsolutePath = getAbsolutePath(Cmd).str();
+ // Up until we load the shard related to a dependency it needs to be
+ // re-indexed.
+ ToVisit.emplace(AbsolutePath, true);
+ InQueue.insert(AbsolutePath);
+ // Goes over each dependency.
+ while (!ToVisit.empty()) {
+ Dependencies.push_back(std::move(ToVisit.front()));
+ // Dependencies is not modified during the rest of the loop, so it is safe
+ // to keep the reference.
+ auto &CurDependency = Dependencies.back();
+ ToVisit.pop();
+ // If we have already seen this shard before(either loaded or failed) don't
+ // re-try again. Since the information in the shard won't change from one TU
+ // to another.
+ if (!LoadedShards.try_emplace(CurDependency.Path).second) {
+ // If the dependency needs to be re-indexed, first occurence would already
+ // have detected that, so we don't need to issue it again.
+ CurDependency.NeedsReIndexing = false;
+ continue;
+ }
+
+ auto Shard = IndexStorage->loadShard(CurDependency.Path);
+ if (!Shard || !Shard->Sources) {
+ // File will be returned as requiring re-indexing to caller.
+ vlog("Failed to load shard: {0}", CurDependency.Path);
+ continue;
+ }
+ // These are the edges in the include graph for current dependency.
+ for (const auto &I : *Shard->Sources) {
+ auto U = URI::parse(I.getKey());
+ if (!U)
+ continue;
+ auto AbsolutePath = URI::resolve(*U, CurDependency.Path);
+ if (!AbsolutePath)
+ continue;
+ // Add file as dependency if haven't seen before.
+ if (InQueue.try_emplace(*AbsolutePath).second)
+ ToVisit.emplace(*AbsolutePath, true);
+ // The node contains symbol information only for current file, the rest is
+ // just edges.
+ if (*AbsolutePath != CurDependency.Path)
+ continue;
+
+ // We found source file info for current dependency.
+ assert(I.getValue().Digest != FileDigest{{0}} && "Digest is empty?");
+ ShardInfo SI;
+ SI.AbsolutePath = CurDependency.Path;
+ SI.Shard = std::move(Shard);
+ SI.Digest = I.getValue().Digest;
+ IntermediateSymbols.push_back(std::move(SI));
+ // Check if the source needs re-indexing.
+ // Get the digest, skip it if file doesn't exist.
+ auto Buf = FS->getBufferForFile(CurDependency.Path);
+ if (!Buf) {
+ elog("Couldn't get buffer for file: {0}: {1}", CurDependency.Path,
+ Buf.getError().message());
+ continue;
+ }
+ // If digests match then dependency doesn't need re-indexing.
+ CurDependency.NeedsReIndexing =
+ digest(Buf->get()->getBuffer()) != I.getValue().Digest;
+ }
+ }
+ // Load shard information into background-index.
+ {
+ std::lock_guard<std::mutex> Lock(DigestsMu);
+ // This can override a newer version that is added in another thread,
+ // if this thread sees the older version but finishes later. This
+ // should be rare in practice.
+ for (const ShardInfo &SI : IntermediateSymbols) {
+ auto SS =
+ SI.Shard->Symbols
+ ? llvm::make_unique<SymbolSlab>(std::move(*SI.Shard->Symbols))
+ : nullptr;
+ auto RS = SI.Shard->Refs
+ ? llvm::make_unique<RefSlab>(std::move(*SI.Shard->Refs))
+ : nullptr;
+ IndexedFileDigests[SI.AbsolutePath] = SI.Digest;
+ IndexedSymbols.update(SI.AbsolutePath, std::move(SS), std::move(RS));
+ }
+ }
+
+ return Dependencies;
+}
+
+// Goes over each changed file and loads them from index. Returns the list of
+// TUs that had out-of-date/no shards.
+std::vector<std::pair<tooling::CompileCommand, BackgroundIndexStorage *>>
+BackgroundIndex::loadShards(std::vector<std::string> ChangedFiles) {
+ std::vector<std::pair<tooling::CompileCommand, BackgroundIndexStorage *>>
+ NeedsReIndexing;
+ // Keeps track of the files that will be reindexed, to make sure we won't
+ // re-index same dependencies more than once. Keys are AbsolutePaths.
+ llvm::StringSet<> FilesToIndex;
+ // Keeps track of the loaded shards to make sure we don't perform redundant
+ // disk IO. Keys are absolute paths.
+ llvm::StringSet<> LoadedShards;
+ for (const auto &File : ChangedFiles) {
+ ProjectInfo PI;
+ auto Cmd = CDB.getCompileCommand(File, &PI);
+ if (!Cmd)
+ continue;
+ BackgroundIndexStorage *IndexStorage = IndexStorageFactory(PI.SourceRoot);
+ auto Dependencies = loadShard(*Cmd, IndexStorage, LoadedShards);
+ for (const auto &Dependency : Dependencies) {
+ if (!Dependency.NeedsReIndexing || FilesToIndex.count(Dependency.Path))
+ continue;
+ // FIXME: Currently, we simply schedule indexing on a TU whenever any of
+ // its dependencies needs re-indexing. We might do it smarter by figuring
+ // out a minimal set of TUs that will cover all the stale dependencies.
+ vlog("Enqueueing TU {0} because its dependency {1} needs re-indexing.",
+ Cmd->Filename, Dependency.Path);
+ NeedsReIndexing.push_back({std::move(*Cmd), IndexStorage});
+ // Mark all of this TU's dependencies as to-be-indexed so that we won't
+ // try to re-index those.
+ for (const auto &Dependency : Dependencies)
+ FilesToIndex.insert(Dependency.Path);
+ break;
+ }
+ }
+ vlog("Loaded all shards");
+ reset(IndexedSymbols.buildIndex(IndexType::Light, DuplicateHandling::Merge));
+
+ return NeedsReIndexing;
}
} // namespace clangd
diff --git a/clangd/index/Background.h b/clangd/index/Background.h
index 3318f4fc..808c03a3 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
//
//===----------------------------------------------------------------------===//
@@ -68,20 +67,18 @@ 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.
// The indexing happens in a background thread, so the symbols will be
// available sometime later.
void enqueue(const std::vector<std::string> &ChangedFiles);
- void enqueue(const std::string &File);
// Cause background threads to stop after ther current task, any remaining
// tasks will be discarded.
@@ -92,14 +89,14 @@ public:
blockUntilIdleForTest(llvm::Optional<double> TimeoutSeconds = 10);
private:
- /// Given index results from a TU, only update files in \p FilesToUpdate.
- /// Also stores new index information on IndexStorage.
+ /// Given index results from a TU, only update symbols coming from files with
+ /// different digests than \p DigestsSnapshot. Also stores new index
+ /// information on IndexStorage.
void update(llvm::StringRef MainFile, IndexFileIn Index,
- const llvm::StringMap<FileDigest> &FilesToUpdate,
+ const llvm::StringMap<FileDigest> &DigestsSnapshot,
BackgroundIndexStorage *IndexStorage);
// configuration
- std::string ResourceDir;
const FileSystemProvider &FSProvider;
const GlobalCompilationDatabase &CDB;
Context BackgroundContext;
@@ -118,6 +115,21 @@ private:
std::mutex DigestsMu;
BackgroundIndexStorage::Factory IndexStorageFactory;
+ struct Source {
+ std::string Path;
+ bool NeedsReIndexing;
+ Source(llvm::StringRef Path, bool NeedsReIndexing)
+ : Path(Path), NeedsReIndexing(NeedsReIndexing) {}
+ };
+ // Loads the shards for a single TU and all of its dependencies. Returns the
+ // list of sources and whether they need to be re-indexed.
+ std::vector<Source> loadShard(const tooling::CompileCommand &Cmd,
+ BackgroundIndexStorage *IndexStorage,
+ llvm::StringSet<> &LoadedShards);
+ // Tries to load shards for the ChangedFiles.
+ std::vector<std::pair<tooling::CompileCommand, BackgroundIndexStorage *>>
+ loadShards(std::vector<std::string> ChangedFiles);
+ void enqueue(tooling::CompileCommand Cmd, BackgroundIndexStorage *Storage);
// queue management
using Task = std::function<void()>;
diff --git a/clangd/index/BackgroundIndexStorage.cpp b/clangd/index/BackgroundIndexStorage.cpp
index a83bec6f..266b18ce 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/index/CanonicalIncludes.cpp b/clangd/index/CanonicalIncludes.cpp
index 0cc44feb..6fa366d4 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
//
//===----------------------------------------------------------------------===//
@@ -13,49 +12,50 @@
#include "llvm/Support/Path.h"
#include <algorithm>
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
const char IWYUPragma[] = "// IWYU pragma: private, include ";
} // namespace
-void CanonicalIncludes::addPathSuffixMapping(StringRef Suffix,
- StringRef CanonicalPath) {
- int Components =
- std::distance(sys::path::begin(Suffix), sys::path::end(Suffix));
+void CanonicalIncludes::addPathSuffixMapping(llvm::StringRef Suffix,
+ llvm::StringRef CanonicalPath) {
+ int Components = std::distance(llvm::sys::path::begin(Suffix),
+ llvm::sys::path::end(Suffix));
MaxSuffixComponents = std::max(MaxSuffixComponents, Components);
SuffixHeaderMapping[Suffix] = CanonicalPath;
}
-void CanonicalIncludes::addMapping(StringRef Path, StringRef CanonicalPath) {
+void CanonicalIncludes::addMapping(llvm::StringRef Path,
+ llvm::StringRef CanonicalPath) {
FullPathMapping[Path] = CanonicalPath;
}
-void CanonicalIncludes::addSymbolMapping(StringRef QualifiedName,
- StringRef CanonicalPath) {
+void CanonicalIncludes::addSymbolMapping(llvm::StringRef QualifiedName,
+ llvm::StringRef CanonicalPath) {
this->SymbolMapping[QualifiedName] = CanonicalPath;
}
-StringRef CanonicalIncludes::mapHeader(ArrayRef<std::string> Headers,
- StringRef QualifiedName) const {
+llvm::StringRef
+CanonicalIncludes::mapHeader(llvm::ArrayRef<std::string> Headers,
+ llvm::StringRef QualifiedName) const {
assert(!Headers.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, [](StringRef Include) {
+ 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.
- StringRef Header = *I;
+ llvm::StringRef Header = *I;
// If Header is not expected be included (e.g. .cc file), we fall back to
// the declaring header.
- StringRef Ext = sys::path::extension(Header).trim('.');
+ 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);
@@ -68,7 +68,8 @@ StringRef CanonicalIncludes::mapHeader(ArrayRef<std::string> Headers,
return MapIt->second;
int Components = 1;
- for (auto It = sys::path::rbegin(Header), End = sys::path::rend(Header);
+ for (auto It = llvm::sys::path::rbegin(Header),
+ End = llvm::sys::path::rend(Header);
It != End && Components <= MaxSuffixComponents; ++It, ++Components) {
auto SubPath = Header.substr(It->data() - Header.begin());
auto MappingIt = SuffixHeaderMapping.find(SubPath);
@@ -85,7 +86,7 @@ collectIWYUHeaderMaps(CanonicalIncludes *Includes) {
PragmaCommentHandler(CanonicalIncludes *Includes) : Includes(Includes) {}
bool HandleComment(Preprocessor &PP, SourceRange Range) override {
- StringRef Text =
+ llvm::StringRef Text =
Lexer::getSourceText(CharSourceRange::getCharRange(Range),
PP.getSourceManager(), PP.getLangOpts());
if (!Text.consume_front(IWYUPragma))
diff --git a/clangd/index/CanonicalIncludes.h b/clangd/index/CanonicalIncludes.h
index 3751b000..c9baf0ad 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clangd/index/FileIndex.cpp b/clangd/index/FileIndex.cpp
index b944c72d..bc102d29 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,6 +10,7 @@
#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"
@@ -24,20 +24,16 @@
#include "llvm/ADT/StringRef.h"
#include <memory>
-using namespace llvm;
namespace clang {
namespace clangd {
static std::pair<SymbolSlab, RefSlab>
indexSymbols(ASTContext &AST, std::shared_ptr<Preprocessor> PP,
- 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;
@@ -49,7 +45,7 @@ indexSymbols(ASTContext &AST, std::shared_ptr<Preprocessor> PP,
if (IsIndexMainAST) {
// We only collect refs when indexing main AST.
CollectorOpts.RefFilter = RefKind::All;
- }else {
+ } else {
IndexOpts.IndexMacrosInPreprocessor = true;
CollectorOpts.CollectMacro = true;
}
@@ -74,16 +70,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;
}
@@ -116,7 +112,7 @@ FileSymbols::buildIndex(IndexType Type, DuplicateHandling DuplicateHandle) {
std::vector<Symbol> SymsStorage;
switch (DuplicateHandle) {
case DuplicateHandling::Merge: {
- DenseMap<SymbolID, Symbol> Merged;
+ llvm::DenseMap<SymbolID, Symbol> Merged;
for (const auto &Slab : SymbolSlabs) {
for (const auto &Sym : *Slab) {
auto I = Merged.try_emplace(Sym.ID, Sym);
@@ -143,9 +139,9 @@ FileSymbols::buildIndex(IndexType Type, DuplicateHandling DuplicateHandle) {
}
std::vector<Ref> RefsStorage; // Contiguous ranges for each SymbolID.
- DenseMap<SymbolID, ArrayRef<Ref>> AllRefs;
+ llvm::DenseMap<SymbolID, llvm::ArrayRef<Ref>> AllRefs;
{
- DenseMap<SymbolID, SmallVector<Ref, 4>> MergedRefs;
+ llvm::DenseMap<SymbolID, llvm::SmallVector<Ref, 4>> MergedRefs;
size_t Count = 0;
for (const auto &RefSlab : RefSlabs)
for (const auto &Sym : *RefSlab) {
@@ -161,8 +157,8 @@ FileSymbols::buildIndex(IndexType Type, DuplicateHandling DuplicateHandle) {
llvm::copy(SymRefs, back_inserter(RefsStorage));
AllRefs.try_emplace(
Sym.first,
- ArrayRef<Ref>(&RefsStorage[RefsStorage.size() - SymRefs.size()],
- SymRefs.size()));
+ llvm::ArrayRef<Ref>(&RefsStorage[RefsStorage.size() - SymRefs.size()],
+ SymRefs.size()));
}
}
@@ -177,13 +173,13 @@ FileSymbols::buildIndex(IndexType Type, DuplicateHandling DuplicateHandle) {
switch (Type) {
case IndexType::Light:
return llvm::make_unique<MemIndex>(
- make_pointee_range(AllSymbols), std::move(AllRefs),
+ llvm::make_pointee_range(AllSymbols), std::move(AllRefs),
std::make_tuple(std::move(SymbolSlabs), std::move(RefSlabs),
std::move(RefsStorage), std::move(SymsStorage)),
StorageSize);
case IndexType::Heavy:
return llvm::make_unique<dex::Dex>(
- make_pointee_range(AllSymbols), std::move(AllRefs),
+ llvm::make_pointee_range(AllSymbols), std::move(AllRefs),
std::make_tuple(std::move(SymbolSlabs), std::move(RefSlabs),
std::move(RefsStorage), std::move(SymsStorage)),
StorageSize);
@@ -197,8 +193,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..f1e37c33 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,7 @@
#include "Index.h"
#include "MemIndex.h"
#include "Merge.h"
+#include "index/CanonicalIncludes.h"
#include "clang/Lex/Preprocessor.h"
#include <memory>
@@ -85,7 +85,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 +126,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 dd4b5eb3..36c591d9 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
//
//===----------------------------------------------------------------------===//
@@ -14,7 +13,6 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
namespace clang {
namespace clangd {
@@ -35,14 +33,14 @@ void SymbolLocation::Position::setColumn(uint32_t Col) {
Column = Col;
}
-raw_ostream &operator<<(raw_ostream &OS, const SymbolLocation &L) {
+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() << ")";
}
-raw_ostream &operator<<(raw_ostream &OS, SymbolOrigin O) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SymbolOrigin O) {
if (O == SymbolOrigin::Unknown)
return OS << "unknown";
constexpr static char Sigils[] = "ADSM4567";
@@ -52,18 +50,18 @@ raw_ostream &operator<<(raw_ostream &OS, SymbolOrigin O) {
return OS;
}
-raw_ostream &operator<<(raw_ostream &OS, Symbol::SymbolFlag F) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Symbol::SymbolFlag F) {
if (F == Symbol::None)
return OS << "None";
- std::string s;
+ std::string S;
if (F & Symbol::Deprecated)
- s += "deprecated|";
+ S += "deprecated|";
if (F & Symbol::IndexedForCodeCompletion)
- s += "completion|";
- return OS << StringRef(s).rtrim('|');
+ S += "completion|";
+ return OS << llvm::StringRef(S).rtrim('|');
}
-raw_ostream &operator<<(raw_ostream &OS, const Symbol &S) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S) {
return OS << S.Scope << S.Name;
}
@@ -85,8 +83,8 @@ SymbolSlab::const_iterator SymbolSlab::find(const SymbolID &ID) const {
}
// Copy the underlying data of the symbol into the owned arena.
-static void own(Symbol &S, UniqueStringSaver &Strings) {
- visitStrings(S, [&](StringRef &V) { V = Strings.save(V); });
+static void own(Symbol &S, llvm::UniqueStringSaver &Strings) {
+ visitStrings(S, [&](llvm::StringRef &V) { V = Strings.save(V); });
}
void SymbolSlab::Builder::insert(const Symbol &S) {
@@ -106,14 +104,14 @@ SymbolSlab SymbolSlab::Builder::build() && {
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.
- BumpPtrAllocator NewArena;
- UniqueStringSaver Strings(NewArena);
+ llvm::BumpPtrAllocator NewArena;
+ llvm::UniqueStringSaver Strings(NewArena);
for (auto &S : Symbols)
own(S, Strings);
return SymbolSlab(std::move(NewArena), std::move(Symbols));
}
-raw_ostream &operator<<(raw_ostream &OS, RefKind K) {
+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"};
@@ -129,7 +127,7 @@ raw_ostream &operator<<(raw_ostream &OS, RefKind K) {
return OS;
}
-raw_ostream &operator<<(raw_ostream &OS, const Ref &R) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Ref &R) {
return OS << R.Location << ":" << R.Kind;
}
@@ -143,7 +141,7 @@ void RefSlab::Builder::insert(const SymbolID &ID, const Ref &S) {
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, ArrayRef<Ref>>> Result;
+ std::vector<std::pair<SymbolID, llvm::ArrayRef<Ref>>> Result;
Result.reserve(Refs.size());
size_t NumRefs = 0;
for (auto &Sym : Refs) {
@@ -155,7 +153,7 @@ RefSlab RefSlab::Builder::build() && {
NumRefs += SymRefs.size();
auto *Array = Arena.Allocate<Ref>(SymRefs.size());
std::uninitialized_copy(SymRefs.begin(), SymRefs.end(), Array);
- Result.emplace_back(Sym.first, ArrayRef<Ref>(Array, SymRefs.size()));
+ Result.emplace_back(Sym.first, llvm::ArrayRef<Ref>(Array, SymRefs.size()));
}
return RefSlab(std::move(Result), std::move(Arena), NumRefs);
}
@@ -174,40 +172,42 @@ std::shared_ptr<SymbolIndex> SwapIndex::snapshot() const {
return Index;
}
-bool fromJSON(const json::Value &Parameters, FuzzyFindRequest &Request) {
- json::ObjectMapper O(Parameters);
+bool fromJSON(const llvm::json::Value &Parameters, FuzzyFindRequest &Request) {
+ llvm::json::ObjectMapper O(Parameters);
int64_t Limit;
bool OK =
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;
}
-json::Value toJSON(const FuzzyFindRequest &Request) {
- return json::Object{
+llvm::json::Value toJSON(const FuzzyFindRequest &Request) {
+ return llvm::json::Object{
{"Query", Request.Query},
- {"Scopes", json::Array{Request.Scopes}},
+ {"Scopes", llvm::json::Array{Request.Scopes}},
{"AnyScope", Request.AnyScope},
{"Limit", Request.Limit},
{"RestrictForCodeCompletion", Request.RestrictForCodeCompletion},
- {"ProximityPaths", json::Array{Request.ProximityPaths}},
+ {"ProximityPaths", llvm::json::Array{Request.ProximityPaths}},
+ {"PreferredTypes", llvm::json::Array{Request.PreferredTypes}},
};
}
bool SwapIndex::fuzzyFind(const FuzzyFindRequest &R,
- function_ref<void(const Symbol &)> CB) const {
+ llvm::function_ref<void(const Symbol &)> CB) const {
return snapshot()->fuzzyFind(R, CB);
}
void SwapIndex::lookup(const LookupRequest &R,
- function_ref<void(const Symbol &)> CB) const {
+ llvm::function_ref<void(const Symbol &)> CB) const {
return snapshot()->lookup(R, CB);
}
void SwapIndex::refs(const RefsRequest &R,
- function_ref<void(const Ref &)> CB) const {
+ llvm::function_ref<void(const Ref &)> CB) const {
return snapshot()->refs(R, CB);
}
size_t SwapIndex::estimateMemoryUsage() const {
diff --git a/clangd/index/Index.h b/clangd/index/Index.h
index a5552d4f..4f6feb93 100644
--- a/clangd/index/Index.h
+++ b/clangd/index/Index.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
@@ -185,19 +184,23 @@ struct Symbol {
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 {
@@ -223,17 +226,22 @@ struct Symbol {
/// - 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;
@@ -446,14 +454,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); }
};
@@ -467,6 +476,10 @@ struct LookupRequest {
struct RefsRequest {
llvm::DenseSet<SymbolID> IDs;
RefKind Filter = RefKind::All;
+ /// If set, limit the number of refers returned from the index. The index may
+ /// choose to return less than this, e.g. it tries to avoid returning stale
+ /// results.
+ llvm::Optional<uint32_t> Limit;
};
/// Interface for symbol indexes that can be used for searching or
diff --git a/clangd/index/IndexAction.cpp b/clangd/index/IndexAction.cpp
index 63e1155f..a6df64b7 100644
--- a/clangd/index/IndexAction.cpp
+++ b/clangd/index/IndexAction.cpp
@@ -4,7 +4,6 @@
#include "clang/Index/IndexingAction.h"
#include "clang/Tooling/Tooling.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -63,10 +62,10 @@ public:
// Add edges from including files to includes.
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
- StringRef FileName, bool IsAngled,
+ llvm::StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange, const FileEntry *File,
- StringRef SearchPath, StringRef RelativePath,
- const Module *Imported,
+ llvm::StringRef SearchPath,
+ llvm::StringRef RelativePath, const Module *Imported,
SrcMgr::CharacteristicKind FileType) override {
auto IncludeURI = toURI(File);
if (!IncludeURI)
@@ -116,8 +115,8 @@ public:
Includes(std::move(Includes)),
PragmaHandler(collectIWYUHeaderMaps(this->Includes.get())) {}
- std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) override {
+ std::unique_ptr<ASTConsumer>
+ CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) override {
CI.getPreprocessor().addCommentHandler(PragmaHandler.get());
if (IncludeGraphCallback != nullptr)
CI.getPreprocessor().addPPCallbacks(
@@ -137,7 +136,7 @@ public:
const auto &CI = getCompilerInstance();
if (CI.hasDiagnostics() &&
CI.getDiagnostics().hasUncompilableErrorOccurred()) {
- errs() << "Skipping TU due to uncompilable errors\n";
+ llvm::errs() << "Skipping TU due to uncompilable errors\n";
return;
}
SymbolsCallback(Collector->takeSymbols());
diff --git a/clangd/index/IndexAction.h b/clangd/index/IndexAction.h
index f2c5298f..748b26e1 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/index/MemIndex.cpp b/clangd/index/MemIndex.cpp
index 42340e8e..531d1f6d 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
//
//===-------------------------------------------------------------------===//
@@ -13,7 +12,6 @@
#include "Quality.h"
#include "Trace.h"
-using namespace llvm;
namespace clang {
namespace clangd {
@@ -25,8 +23,9 @@ std::unique_ptr<SymbolIndex> MemIndex::build(SymbolSlab Slab, RefSlab Refs) {
BackingDataSize);
}
-bool MemIndex::fuzzyFind(const FuzzyFindRequest &Req,
- function_ref<void(const Symbol &)> Callback) const {
+bool MemIndex::fuzzyFind(
+ const FuzzyFindRequest &Req,
+ llvm::function_ref<void(const Symbol &)> Callback) const {
assert(!StringRef(Req.Query).contains("::") &&
"There must be no :: in query.");
trace::Span Tracer("MemIndex fuzzyFind");
@@ -39,7 +38,7 @@ bool MemIndex::fuzzyFind(const FuzzyFindRequest &Req,
const Symbol *Sym = Pair.second;
// Exact match against all possible scopes.
- if (!Req.AnyScope && !is_contained(Req.Scopes, Sym->Scope))
+ if (!Req.AnyScope && !llvm::is_contained(Req.Scopes, Sym->Scope))
continue;
if (Req.RestrictForCodeCompletion &&
!(Sym->Flags & Symbol::IndexedForCodeCompletion))
@@ -57,7 +56,7 @@ bool MemIndex::fuzzyFind(const FuzzyFindRequest &Req,
}
void MemIndex::lookup(const LookupRequest &Req,
- function_ref<void(const Symbol &)> Callback) const {
+ llvm::function_ref<void(const Symbol &)> Callback) const {
trace::Span Tracer("MemIndex lookup");
for (const auto &ID : Req.IDs) {
auto I = Index.find(ID);
@@ -67,15 +66,20 @@ void MemIndex::lookup(const LookupRequest &Req,
}
void MemIndex::refs(const RefsRequest &Req,
- function_ref<void(const Ref &)> Callback) const {
+ llvm::function_ref<void(const Ref &)> Callback) const {
trace::Span Tracer("MemIndex refs");
+ uint32_t Remaining =
+ Req.Limit.getValueOr(std::numeric_limits<uint32_t>::max());
for (const auto &ReqID : Req.IDs) {
auto SymRefs = Refs.find(ReqID);
if (SymRefs == Refs.end())
continue;
- for (const auto &O : SymRefs->second)
- if (static_cast<int>(Req.Filter & O.Kind))
+ for (const auto &O : SymRefs->second) {
+ if (Remaining > 0 && static_cast<int>(Req.Filter & O.Kind)) {
+ --Remaining;
Callback(O);
+ }
+ }
}
}
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 42616f05..65e9b86d 100644
--- a/clangd/index/Merge.cpp
+++ b/clangd/index/Merge.cpp
@@ -1,20 +1,22 @@
//===--- 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/Index.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>
-using namespace llvm;
namespace clang {
namespace clangd {
@@ -23,8 +25,9 @@ namespace clangd {
// - find the generating file from each Symbol which is Static-only
// - ask Dynamic if it has that file (needs new SymbolIndex method)
// - if so, drop the Symbol.
-bool MergedIndex::fuzzyFind(const FuzzyFindRequest &Req,
- function_ref<void(const Symbol &)> Callback) const {
+bool MergedIndex::fuzzyFind(
+ const FuzzyFindRequest &Req,
+ llvm::function_ref<void(const Symbol &)> Callback) const {
// We can't step through both sources in parallel. So:
// 1) query all dynamic symbols, slurping results into a slab
// 2) query the static symbols, for each one:
@@ -43,7 +46,7 @@ bool MergedIndex::fuzzyFind(const FuzzyFindRequest &Req,
});
SymbolSlab Dyn = std::move(DynB).build();
- DenseSet<SymbolID> SeenDynamicSymbols;
+ llvm::DenseSet<SymbolID> SeenDynamicSymbols;
More |= Static->fuzzyFind(Req, [&](const Symbol &S) {
auto DynS = Dyn.find(S.ID);
++StaticCount;
@@ -62,8 +65,9 @@ bool MergedIndex::fuzzyFind(const FuzzyFindRequest &Req,
return More;
}
-void MergedIndex::lookup(const LookupRequest &Req,
- function_ref<void(const Symbol &)> Callback) const {
+void MergedIndex::lookup(
+ const LookupRequest &Req,
+ llvm::function_ref<void(const Symbol &)> Callback) const {
trace::Span Tracer("MergedIndex lookup");
SymbolSlab::Builder B;
@@ -84,8 +88,10 @@ void MergedIndex::lookup(const LookupRequest &Req,
}
void MergedIndex::refs(const RefsRequest &Req,
- function_ref<void(const Ref &)> Callback) const {
+ llvm::function_ref<void(const Ref &)> Callback) const {
trace::Span Tracer("MergedIndex refs");
+ uint32_t Remaining =
+ Req.Limit.getValueOr(std::numeric_limits<uint32_t>::max());
// We don't want duplicated refs from the static/dynamic indexes,
// and we can't reliably duplicate them because offsets may differ slightly.
// We consider the dynamic index authoritative and report all its refs,
@@ -94,17 +100,41 @@ void MergedIndex::refs(const RefsRequest &Req,
// FIXME: The heuristic fails if the dynamic index contains a file, but all
// refs were removed (we will report stale ones from the static index).
// Ultimately we should explicit check which index has the file instead.
- StringSet<> DynamicIndexFileURIs;
+ llvm::StringSet<> DynamicIndexFileURIs;
Dynamic->refs(Req, [&](const Ref &O) {
DynamicIndexFileURIs.insert(O.Location.FileURI);
Callback(O);
+ --Remaining;
});
+ if (Remaining == 0)
+ return;
+ // We return less than Req.Limit if static index returns more refs for dirty
+ // files.
Static->refs(Req, [&](const Ref &O) {
- if (!DynamicIndexFileURIs.count(O.Location.FileURI))
+ if (Remaining > 0 && !DynamicIndexFileURIs.count(O.Location.FileURI)) {
+ --Remaining;
Callback(O);
+ }
});
}
+// 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.
@@ -119,12 +149,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;
@@ -134,6 +163,8 @@ Symbol mergeSymbol(const Symbol &L, const Symbol &R) {
S.Documentation = O.Documentation;
if (S.ReturnType == "")
S.ReturnType = O.ReturnType;
+ if (S.Type == "")
+ S.Type = O.Type;
for (const auto &OI : O.IncludeHeaders) {
bool Found = false;
for (auto &SI : S.IncludeHeaders) {
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/Serialization.cpp b/clangd/index/Serialization.cpp
index 1d17a42c..20c43ab0 100644
--- a/clangd/index/Serialization.cpp
+++ b/clangd/index/Serialization.cpp
@@ -1,9 +1,8 @@
//===-- 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
//
//===----------------------------------------------------------------------===//
@@ -17,12 +16,12 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
-Error makeError(const Twine &Msg) {
- return make_error<StringError>(Msg, inconvertibleErrorCode());
+llvm::Error makeError(const llvm::Twine &Msg) {
+ return llvm::make_error<llvm::StringError>(Msg,
+ llvm::inconvertibleErrorCode());
}
// IO PRIMITIVES
@@ -40,14 +39,14 @@ class Reader {
bool Err = false;
public:
- Reader(StringRef Data) : Begin(Data.begin()), End(Data.end()) {}
+ Reader(llvm::StringRef Data) : Begin(Data.begin()), End(Data.end()) {}
// The "error" bit is set by reading past EOF or reading invalid data.
// When in an error state, reads may return zero values: callers should check.
bool err() const { return Err; }
// Did we read all the data, or encounter an error?
bool eof() const { return Begin == End || Err; }
// All the data we didn't read yet.
- StringRef rest() const { return StringRef(Begin, End - Begin); }
+ llvm::StringRef rest() const { return llvm::StringRef(Begin, End - Begin); }
uint8_t consume8() {
if (LLVM_UNLIKELY(Begin == End)) {
@@ -62,17 +61,17 @@ public:
Err = true;
return 0;
}
- auto Ret = support::endian::read32le(Begin);
+ auto Ret = llvm::support::endian::read32le(Begin);
Begin += 4;
return Ret;
}
- StringRef consume(int N) {
+ llvm::StringRef consume(int N) {
if (LLVM_UNLIKELY(Begin + N > End)) {
Err = true;
- return StringRef();
+ return llvm::StringRef();
}
- StringRef Ret(Begin, N);
+ llvm::StringRef Ret(Begin, N);
Begin += N;
return Ret;
}
@@ -90,28 +89,28 @@ public:
return Val;
}
- StringRef consumeString(ArrayRef<StringRef> Strings) {
+ llvm::StringRef consumeString(llvm::ArrayRef<llvm::StringRef> Strings) {
auto StringIndex = consumeVar();
if (LLVM_UNLIKELY(StringIndex >= Strings.size())) {
Err = true;
- return StringRef();
+ return llvm::StringRef();
}
return Strings[StringIndex];
}
SymbolID consumeID() {
- StringRef Raw = consume(SymbolID::RawSize); // short if truncated.
+ llvm::StringRef Raw = consume(SymbolID::RawSize); // short if truncated.
return LLVM_UNLIKELY(err()) ? SymbolID() : SymbolID::fromRaw(Raw);
}
};
-void write32(uint32_t I, raw_ostream &OS) {
- char buf[4];
- support::endian::write32le(buf, I);
- OS.write(buf, sizeof(buf));
+void write32(uint32_t I, llvm::raw_ostream &OS) {
+ char Buf[4];
+ llvm::support::endian::write32le(Buf, I);
+ OS.write(Buf, sizeof(Buf));
}
-void writeVar(uint32_t I, raw_ostream &OS) {
+void writeVar(uint32_t I, llvm::raw_ostream &OS) {
constexpr static uint8_t More = 1 << 7;
if (LLVM_LIKELY(I < 1 << 7)) {
OS.write(I);
@@ -142,10 +141,10 @@ void writeVar(uint32_t I, raw_ostream &OS) {
// Maps each string to a canonical representation.
// Strings remain owned externally (e.g. by SymbolSlab).
class StringTableOut {
- DenseSet<StringRef> Unique;
- std::vector<StringRef> Sorted;
+ llvm::DenseSet<llvm::StringRef> Unique;
+ std::vector<llvm::StringRef> Sorted;
// Since strings are interned, look up can be by pointer.
- DenseMap<std::pair<const char *, size_t>, unsigned> Index;
+ llvm::DenseMap<std::pair<const char *, size_t>, unsigned> Index;
public:
StringTableOut() {
@@ -154,22 +153,22 @@ public:
Unique.insert("");
}
// Add a string to the table. Overwrites S if an identical string exists.
- void intern(StringRef &S) { S = *Unique.insert(S).first; };
+ void intern(llvm::StringRef &S) { S = *Unique.insert(S).first; };
// Finalize the table and write it to OS. No more strings may be added.
- void finalize(raw_ostream &OS) {
+ void finalize(llvm::raw_ostream &OS) {
Sorted = {Unique.begin(), Unique.end()};
llvm::sort(Sorted);
for (unsigned I = 0; I < Sorted.size(); ++I)
Index.try_emplace({Sorted[I].data(), Sorted[I].size()}, I);
std::string RawTable;
- for (StringRef S : Sorted) {
+ for (llvm::StringRef S : Sorted) {
RawTable.append(S);
RawTable.push_back(0);
}
- if (zlib::isAvailable()) {
- SmallString<1> Compressed;
- cantFail(zlib::compress(RawTable, Compressed));
+ if (llvm::zlib::isAvailable()) {
+ llvm::SmallString<1> Compressed;
+ llvm::cantFail(llvm::zlib::compress(RawTable, Compressed));
write32(RawTable.size(), OS);
OS << Compressed;
} else {
@@ -178,7 +177,7 @@ public:
}
}
// Get the ID of an string, which must be interned. Table must be finalized.
- unsigned index(StringRef S) const {
+ unsigned index(llvm::StringRef S) const {
assert(!Sorted.empty() && "table not finalized");
assert(Index.count({S.data(), S.size()}) && "string not interned");
return Index.find({S.data(), S.size()})->second;
@@ -186,33 +185,33 @@ public:
};
struct StringTableIn {
- BumpPtrAllocator Arena;
- std::vector<StringRef> Strings;
+ llvm::BumpPtrAllocator Arena;
+ std::vector<llvm::StringRef> Strings;
};
-Expected<StringTableIn> readStringTable(StringRef Data) {
+llvm::Expected<StringTableIn> readStringTable(llvm::StringRef Data) {
Reader R(Data);
size_t UncompressedSize = R.consume32();
if (R.err())
return makeError("Truncated string table");
- StringRef Uncompressed;
- SmallString<1> UncompressedStorage;
+ llvm::StringRef Uncompressed;
+ llvm::SmallString<1> UncompressedStorage;
if (UncompressedSize == 0) // No compression
Uncompressed = R.rest();
else {
- if (Error E = llvm::zlib::uncompress(R.rest(), UncompressedStorage,
- UncompressedSize))
+ if (llvm::Error E = llvm::zlib::uncompress(R.rest(), UncompressedStorage,
+ UncompressedSize))
return std::move(E);
Uncompressed = UncompressedStorage;
}
StringTableIn Table;
- StringSaver Saver(Table.Arena);
+ llvm::StringSaver Saver(Table.Arena);
R = Reader(Uncompressed);
for (Reader R(Uncompressed); !R.eof();) {
auto Len = R.rest().find(0);
- if (Len == StringRef::npos)
+ if (Len == llvm::StringRef::npos)
return makeError("Bad string table: not null terminated");
Table.Strings.push_back(Saver.save(R.consume(Len)));
R.consume8();
@@ -229,7 +228,7 @@ Expected<StringTableIn> readStringTable(StringRef Data) {
// - most numbers encode as varint
void writeLocation(const SymbolLocation &Loc, const StringTableOut &Strings,
- raw_ostream &OS) {
+ llvm::raw_ostream &OS) {
writeVar(Strings.index(Loc.FileURI), OS);
for (const auto &Endpoint : {Loc.Start, Loc.End}) {
writeVar(Endpoint.line(), OS);
@@ -237,7 +236,8 @@ void writeLocation(const SymbolLocation &Loc, const StringTableOut &Strings,
}
}
-SymbolLocation readLocation(Reader &Data, ArrayRef<StringRef> Strings) {
+SymbolLocation readLocation(Reader &Data,
+ llvm::ArrayRef<llvm::StringRef> Strings) {
SymbolLocation Loc;
Loc.FileURI = Data.consumeString(Strings).data();
for (auto *Endpoint : {&Loc.Start, &Loc.End}) {
@@ -261,7 +261,8 @@ IncludeGraphNode readIncludeGraphNode(Reader &Data,
}
void writeIncludeGraphNode(const IncludeGraphNode &IGN,
- const StringTableOut &Strings, raw_ostream &OS) {
+ const StringTableOut &Strings,
+ llvm::raw_ostream &OS) {
OS.write(IGN.IsTU);
writeVar(Strings.index(IGN.URI), OS);
llvm::StringRef Hash(reinterpret_cast<const char *>(IGN.Digest.data()),
@@ -273,7 +274,7 @@ void writeIncludeGraphNode(const IncludeGraphNode &IGN,
}
void writeSymbol(const Symbol &Sym, const StringTableOut &Strings,
- raw_ostream &OS) {
+ llvm::raw_ostream &OS) {
OS << Sym.ID.raw(); // TODO: once we start writing xrefs and posting lists,
// symbol IDs should probably be in a string table.
OS.write(static_cast<uint8_t>(Sym.SymInfo.Kind));
@@ -300,7 +301,7 @@ void writeSymbol(const Symbol &Sym, const StringTableOut &Strings,
WriteInclude(Include);
}
-Symbol readSymbol(Reader &Data, ArrayRef<StringRef> Strings) {
+Symbol readSymbol(Reader &Data, llvm::ArrayRef<llvm::StringRef> Strings) {
Symbol Sym;
Sym.ID = Data.consumeID();
Sym.SymInfo.Kind = static_cast<index::SymbolKind>(Data.consume8());
@@ -332,8 +333,8 @@ Symbol readSymbol(Reader &Data, ArrayRef<StringRef> Strings) {
// - Ref[NumRefs]
// Fields of Ref are encoded in turn, see implementation.
-void writeRefs(const SymbolID &ID, ArrayRef<Ref> Refs,
- const StringTableOut &Strings, raw_ostream &OS) {
+void writeRefs(const SymbolID &ID, llvm::ArrayRef<Ref> Refs,
+ const StringTableOut &Strings, llvm::raw_ostream &OS) {
OS << ID.raw();
writeVar(Refs.size(), OS);
for (const auto &Ref : Refs) {
@@ -342,8 +343,8 @@ void writeRefs(const SymbolID &ID, ArrayRef<Ref> Refs,
}
}
-std::pair<SymbolID, std::vector<Ref>> readRefs(Reader &Data,
- ArrayRef<StringRef> Strings) {
+std::pair<SymbolID, std::vector<Ref>>
+readRefs(Reader &Data, llvm::ArrayRef<llvm::StringRef> Strings) {
std::pair<SymbolID, std::vector<Ref>> Result;
Result.first = Data.consumeID();
Result.second.resize(Data.consumeVar());
@@ -368,17 +369,18 @@ std::pair<SymbolID, std::vector<Ref>> readRefs(Reader &Data,
// data. Later we may want to support some backward compatibility.
constexpr static uint32_t Version = 8;
-Expected<IndexFileIn> readRIFF(StringRef Data) {
+llvm::Expected<IndexFileIn> readRIFF(llvm::StringRef Data) {
auto RIFF = riff::readFile(Data);
if (!RIFF)
return RIFF.takeError();
if (RIFF->Type != riff::fourCC("CdIx"))
return makeError("wrong RIFF type");
- StringMap<StringRef> Chunks;
+ llvm::StringMap<llvm::StringRef> Chunks;
for (const auto &Chunk : RIFF->Chunks)
- Chunks.try_emplace(StringRef(Chunk.ID.data(), Chunk.ID.size()), Chunk.Data);
+ Chunks.try_emplace(llvm::StringRef(Chunk.ID.data(), Chunk.ID.size()),
+ Chunk.Data);
- for (StringRef RequiredChunk : {"meta", "stri"})
+ for (llvm::StringRef RequiredChunk : {"meta", "stri"})
if (!Chunks.count(RequiredChunk))
return makeError("missing required chunk " + RequiredChunk);
@@ -439,14 +441,14 @@ void visitStrings(IncludeGraphNode &IGN, const Callback &CB) {
CB(Include);
}
-void writeRIFF(const IndexFileOut &Data, raw_ostream &OS) {
+void writeRIFF(const IndexFileOut &Data, llvm::raw_ostream &OS) {
assert(Data.Symbols && "An index file without symbols makes no sense!");
riff::File RIFF;
RIFF.Type = riff::fourCC("CdIx");
- SmallString<4> Meta;
+ llvm::SmallString<4> Meta;
{
- raw_svector_ostream MetaOS(Meta);
+ llvm::raw_svector_ostream MetaOS(Meta);
write32(Version, MetaOS);
}
RIFF.Chunks.push_back({riff::fourCC("meta"), Meta});
@@ -455,13 +457,15 @@ void writeRIFF(const IndexFileOut &Data, raw_ostream &OS) {
std::vector<Symbol> Symbols;
for (const auto &Sym : *Data.Symbols) {
Symbols.emplace_back(Sym);
- visitStrings(Symbols.back(), [&](StringRef &S) { Strings.intern(S); });
+ visitStrings(Symbols.back(),
+ [&](llvm::StringRef &S) { Strings.intern(S); });
}
std::vector<IncludeGraphNode> Sources;
if (Data.Sources)
for (const auto &Source : *Data.Sources) {
Sources.push_back(Source.getValue());
- visitStrings(Sources.back(), [&](StringRef &S) { Strings.intern(S); });
+ visitStrings(Sources.back(),
+ [&](llvm::StringRef &S) { Strings.intern(S); });
}
std::vector<std::pair<SymbolID, std::vector<Ref>>> Refs;
@@ -469,7 +473,7 @@ void writeRIFF(const IndexFileOut &Data, raw_ostream &OS) {
for (const auto &Sym : *Data.Refs) {
Refs.emplace_back(Sym);
for (auto &Ref : Refs.back().second) {
- StringRef File = Ref.Location.FileURI;
+ llvm::StringRef File = Ref.Location.FileURI;
Strings.intern(File);
Ref.Location.FileURI = File.data();
}
@@ -478,14 +482,14 @@ void writeRIFF(const IndexFileOut &Data, raw_ostream &OS) {
std::string StringSection;
{
- raw_string_ostream StringOS(StringSection);
+ llvm::raw_string_ostream StringOS(StringSection);
Strings.finalize(StringOS);
}
RIFF.Chunks.push_back({riff::fourCC("stri"), StringSection});
std::string SymbolSection;
{
- raw_string_ostream SymbolOS(SymbolSection);
+ llvm::raw_string_ostream SymbolOS(SymbolSection);
for (const auto &Sym : Symbols)
writeSymbol(Sym, Strings, SymbolOS);
}
@@ -494,7 +498,7 @@ void writeRIFF(const IndexFileOut &Data, raw_ostream &OS) {
std::string RefsSection;
if (Data.Refs) {
{
- raw_string_ostream RefsOS(RefsSection);
+ llvm::raw_string_ostream RefsOS(RefsSection);
for (const auto &Sym : Refs)
writeRefs(Sym.first, Sym.second, Strings, RefsOS);
}
@@ -504,7 +508,7 @@ void writeRIFF(const IndexFileOut &Data, raw_ostream &OS) {
std::string SrcsSection;
{
{
- raw_string_ostream SrcsOS(SrcsSection);
+ llvm::raw_string_ostream SrcsOS(SrcsSection);
for (const auto &SF : Sources)
writeIncludeGraphNode(SF, Strings, SrcsOS);
}
@@ -517,10 +521,10 @@ void writeRIFF(const IndexFileOut &Data, raw_ostream &OS) {
} // namespace
// Defined in YAMLSerialization.cpp.
-void writeYAML(const IndexFileOut &, raw_ostream &);
-Expected<IndexFileIn> readYAML(StringRef);
+void writeYAML(const IndexFileOut &, llvm::raw_ostream &);
+llvm::Expected<IndexFileIn> readYAML(llvm::StringRef);
-raw_ostream &operator<<(raw_ostream &OS, const IndexFileOut &O) {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const IndexFileOut &O) {
switch (O.Format) {
case IndexFileFormat::RIFF:
writeRIFF(O, OS);
@@ -532,22 +536,23 @@ raw_ostream &operator<<(raw_ostream &OS, const IndexFileOut &O) {
return OS;
}
-Expected<IndexFileIn> readIndexFile(StringRef Data) {
+llvm::Expected<IndexFileIn> readIndexFile(llvm::StringRef Data) {
if (Data.startswith("RIFF")) {
return readRIFF(Data);
} else if (auto YAMLContents = readYAML(Data)) {
return std::move(*YAMLContents);
} else {
return makeError("Not a RIFF file and failed to parse as YAML: " +
- toString(YAMLContents.takeError()));
+ llvm::toString(YAMLContents.takeError()));
}
}
-std::unique_ptr<SymbolIndex> loadIndex(StringRef SymbolFilename, bool UseDex) {
+std::unique_ptr<SymbolIndex> loadIndex(llvm::StringRef SymbolFilename,
+ bool UseDex) {
trace::Span OverallTracer("LoadIndex");
- auto Buffer = MemoryBuffer::getFile(SymbolFilename);
+ auto Buffer = llvm::MemoryBuffer::getFile(SymbolFilename);
if (!Buffer) {
- errs() << "Can't open " << SymbolFilename << "\n";
+ llvm::errs() << "Can't open " << SymbolFilename << "\n";
return nullptr;
}
@@ -561,7 +566,7 @@ std::unique_ptr<SymbolIndex> loadIndex(StringRef SymbolFilename, bool UseDex) {
if (I->Refs)
Refs = std::move(*I->Refs);
} else {
- errs() << "Bad Index: " << toString(I.takeError()) << "\n";
+ llvm::errs() << "Bad Index: " << llvm::toString(I.takeError()) << "\n";
return nullptr;
}
}
diff --git a/clangd/index/Serialization.h b/clangd/index/Serialization.h
index c403b957..d81b8968 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/clangd/index/SymbolCollector.cpp b/clangd/index/SymbolCollector.cpp
index b78bc5f5..cbbbd505 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
//
//===----------------------------------------------------------------------===//
@@ -29,7 +28,6 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -51,38 +49,18 @@ const NamedDecl &getTemplateOrThis(const NamedDecl &ND) {
//
// The Path can be a path relative to the build directory, or retrieved from
// the SourceManager.
-Optional<std::string> toURI(const SourceManager &SM, StringRef Path,
- const SymbolCollector::Options &Opts) {
- SmallString<128> AbsolutePath(Path);
- if (std::error_code EC =
- SM.getFileManager().getVirtualFileSystem()->makeAbsolute(
- AbsolutePath))
- log("Warning: could not make absolute file: {0}", EC.message());
- if (sys::path::is_absolute(AbsolutePath)) {
- // Handle the symbolic link path case where the current working directory
- // (getCurrentWorkingDirectory) is a symlink./ We always want to the real
- // file path (instead of the symlink path) for the C++ symbols.
- //
- // Consider the following example:
- //
- // src dir: /project/src/foo.h
- // current working directory (symlink): /tmp/build -> /project/src/
- //
- // The file path of Symbol is "/project/src/foo.h" instead of
- // "/tmp/build/foo.h"
- if (const DirectoryEntry *Dir = SM.getFileManager().getDirectory(
- sys::path::parent_path(AbsolutePath.str()))) {
- StringRef DirName = SM.getFileManager().getCanonicalName(Dir);
- SmallString<128> AbsoluteFilename;
- sys::path::append(AbsoluteFilename, DirName,
- sys::path::filename(AbsolutePath.str()));
- AbsolutePath = AbsoluteFilename;
- }
- } else if (!Opts.FallbackDir.empty()) {
- sys::fs::make_absolute(Opts.FallbackDir, AbsolutePath);
+std::string toURI(const SourceManager &SM, llvm::StringRef Path,
+ const SymbolCollector::Options &Opts) {
+ llvm::SmallString<128> AbsolutePath(Path);
+ if (auto CanonPath =
+ getCanonicalPath(SM.getFileManager().getFile(Path), SM)) {
+ AbsolutePath = *CanonPath;
}
-
- sys::path::remove_dots(AbsolutePath, /*remove_dot_dot=*/true);
+ // We don't perform is_absolute check in an else branch because makeAbsolute
+ // might return a relative path on some InMemoryFileSystems.
+ if (!llvm::sys::path::is_absolute(AbsolutePath) && !Opts.FallbackDir.empty())
+ llvm::sys::fs::make_absolute(Opts.FallbackDir, AbsolutePath);
+ llvm::sys::path::remove_dots(AbsolutePath, /*remove_dot_dot=*/true);
return URI::create(AbsolutePath).toString();
}
@@ -122,7 +100,7 @@ bool isPrivateProtoDecl(const NamedDecl &ND) {
// will include OUTER_INNER and exclude some_enum_constant.
// FIXME: the heuristic relies on naming style (i.e. no underscore in
// user-defined names) and can be improved.
- return (ND.getKind() != Decl::EnumConstant) || any_of(Name, islower);
+ return (ND.getKind() != Decl::EnumConstant) || llvm::any_of(Name, islower);
}
// We only collect #include paths for symbols that are suitable for global code
@@ -150,9 +128,9 @@ 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.
-Optional<std::string> getIncludeHeader(StringRef QName, const SourceManager &SM,
- SourceLocation Loc,
- const SymbolCollector::Options &Opts) {
+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) {
@@ -168,7 +146,7 @@ Optional<std::string> getIncludeHeader(StringRef QName, const SourceManager &SM,
}
if (Headers.empty())
return None;
- StringRef Header = Headers[0];
+ llvm::StringRef Header = Headers[0];
if (Opts.Includes) {
Header = Opts.Includes->mapHeader(Headers, QName);
if (Header.startswith("<") || Header.startswith("\""))
@@ -206,22 +184,22 @@ bool shouldIndexFile(const SourceManager &SM, FileID FID,
}
// Return the symbol location of the token at \p TokLoc.
-Optional<SymbolLocation> getTokenLocation(SourceLocation TokLoc,
- const SourceManager &SM,
- const SymbolCollector::Options &Opts,
- const clang::LangOptions &LangOpts,
- std::string &FileURIStorage) {
- auto U = toURI(SM, SM.getFilename(TokLoc), Opts);
- if (!U)
+llvm::Optional<SymbolLocation>
+getTokenLocation(SourceLocation TokLoc, const SourceManager &SM,
+ const SymbolCollector::Options &Opts,
+ const clang::LangOptions &LangOpts,
+ std::string &FileURIStorage) {
+ auto Path = SM.getFilename(TokLoc);
+ if (Path.empty())
return None;
- FileURIStorage = std::move(*U);
+ FileURIStorage = toURI(SM, Path, Opts);
SymbolLocation Result;
Result.FileURI = FileURIStorage.c_str();
auto Range = getTokenRange(TokLoc, SM, LangOpts);
Result.Start = Range.first;
Result.End = Range.second;
- return std::move(Result);
+ return Result;
}
// Checks whether \p ND is a definition of a TagDecl (class/struct/enum/union)
@@ -261,22 +239,20 @@ void SymbolCollector::initialize(ASTContext &Ctx) {
bool SymbolCollector::shouldCollectSymbol(const NamedDecl &ND,
const ASTContext &ASTCtx,
- const Options &Opts) {
+ 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;
- // FIXME: figure out a way to handle internal linkage symbols (e.g. static
- // variables, function) defined in the .cc files. Also we skip the symbols
- // in anonymous namespace as the qualifier names of these symbols are like
- // `foo::<anonymous>::bar`, which need a special handling.
- // In real world projects, we have a relatively large set of header files
- // that define static variables (like "static const int A = 1;"), we still
- // want to collect these symbols, although they cause potential ODR
- // violations.
- if (ND.isInAnonymousNamespace())
+ // Skip main-file symbols if we are not collecting them.
+ if (IsMainFileOnly && !Opts.CollectMainFileSymbols)
+ return false;
+
+ // Skip symbols in anonymous namespaces in header files.
+ if (!IsMainFileOnly && ND.isInAnonymousNamespace())
return false;
// We want most things but not "local" symbols such as symbols inside
@@ -306,10 +282,6 @@ bool SymbolCollector::shouldCollectSymbol(const NamedDecl &ND,
explicitTemplateSpecialization<VarDecl>(ND))
return false;
- const auto &SM = ASTCtx.getSourceManager();
- // Skip decls in the main file.
- if (SM.isInMainFile(SM.getExpansionLoc(ND.getBeginLoc())))
- return false;
// Avoid indexing internal symbols in protobuf generated headers.
if (isPrivateProtoDecl(ND))
return false;
@@ -319,7 +291,7 @@ bool SymbolCollector::shouldCollectSymbol(const NamedDecl &ND,
// Always return true to continue indexing.
bool SymbolCollector::handleDeclOccurence(
const Decl *D, index::SymbolRoleSet Roles,
- ArrayRef<index::SymbolRelation> Relations, SourceLocation Loc,
+ llvm::ArrayRef<index::SymbolRelation> Relations, SourceLocation Loc,
index::IndexDataConsumer::ASTNodeInfo ASTNode) {
assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set.");
assert(CompletionAllocator && CompletionTUInfo);
@@ -356,9 +328,15 @@ bool SymbolCollector::handleDeclOccurence(
if (IsOnlyRef && !CollectRef)
return true;
- if (!shouldCollectSymbol(*ND, *ASTCtx, Opts))
+
+ // 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))
return true;
- if (CollectRef && !isa<NamespaceDecl>(ND) &&
+ // Do not store references to main-file symbols.
+ if (CollectRef && !IsMainFileOnly && !isa<NamespaceDecl>(ND) &&
(Opts.RefsInHeaders || SM.getFileID(SpellingLoc) == SM.getMainFileID()))
DeclRefs[ND].emplace_back(SpellingLoc, Roles);
// Don't continue indexing if this is a mere reference.
@@ -369,19 +347,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));
- else if (isPreferredDeclaration(OriginalDecl, Roles))
+ BasicSymbol = addDeclaration(*ND, std::move(*ID), IsMainFileOnly);
+ 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));
+ BasicSymbol = addDeclaration(*OriginalDecl, std::move(*ID), IsMainFileOnly);
if (Roles & static_cast<unsigned>(index::SymbolRole::Definition))
- addDefinition(OriginalDecl, *BasicSymbol);
+ addDefinition(*OriginalDecl, *BasicSymbol);
return true;
}
@@ -395,13 +379,21 @@ bool SymbolCollector::handleMacroOccurence(const IdentifierInfo *Name,
const auto &SM = PP->getSourceManager();
auto DefLoc = MI->getDefinitionLoc();
- if (SM.isInMainFile(SM.getExpansionLoc(DefLoc)))
- 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())
return true;
+ // 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
// file. The macro may not be an interesting symbol, but it's cheaper to check
// at the end.
@@ -426,7 +418,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.
@@ -481,17 +476,13 @@ void SymbolCollector::finish() {
}
const auto &SM = ASTCtx->getSourceManager();
- DenseMap<FileID, std::string> URICache;
- auto GetURI = [&](FileID FID) -> Optional<std::string> {
+ llvm::DenseMap<FileID, std::string> URICache;
+ auto GetURI = [&](FileID FID) -> llvm::Optional<std::string> {
auto Found = URICache.find(FID);
if (Found == URICache.end()) {
if (auto *FileEntry = SM.getFileEntryForID(FID)) {
auto FileURI = toURI(SM, FileEntry->getName(), Opts);
- if (!FileURI) {
- log("Failed to create URI for file: {0}\n", FileEntry);
- FileURI = ""; // reset to empty as we also want to cache this case.
- }
- Found = URICache.insert({FID, *FileURI}).first;
+ Found = URICache.insert({FID, FileURI}).first;
} else {
// Ignore cases where we can not find a corresponding file entry
// for the loc, thoses are not interesting, e.g. symbols formed
@@ -531,7 +522,8 @@ void SymbolCollector::finish() {
}
const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND,
- SymbolID ID) {
+ SymbolID ID,
+ bool IsMainFileOnly) {
auto &Ctx = ND.getASTContext();
auto &SM = Ctx.getSourceManager();
@@ -542,10 +534,13 @@ const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND,
// FIXME: this returns foo:bar: for objective-C methods, we prefer only foo:
// for consistency with CodeCompletionString and a clean name/signature split.
- if (isIndexedForCodeCompletion(ND, Ctx))
+ // We collect main-file symbols, but do not use them for code completion.
+ if (!IsMainFileOnly && isIndexedForCodeCompletion(ND, Ctx))
S.Flags |= Symbol::IndexedForCodeCompletion;
if (isImplementationDetail(&ND))
S.Flags |= Symbol::ImplementationDetail;
+ if (!IsMainFileOnly)
+ S.Flags |= Symbol::VisibleOutsideFile;
S.SymInfo = index::getSymbolInfo(&ND);
std::string FileURI;
auto Loc = findNameLoc(&ND);
@@ -555,6 +550,10 @@ const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND,
getTokenLocation(Loc, SM, Opts, ASTCtx->getLangOpts(), FileURI))
S.CanonicalDeclaration = *DeclLoc;
+ S.Origin = Opts.Origin;
+ if (ND.getAvailability() == AR_Deprecated)
+ S.Flags |= Symbol::Deprecated;
+
// Add completion info.
// FIXME: we may want to choose a different redecl, or combine from several.
assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set.");
@@ -564,13 +563,28 @@ const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND,
*ASTCtx, *PP, CodeCompletionContext::CCC_Symbol, *CompletionAllocator,
*CompletionTUInfo,
/*IncludeBriefComments*/ false);
- std::string Signature;
- std::string SnippetSuffix;
- getSignature(*CCS, &Signature, &SnippetSuffix);
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)) {
+ Symbols.insert(S);
+ return Symbols.find(S.ID);
+ }
+
+ std::string Signature;
+ std::string SnippetSuffix;
+ getSignature(*CCS, &Signature, &SnippetSuffix);
+ S.Signature = Signature;
+ S.CompletionSnippetSuffix = SnippetSuffix;
std::string ReturnType = getReturnType(*CCS);
+ S.ReturnType = ReturnType;
std::string Include;
if (Opts.CollectIncludePath && shouldCollectIncludePath(S.SymInfo.Kind)) {
@@ -580,10 +594,6 @@ const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND,
QName, SM, SM.getExpansionLoc(ND.getLocation()), Opts))
Include = std::move(*Header);
}
- S.Signature = Signature;
- S.CompletionSnippetSuffix = SnippetSuffix;
- S.Documentation = Documentation;
- S.ReturnType = ReturnType;
if (!Include.empty())
S.IncludeHeaders.emplace_back(Include, 1);
@@ -594,9 +604,6 @@ const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND,
S.Type = TypeStorage->raw();
}
- S.Origin = Opts.Origin;
- if (ND.getAvailability() == AR_Deprecated)
- S.Flags |= Symbol::Deprecated;
Symbols.insert(S);
return Symbols.find(S.ID);
}
diff --git a/clangd/index/SymbolCollector.h b/clangd/index/SymbolCollector.h
index 01f2b0ad..1b10df4c 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
@@ -28,13 +27,14 @@ namespace clangd {
/// It collects most declarations except:
/// - Implicit declarations
/// - Anonymous declarations (anonymous enum/class/struct, etc)
-/// - Declarations in anonymous namespaces
+/// - Declarations in anonymous namespaces in headers
/// - Local declarations (in function bodies, blocks, etc)
-/// - Declarations in main files
/// - Template specializations
/// - Library-specific private declarations (e.g. private declaration generated
/// by protobuf compiler)
///
+/// References to main-file symbols are not collected.
+///
/// See also shouldCollectSymbol(...).
///
/// Clients (e.g. clangd) can use SymbolCollector together with
@@ -72,6 +72,9 @@ public:
/// collect macros. For example, `indexTopLevelDecls` will not index any
/// macro even if this is true.
bool CollectMacro = false;
+ /// Collect symbols local to main-files, such as static functions
+ /// and symbols inside an anonymous namespace.
+ bool CollectMainFileSymbols = true;
/// 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;
@@ -81,7 +84,7 @@ public:
/// Returns true is \p ND should be collected.
static bool shouldCollectSymbol(const NamedDecl &ND, const ASTContext &ASTCtx,
- const Options &Opts);
+ const Options &Opts, bool IsMainFileSymbol);
void initialize(ASTContext &Ctx) override;
@@ -105,7 +108,7 @@ public:
void finish() override;
private:
- const Symbol *addDeclaration(const NamedDecl &, SymbolID);
+ const Symbol *addDeclaration(const NamedDecl &, SymbolID, bool IsMainFileSymbol);
void addDefinition(const NamedDecl &, const Symbol &DeclSymbol);
// All Symbols collected from the AST.
diff --git a/clangd/index/SymbolID.cpp b/clangd/index/SymbolID.cpp
index 0ab74810..b97103d3 100644
--- a/clangd/index/SymbolID.cpp
+++ b/clangd/index/SymbolID.cpp
@@ -1,54 +1,56 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
#include "SymbolID.h"
#include "llvm/Support/SHA1.h"
-using namespace llvm;
namespace clang {
namespace clangd {
-SymbolID::SymbolID(StringRef USR) {
- auto Hash = llvm::SHA1::hash(arrayRefFromStringRef(USR));
+SymbolID::SymbolID(llvm::StringRef USR) {
+ auto Hash = llvm::SHA1::hash(llvm::arrayRefFromStringRef(USR));
static_assert(sizeof(Hash) >= RawSize, "RawSize larger than SHA1");
memcpy(HashValue.data(), Hash.data(), RawSize);
}
llvm::StringRef SymbolID::raw() const {
- return StringRef(reinterpret_cast<const char *>(HashValue.data()), RawSize);
+ return llvm::StringRef(reinterpret_cast<const char *>(HashValue.data()),
+ RawSize);
}
-SymbolID SymbolID::fromRaw(StringRef Raw) {
+SymbolID SymbolID::fromRaw(llvm::StringRef Raw) {
SymbolID ID;
assert(Raw.size() == RawSize);
memcpy(ID.HashValue.data(), Raw.data(), RawSize);
return ID;
}
-std::string SymbolID::str() const { return toHex(raw()); }
+std::string SymbolID::str() const { return llvm::toHex(raw()); }
-Expected<SymbolID> SymbolID::fromStr(StringRef Str) {
+llvm::Expected<SymbolID> SymbolID::fromStr(llvm::StringRef Str) {
if (Str.size() != RawSize * 2)
- return createStringError(inconvertibleErrorCode(), "Bad ID length");
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Bad ID length");
for (char C : Str)
- if (!isHexDigit(C))
- return createStringError(inconvertibleErrorCode(), "Bad hex ID");
- return fromRaw(fromHex(Str));
+ if (!llvm::isHexDigit(C))
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Bad hex ID");
+ return fromRaw(llvm::fromHex(Str));
}
-raw_ostream &operator<<(raw_ostream &OS, const SymbolID &ID) {
- return OS << toHex(ID.raw());
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolID &ID) {
+ return OS << llvm::toHex(ID.raw());
}
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..0e4fc663 100644
--- a/clangd/index/SymbolID.h
+++ b/clangd/index/SymbolID.h
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
diff --git a/clangd/index/YAMLSerialization.cpp b/clangd/index/YAMLSerialization.cpp
index d3ffdddc..7aab39f4 100644
--- a/clangd/index/YAMLSerialization.cpp
+++ b/clangd/index/YAMLSerialization.cpp
@@ -1,9 +1,8 @@
//===--- SymbolYAML.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
//
//===----------------------------------------------------------------------===//
//
@@ -28,8 +27,6 @@
#include "llvm/Support/raw_ostream.h"
#include <cstdint>
-using namespace llvm;
-
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::clangd::Symbol::IncludeHeaderWithReferences)
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::clangd::Ref)
@@ -38,8 +35,8 @@ using RefBundle =
std::pair<clang::clangd::SymbolID, std::vector<clang::clangd::Ref>>;
// This is a pale imitation of std::variant<Symbol, RefBundle>
struct VariantEntry {
- Optional<clang::clangd::Symbol> Symbol;
- Optional<RefBundle> Refs;
+ llvm::Optional<clang::clangd::Symbol> Symbol;
+ llvm::Optional<RefBundle> Refs;
};
// A class helps YAML to serialize the 32-bit encoded position (Line&Column),
// as YAMLIO can't directly map bitfields.
@@ -66,14 +63,14 @@ using clang::index::SymbolLanguage;
struct NormalizedSymbolID {
NormalizedSymbolID(IO &) {}
NormalizedSymbolID(IO &, const SymbolID &ID) {
- raw_string_ostream OS(HexString);
+ llvm::raw_string_ostream OS(HexString);
OS << ID;
}
SymbolID denormalize(IO &I) {
auto ID = SymbolID::fromStr(HexString);
if (!ID) {
- I.setError(toString(ID.takeError()));
+ I.setError(llvm::toString(ID.takeError()));
return SymbolID();
}
return *ID;
@@ -294,8 +291,8 @@ template <> struct MappingTraits<VariantEntry> {
namespace clang {
namespace clangd {
-void writeYAML(const IndexFileOut &O, raw_ostream &OS) {
- yaml::Output Yout(OS);
+void writeYAML(const IndexFileOut &O, llvm::raw_ostream &OS) {
+ llvm::yaml::Output Yout(OS);
for (const auto &Sym : *O.Symbols) {
VariantEntry Entry;
Entry.Symbol = Sym;
@@ -309,23 +306,27 @@ void writeYAML(const IndexFileOut &O, raw_ostream &OS) {
}
}
-Expected<IndexFileIn> readYAML(StringRef Data) {
+llvm::Expected<IndexFileIn> readYAML(llvm::StringRef Data) {
SymbolSlab::Builder Symbols;
RefSlab::Builder Refs;
- BumpPtrAllocator Arena; // store the underlying data of Position::FileURI.
- UniqueStringSaver Strings(Arena);
- yaml::Input Yin(Data, &Strings);
- do {
+ llvm::BumpPtrAllocator
+ Arena; // store the underlying data of Position::FileURI.
+ llvm::UniqueStringSaver Strings(Arena);
+ llvm::yaml::Input Yin(Data, &Strings);
+ while (Yin.setCurrentDocument()) {
+ llvm::yaml::EmptyContext Ctx;
VariantEntry Variant;
- Yin >> Variant;
+ yamlize(Yin, Variant, true, Ctx);
if (Yin.error())
- return errorCodeToError(Yin.error());
+ return llvm::errorCodeToError(Yin.error());
+
if (Variant.Symbol)
Symbols.insert(*Variant.Symbol);
if (Variant.Refs)
for (const auto &Ref : Variant.Refs->second)
Refs.insert(Variant.Refs->first, Ref);
- } while (Yin.nextDocument());
+ Yin.nextDocument();
+ }
IndexFileIn Result;
Result.Symbols.emplace(std::move(Symbols).build());
@@ -336,20 +337,20 @@ Expected<IndexFileIn> readYAML(StringRef Data) {
std::string toYAML(const Symbol &S) {
std::string Buf;
{
- raw_string_ostream OS(Buf);
- yaml::Output Yout(OS);
+ llvm::raw_string_ostream OS(Buf);
+ llvm::yaml::Output Yout(OS);
Symbol Sym = S; // copy: Yout<< requires mutability.
Yout << Sym;
}
return Buf;
}
-std::string toYAML(const std::pair<SymbolID, ArrayRef<Ref>> &Data) {
+std::string toYAML(const std::pair<SymbolID, llvm::ArrayRef<Ref>> &Data) {
RefBundle Refs = {Data.first, Data.second};
std::string Buf;
{
- raw_string_ostream OS(Buf);
- yaml::Output Yout(OS);
+ llvm::raw_string_ostream OS(Buf);
+ llvm::yaml::Output Yout(OS);
Yout << Refs;
}
return Buf;
diff --git a/clangd/index/dex/Dex.cpp b/clangd/index/dex/Dex.cpp
index 8d64e1b4..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
//
//===----------------------------------------------------------------------===//
@@ -20,7 +19,6 @@
#include <algorithm>
#include <queue>
-using namespace llvm;
namespace clang {
namespace clangd {
namespace dex {
@@ -44,61 +42,22 @@ 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);
Result.emplace_back(Token::Kind::Scope, Sym.Scope);
// Skip token generation for symbols with unknown declaration location.
- if (!StringRef(Sym.CanonicalDeclaration.FileURI).empty())
+ if (!llvm::StringRef(Sym.CanonicalDeclaration.FileURI).empty())
for (const auto &ProximityURI :
generateProximityURIs(Sym.CanonicalDeclaration.FileURI))
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(ArrayRef<std::string> ProximityPaths,
- const DenseMap<Token, PostingList> &InvertedIndex,
- const Corpus &Corpus) {
- std::vector<std::unique_ptr<Iterator>> BoostingIterators;
- // Deduplicate parent URIs extracted from the ProximityPaths.
- StringSet<> ParentURIs;
- 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() {
@@ -124,7 +83,7 @@ void Dex::buildIndex() {
}
// Populate TempInvertedIndex with lists for index symbols.
- DenseMap<Token, std::vector<DocID>> TempInvertedIndex;
+ llvm::DenseMap<Token, std::vector<DocID>> TempInvertedIndex;
for (DocID SymbolRank = 0; SymbolRank < Symbols.size(); ++SymbolRank) {
const auto *Sym = Symbols[SymbolRank];
for (const auto &Token : generateSearchTokens(*Sym))
@@ -143,11 +102,62 @@ 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.
bool Dex::fuzzyFind(const FuzzyFindRequest &Req,
- function_ref<void(const Symbol &)> Callback) const {
+ llvm::function_ref<void(const Symbol &)> Callback) const {
assert(!StringRef(Req.Query).contains("::") &&
"There must be no :: in query.");
trace::Span Tracer("Dex fuzzyFind");
@@ -176,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));
@@ -190,7 +201,7 @@ bool Dex::fuzzyFind(const FuzzyFindRequest &Req,
// FIXME(kbobyrev): Tune this ratio.
if (Req.Limit)
Root = Corpus.limit(move(Root), *Req.Limit * 100);
- SPAN_ATTACH(Tracer, "query", to_string(*Root));
+ SPAN_ATTACH(Tracer, "query", llvm::to_string(*Root));
vlog("Dex query tree: {0}", *Root);
using IDAndScore = std::pair<DocID, float>;
@@ -204,7 +215,7 @@ bool Dex::fuzzyFind(const FuzzyFindRequest &Req,
for (const auto &IDAndScore : IDAndScores) {
const DocID SymbolDocID = IDAndScore.first;
const auto *Sym = Symbols[SymbolDocID];
- const Optional<float> Score = Filter.match(Sym->Name);
+ const llvm::Optional<float> Score = Filter.match(Sym->Name);
if (!Score)
continue;
// Combine Fuzzy Matching score, precomputed symbol quality and boosting
@@ -225,7 +236,7 @@ bool Dex::fuzzyFind(const FuzzyFindRequest &Req,
}
void Dex::lookup(const LookupRequest &Req,
- function_ref<void(const Symbol &)> Callback) const {
+ llvm::function_ref<void(const Symbol &)> Callback) const {
trace::Span Tracer("Dex lookup");
for (const auto &ID : Req.IDs) {
auto I = LookupTable.find(ID);
@@ -235,12 +246,17 @@ void Dex::lookup(const LookupRequest &Req,
}
void Dex::refs(const RefsRequest &Req,
- function_ref<void(const Ref &)> Callback) const {
+ llvm::function_ref<void(const Ref &)> Callback) const {
trace::Span Tracer("Dex refs");
+ uint32_t Remaining =
+ Req.Limit.getValueOr(std::numeric_limits<uint32_t>::max());
for (const auto &ID : Req.IDs)
- for (const auto &Ref : Refs.lookup(ID))
- if (static_cast<int>(Req.Filter & Ref.Kind))
+ for (const auto &Ref : Refs.lookup(ID)) {
+ if (Remaining > 0 && static_cast<int>(Req.Filter & Ref.Kind)) {
+ --Remaining;
Callback(Ref);
+ }
+ }
}
size_t Dex::estimateMemoryUsage() const {
@@ -254,13 +270,13 @@ size_t Dex::estimateMemoryUsage() const {
return Bytes + BackingDataSize;
}
-std::vector<std::string> generateProximityURIs(StringRef URIPath) {
+std::vector<std::string> generateProximityURIs(llvm::StringRef URIPath) {
std::vector<std::string> Result;
auto ParsedURI = URI::parse(URIPath);
assert(ParsedURI &&
"Non-empty argument of generateProximityURIs() should be a valid "
"URI.");
- StringRef Body = ParsedURI->body();
+ llvm::StringRef Body = ParsedURI->body();
// FIXME(kbobyrev): Currently, this is a heuristic which defines the maximum
// size of resulting vector. Some projects might want to have higher limit if
// the file hierarchy is deeper. For the generic case, it would be useful to
@@ -273,7 +289,7 @@ std::vector<std::string> generateProximityURIs(StringRef URIPath) {
while (!Body.empty() && --Limit > 0) {
// FIXME(kbobyrev): Parsing and encoding path to URIs is not necessary and
// could be optimized.
- Body = sys::path::parent_path(Body, sys::path::Style::posix);
+ Body = llvm::sys::path::parent_path(Body, llvm::sys::path::Style::posix);
URI TokenURI(ParsedURI->scheme(), ParsedURI->authority(), Body);
if (!Body.empty())
Result.emplace_back(TokenURI.toString());
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 9e62c155..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
//
//===----------------------------------------------------------------------===//
@@ -13,7 +12,6 @@
#include <cassert>
#include <numeric>
-using namespace llvm;
namespace clang {
namespace clangd {
namespace dex {
@@ -77,7 +75,7 @@ public:
}
private:
- raw_ostream &dump(raw_ostream &OS) const override {
+ llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
OS << "(& ";
auto Separator = "";
for (const auto &Child : Children) {
@@ -198,7 +196,7 @@ public:
}
private:
- raw_ostream &dump(raw_ostream &OS) const override {
+ llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
OS << "(| ";
auto Separator = "";
for (const auto &Child : Children) {
@@ -246,7 +244,9 @@ public:
size_t estimateSize() const override { return Size; }
private:
- raw_ostream &dump(raw_ostream &OS) const override { return OS << "true"; }
+ llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
+ return OS << "true";
+ }
DocID Index = 0;
/// Size of the underlying virtual PostingList.
@@ -271,7 +271,9 @@ public:
size_t estimateSize() const override { return 0; }
private:
- raw_ostream &dump(raw_ostream &OS) const override { return OS << "false"; }
+ llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
+ return OS << "false";
+ }
};
/// Boost iterator is a wrapper around its child which multiplies scores of
@@ -294,7 +296,7 @@ public:
size_t estimateSize() const override { return Child->estimateSize(); }
private:
- raw_ostream &dump(raw_ostream &OS) const override {
+ llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
return OS << "(* " << Factor << ' ' << *Child << ')';
}
@@ -334,7 +336,7 @@ public:
}
private:
- raw_ostream &dump(raw_ostream &OS) const override {
+ llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
return OS << "(LIMIT " << Limit << " " << *Child << ')';
}
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 a0c8afdf..44a668bb 100644
--- a/clangd/index/dex/PostingList.cpp
+++ b/clangd/index/dex/PostingList.cpp
@@ -1,9 +1,8 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
@@ -13,7 +12,6 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace dex {
@@ -24,7 +22,7 @@ namespace {
/// them on-the-fly when the contents of chunk are to be seen.
class ChunkIterator : public Iterator {
public:
- explicit ChunkIterator(const Token *Tok, ArrayRef<Chunk> Chunks)
+ explicit ChunkIterator(const Token *Tok, llvm::ArrayRef<Chunk> Chunks)
: Tok(Tok), Chunks(Chunks), CurrentChunk(Chunks.begin()) {
if (!Chunks.empty()) {
DecompressedChunk = CurrentChunk->decompress();
@@ -71,7 +69,7 @@ public:
}
private:
- raw_ostream &dump(raw_ostream &OS) const override {
+ llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
if (Tok != nullptr)
return OS << *Tok;
OS << '[';
@@ -113,13 +111,13 @@ private:
}
const Token *Tok;
- ArrayRef<Chunk> Chunks;
+ llvm::ArrayRef<Chunk> Chunks;
/// Iterator over chunks.
/// If CurrentChunk is valid, then DecompressedChunk is
/// CurrentChunk->decompress() and CurrentID is a valid (non-end) iterator
/// into it.
decltype(Chunks)::const_iterator CurrentChunk;
- SmallVector<DocID, Chunk::PayloadSize + 1> DecompressedChunk;
+ llvm::SmallVector<DocID, Chunk::PayloadSize + 1> DecompressedChunk;
/// Iterator over DecompressedChunk.
decltype(DecompressedChunk)::iterator CurrentID;
@@ -130,11 +128,11 @@ static constexpr size_t BitsPerEncodingByte = 7;
/// Writes a variable length DocID into the buffer and updates the buffer size.
/// If it doesn't fit, returns false and doesn't write to the buffer.
-bool encodeVByte(DocID Delta, MutableArrayRef<uint8_t> &Payload) {
+bool encodeVByte(DocID Delta, llvm::MutableArrayRef<uint8_t> &Payload) {
assert(Delta != 0 && "0 is not a valid PostingList delta.");
// Calculate number of bytes Delta encoding would take by examining the
// meaningful bits.
- unsigned Width = 1 + findLastSet(Delta) / BitsPerEncodingByte;
+ unsigned Width = 1 + llvm::findLastSet(Delta) / BitsPerEncodingByte;
if (Width > Payload.size())
return false;
@@ -166,12 +164,12 @@ bool encodeVByte(DocID Delta, MutableArrayRef<uint8_t> &Payload) {
/// DocIDs 42 47 7000
/// gaps 5 6958
/// Encoding (raw number) 00000101 10110110 00101110
-std::vector<Chunk> encodeStream(ArrayRef<DocID> Documents) {
+std::vector<Chunk> encodeStream(llvm::ArrayRef<DocID> Documents) {
assert(!Documents.empty() && "Can't encode empty sequence.");
std::vector<Chunk> Result;
Result.emplace_back();
DocID Last = Result.back().Head = Documents.front();
- MutableArrayRef<uint8_t> RemainingPayload = Result.back().Payload;
+ llvm::MutableArrayRef<uint8_t> RemainingPayload = Result.back().Payload;
for (DocID Doc : Documents.drop_front()) {
if (!encodeVByte(Doc - Last, RemainingPayload)) { // didn't fit, flush chunk
Result.emplace_back();
@@ -185,7 +183,7 @@ std::vector<Chunk> encodeStream(ArrayRef<DocID> Documents) {
/// Reads variable length DocID from the buffer and updates the buffer size. If
/// the stream is terminated, return None.
-Optional<DocID> readVByte(ArrayRef<uint8_t> &Bytes) {
+llvm::Optional<DocID> readVByte(llvm::ArrayRef<uint8_t> &Bytes) {
if (Bytes.front() == 0 || Bytes.empty())
return None;
DocID Result = 0;
@@ -203,9 +201,9 @@ Optional<DocID> readVByte(ArrayRef<uint8_t> &Bytes) {
} // namespace
-SmallVector<DocID, Chunk::PayloadSize + 1> Chunk::decompress() const {
- SmallVector<DocID, Chunk::PayloadSize + 1> Result{Head};
- ArrayRef<uint8_t> Bytes(Payload);
+llvm::SmallVector<DocID, Chunk::PayloadSize + 1> Chunk::decompress() const {
+ llvm::SmallVector<DocID, Chunk::PayloadSize + 1> Result{Head};
+ llvm::ArrayRef<uint8_t> Bytes(Payload);
DocID Delta;
for (DocID Current = Head; !Bytes.empty(); Current += Delta) {
auto MaybeDelta = readVByte(Bytes);
@@ -214,10 +212,10 @@ SmallVector<DocID, Chunk::PayloadSize + 1> Chunk::decompress() const {
Delta = *MaybeDelta;
Result.push_back(Current + Delta);
}
- return SmallVector<DocID, Chunk::PayloadSize + 1>{Result};
+ return llvm::SmallVector<DocID, Chunk::PayloadSize + 1>{Result};
}
-PostingList::PostingList(ArrayRef<DocID> Documents)
+PostingList::PostingList(llvm::ArrayRef<DocID> Documents)
: Chunks(encodeStream(Documents)) {}
std::unique_ptr<Iterator> PostingList::iterator(const Token *Tok) const {
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 7779e8b8..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
//
//===----------------------------------------------------------------------===//
@@ -17,16 +16,15 @@
#include <queue>
#include <string>
-using namespace llvm;
namespace clang {
namespace clangd {
namespace dex {
-std::vector<Token> generateIdentifierTrigrams(StringRef Identifier) {
+std::vector<Token> generateIdentifierTrigrams(llvm::StringRef Identifier) {
// Apply fuzzy matching text segmentation.
std::vector<CharRole> Roles(Identifier.size());
calculateRoles(Identifier,
- makeMutableArrayRef(Roles.data(), Identifier.size()));
+ llvm::makeMutableArrayRef(Roles.data(), Identifier.size()));
std::string LowercaseIdentifier = Identifier.lower();
@@ -48,7 +46,7 @@ std::vector<Token> generateIdentifierTrigrams(StringRef Identifier) {
}
}
- DenseSet<Token> UniqueTrigrams;
+ llvm::DenseSet<Token> UniqueTrigrams;
auto Add = [&](std::string Chars) {
UniqueTrigrams.insert(Token(Token::Kind::Trigram, Chars));
@@ -85,7 +83,7 @@ std::vector<Token> generateIdentifierTrigrams(StringRef Identifier) {
return {UniqueTrigrams.begin(), UniqueTrigrams.end()};
}
-std::vector<Token> generateQueryTrigrams(StringRef Query) {
+std::vector<Token> generateQueryTrigrams(llvm::StringRef Query) {
if (Query.empty())
return {};
std::string LowercaseQuery = Query.lower();
@@ -94,9 +92,9 @@ std::vector<Token> generateQueryTrigrams(StringRef Query) {
// Apply fuzzy matching text segmentation.
std::vector<CharRole> Roles(Query.size());
- calculateRoles(Query, makeMutableArrayRef(Roles.data(), Query.size()));
+ calculateRoles(Query, llvm::makeMutableArrayRef(Roles.data(), Query.size()));
- DenseSet<Token> UniqueTrigrams;
+ llvm::DenseSet<Token> UniqueTrigrams;
std::string Chars;
for (unsigned I = 0; I < Query.size(); ++I) {
if (Roles[I] != Head && Roles[I] != Tail)
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 795173c7..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
//
//===----------------------------------------------------------------------===//
//
@@ -22,14 +21,13 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Signals.h"
-using namespace llvm;
-using namespace clang;
-using namespace clangd;
-
+namespace clang {
+namespace clangd {
namespace {
-cl::opt<std::string> IndexPath("index-path", cl::desc("Path to the index"),
- cl::Positional, cl::Required);
+llvm::cl::opt<std::string> IndexPath("index-path",
+ llvm::cl::desc("Path to the index"),
+ llvm::cl::Positional, llvm::cl::Required);
static const std::string Overview = R"(
This is an **experimental** interactive tool to process user-provided search
@@ -40,16 +38,16 @@ and manually construct non-trivial test cases.
Type use "help" request to get information about the details.
)";
-void reportTime(StringRef Name, function_ref<void()> F) {
+void reportTime(llvm::StringRef Name, llvm::function_ref<void()> F) {
const auto TimerStart = std::chrono::high_resolution_clock::now();
F();
const auto TimerStop = std::chrono::high_resolution_clock::now();
const auto Duration = std::chrono::duration_cast<std::chrono::milliseconds>(
TimerStop - TimerStart);
- outs() << formatv("{0} took {1:ms+n}.\n", Name, Duration);
+ llvm::outs() << llvm::formatv("{0} took {1:ms+n}.\n", Name, Duration);
}
-std::vector<SymbolID> getSymbolIDsFromIndex(StringRef QualifiedName,
+std::vector<SymbolID> getSymbolIDsFromIndex(llvm::StringRef QualifiedName,
const SymbolIndex *Index) {
FuzzyFindRequest Request;
// Remove leading "::" qualifier as FuzzyFind doesn't need leading "::"
@@ -77,9 +75,9 @@ std::vector<SymbolID> getSymbolIDsFromIndex(StringRef QualifiedName,
// Creating a Command populates parser options, parseAndRun() resets them.
class Command {
// By resetting the parser options, we lost the standard -help flag.
- cl::opt<bool, false, cl::parser<bool>> Help{
- "help", cl::desc("Display available options"), cl::ValueDisallowed,
- cl::cat(cl::GeneralCategory)};
+ llvm::cl::opt<bool, false, llvm::cl::parser<bool>> Help{
+ "help", llvm::cl::desc("Display available options"),
+ llvm::cl::ValueDisallowed, llvm::cl::cat(llvm::cl::GeneralCategory)};
virtual void run() = 0;
protected:
@@ -87,24 +85,25 @@ protected:
public:
virtual ~Command() = default;
- virtual void parseAndRun(ArrayRef<const char *> Argv, const char *Overview,
- const SymbolIndex &Index) {
+ virtual void parseAndRun(llvm::ArrayRef<const char *> Argv,
+ const char *Overview, const SymbolIndex &Index) {
std::string ParseErrs;
- raw_string_ostream OS(ParseErrs);
- bool Ok =
- cl::ParseCommandLineOptions(Argv.size(), Argv.data(), Overview, &OS);
+ llvm::raw_string_ostream OS(ParseErrs);
+ bool Ok = llvm::cl::ParseCommandLineOptions(Argv.size(), Argv.data(),
+ Overview, &OS);
if (Help.getNumOccurrences() > 0) {
// Avoid printing parse errors in this case.
// (Well, in theory. A bunch get printed to llvm::errs() regardless!)
- cl::PrintHelpMessage();
+ llvm::cl::PrintHelpMessage();
} else {
- outs() << OS.str();
+ llvm::outs() << OS.str();
if (Ok) {
this->Index = &Index;
reportTime(Argv[0], [&] { run(); });
}
}
- cl::ResetCommandLineParser(); // must do this before opts are destroyed.
+ llvm::cl::ResetCommandLineParser(); // must do this before opts are
+ // destroyed.
}
};
@@ -118,20 +117,20 @@ public:
// * print out tokens with least dense posting lists
class FuzzyFind : public Command {
- cl::opt<std::string> Query{
+ llvm::cl::opt<std::string> Query{
"query",
- cl::Positional,
- cl::Required,
- cl::desc("Query string to be fuzzy-matched"),
+ llvm::cl::Positional,
+ llvm::cl::Required,
+ llvm::cl::desc("Query string to be fuzzy-matched"),
};
- cl::opt<std::string> Scopes{
+ llvm::cl::opt<std::string> Scopes{
"scopes",
- cl::desc("Allowed symbol scopes (comma-separated list)"),
+ llvm::cl::desc("Allowed symbol scopes (comma-separated list)"),
};
- cl::opt<unsigned> Limit{
+ llvm::cl::opt<unsigned> Limit{
"limit",
- cl::init(10),
- cl::desc("Max results to display"),
+ llvm::cl::init(10),
+ llvm::cl::desc("Max results to display"),
};
void run() override {
@@ -139,42 +138,45 @@ class FuzzyFind : public Command {
Request.Limit = Limit;
Request.Query = Query;
if (Scopes.getNumOccurrences() > 0) {
- SmallVector<StringRef, 8> Scopes;
- StringRef(this->Scopes).split(Scopes, ',');
+ llvm::SmallVector<llvm::StringRef, 8> Scopes;
+ llvm::StringRef(this->Scopes).split(Scopes, ',');
Request.Scopes = {Scopes.begin(), Scopes.end()};
}
Request.AnyScope = Request.Scopes.empty();
// FIXME(kbobyrev): Print symbol final scores to see the distribution.
static const auto OutputFormat = "{0,-4} | {1,-40} | {2,-25}\n";
- outs() << formatv(OutputFormat, "Rank", "Symbol ID", "Symbol Name");
+ llvm::outs() << llvm::formatv(OutputFormat, "Rank", "Symbol ID",
+ "Symbol Name");
size_t Rank = 0;
Index->fuzzyFind(Request, [&](const Symbol &Sym) {
- outs() << formatv(OutputFormat, Rank++, Sym.ID.str(),
- Sym.Scope + Sym.Name);
+ llvm::outs() << llvm::formatv(OutputFormat, Rank++, Sym.ID.str(),
+ Sym.Scope + Sym.Name);
});
}
};
class Lookup : public Command {
- cl::opt<std::string> ID{
+ llvm::cl::opt<std::string> ID{
"id",
- cl::Positional,
- cl::desc("Symbol ID to look up (hex)"),
+ llvm::cl::Positional,
+ llvm::cl::desc("Symbol ID to look up (hex)"),
};
- cl::opt<std::string> Name{
- "name", cl::desc("Qualified name to look up."),
+ llvm::cl::opt<std::string> Name{
+ "name",
+ llvm::cl::desc("Qualified name to look up."),
};
void run() override {
if (ID.getNumOccurrences() == 0 && Name.getNumOccurrences() == 0) {
- outs() << "Missing required argument: please provide id or -name.\n";
+ llvm::outs()
+ << "Missing required argument: please provide id or -name.\n";
return;
}
std::vector<SymbolID> IDs;
if (ID.getNumOccurrences()) {
auto SID = SymbolID::fromStr(ID);
if (!SID) {
- outs() << toString(SID.takeError()) << "\n";
+ llvm::outs() << llvm::toString(SID.takeError()) << "\n";
return;
}
IDs.push_back(*SID);
@@ -187,60 +189,65 @@ class Lookup : public Command {
bool FoundSymbol = false;
Index->lookup(Request, [&](const Symbol &Sym) {
FoundSymbol = true;
- outs() << toYAML(Sym);
+ llvm::outs() << toYAML(Sym);
});
if (!FoundSymbol)
- outs() << "not found\n";
+ llvm::outs() << "not found\n";
}
};
class Refs : public Command {
- cl::opt<std::string> ID{
- "id", cl::Positional,
- cl::desc("Symbol ID of the symbol being queried (hex)."),
+ llvm::cl::opt<std::string> ID{
+ "id",
+ llvm::cl::Positional,
+ llvm::cl::desc("Symbol ID of the symbol being queried (hex)."),
};
- cl::opt<std::string> Name{
- "name", cl::desc("Qualified name of the symbol being queried."),
+ llvm::cl::opt<std::string> Name{
+ "name",
+ llvm::cl::desc("Qualified name of the symbol being queried."),
};
- cl::opt<std::string> Filter{
- "filter", cl::init(".*"),
- cl::desc(
+ llvm::cl::opt<std::string> Filter{
+ "filter",
+ llvm::cl::init(".*"),
+ llvm::cl::desc(
"Print all results from files matching this regular expression."),
};
void run() override {
if (ID.getNumOccurrences() == 0 && Name.getNumOccurrences() == 0) {
- outs() << "Missing required argument: please provide id or -name.\n";
+ llvm::outs()
+ << "Missing required argument: please provide id or -name.\n";
return;
}
std::vector<SymbolID> IDs;
if (ID.getNumOccurrences()) {
auto SID = SymbolID::fromStr(ID);
if (!SID) {
- outs() << toString(SID.takeError()) << "\n";
+ llvm::outs() << llvm::toString(SID.takeError()) << "\n";
return;
}
IDs.push_back(*SID);
} else {
IDs = getSymbolIDsFromIndex(Name, Index);
if (IDs.size() > 1) {
- outs() << formatv("The name {0} is ambiguous, found {1} different "
- "symbols. Please use id flag to disambiguate.\n",
- Name, IDs.size());
+ llvm::outs() << llvm::formatv(
+ "The name {0} is ambiguous, found {1} different "
+ "symbols. Please use id flag to disambiguate.\n",
+ Name, IDs.size());
return;
}
}
RefsRequest RefRequest;
RefRequest.IDs.insert(IDs.begin(), IDs.end());
- Regex RegexFilter(Filter);
+ llvm::Regex RegexFilter(Filter);
Index->refs(RefRequest, [&RegexFilter](const Ref &R) {
auto U = URI::parse(R.Location.FileURI);
if (!U) {
- outs() << U.takeError();
+ llvm::outs() << U.takeError();
return;
}
if (RegexFilter.match(U->body()))
- outs() << R << "\n";
+ llvm::outs() << R << "\n";
});
}
};
@@ -257,16 +264,20 @@ struct {
llvm::make_unique<Refs>},
};
-std::unique_ptr<SymbolIndex> openIndex(StringRef Index) {
+std::unique_ptr<SymbolIndex> openIndex(llvm::StringRef Index) {
return loadIndex(Index, /*UseDex=*/true);
}
} // namespace
+} // namespace clangd
+} // namespace clang
int main(int argc, const char *argv[]) {
- cl::ParseCommandLineOptions(argc, argv, Overview);
- cl::ResetCommandLineParser(); // We reuse it for REPL commands.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
+ using namespace clang::clangd;
+
+ llvm::cl::ParseCommandLineOptions(argc, argv, Overview);
+ llvm::cl::ResetCommandLineParser(); // We reuse it for REPL commands.
+ llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
std::unique_ptr<SymbolIndex> Index;
reportTime("Dex build", [&]() {
@@ -274,28 +285,29 @@ int main(int argc, const char *argv[]) {
});
if (!Index) {
- outs() << "Failed to open the index.\n";
+ llvm::outs() << "Failed to open the index.\n";
return -1;
}
- LineEditor LE("dexp");
+ llvm::LineEditor LE("dexp");
- while (Optional<std::string> Request = LE.readLine()) {
+ while (llvm::Optional<std::string> Request = LE.readLine()) {
// Split on spaces and add required null-termination.
std::replace(Request->begin(), Request->end(), ' ', '\0');
- SmallVector<StringRef, 8> Args;
- StringRef(*Request).split(Args, '\0', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ llvm::SmallVector<llvm::StringRef, 8> Args;
+ llvm::StringRef(*Request).split(Args, '\0', /*MaxSplit=*/-1,
+ /*KeepEmpty=*/false);
if (Args.empty())
continue;
if (Args.front() == "help") {
- outs() << "dexp - Index explorer\nCommands:\n";
+ llvm::outs() << "dexp - Index explorer\nCommands:\n";
for (const auto &C : CommandInfo)
- outs() << formatv("{0,16} - {1}\n", C.Name, C.Description);
- outs() << "Get detailed command help with e.g. `find -help`.\n";
+ llvm::outs() << llvm::formatv("{0,16} - {1}\n", C.Name, C.Description);
+ llvm::outs() << "Get detailed command help with e.g. `find -help`.\n";
continue;
}
- SmallVector<const char *, 8> FakeArgv;
- for (StringRef S : Args)
+ llvm::SmallVector<const char *, 8> FakeArgv;
+ for (llvm::StringRef S : Args)
FakeArgv.push_back(S.data()); // Terminated by separator or end of string.
bool Recognized = false;
@@ -307,7 +319,7 @@ int main(int argc, const char *argv[]) {
}
}
if (!Recognized)
- outs() << "Unknown command. Try 'help'.\n";
+ llvm::outs() << "Unknown command. Try 'help'.\n";
}
return 0;
diff --git a/clangd/indexer/IndexerMain.cpp b/clangd/indexer/IndexerMain.cpp
index 46716a95..1621e8f9 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
//
//===----------------------------------------------------------------------===//
//
@@ -22,20 +21,17 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Signals.h"
-using namespace llvm;
-using namespace clang::tooling;
-
namespace clang {
namespace clangd {
namespace {
-static cl::opt<IndexFileFormat>
- Format("format", cl::desc("Format of the index to be written"),
- cl::values(clEnumValN(IndexFileFormat::YAML, "yaml",
- "human-readable YAML format"),
- clEnumValN(IndexFileFormat::RIFF, "binary",
- "binary RIFF format")),
- cl::init(IndexFileFormat::RIFF));
+static llvm::cl::opt<IndexFileFormat>
+ Format("format", llvm::cl::desc("Format of the index to be written"),
+ llvm::cl::values(clEnumValN(IndexFileFormat::YAML, "yaml",
+ "human-readable YAML format"),
+ clEnumValN(IndexFileFormat::RIFF, "binary",
+ "binary RIFF format")),
+ llvm::cl::init(IndexFileFormat::RIFF));
class IndexActionFactory : public tooling::FrontendActionFactory {
public:
@@ -86,7 +82,7 @@ private:
} // namespace clang
int main(int argc, const char **argv) {
- sys::PrintStackTraceOnErrorSignal(argv[0]);
+ llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
const char *Overview = R"(
Creates an index of symbol information etc in a whole project.
@@ -103,10 +99,10 @@ int main(int argc, const char **argv) {
)";
auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
- argc, argv, cl::GeneralCategory, Overview);
+ argc, argv, llvm::cl::GeneralCategory, Overview);
if (!Executor) {
- errs() << toString(Executor.takeError()) << "\n";
+ llvm::errs() << llvm::toString(Executor.takeError()) << "\n";
return 1;
}
@@ -115,12 +111,12 @@ int main(int argc, const char **argv) {
auto Err = Executor->get()->execute(
llvm::make_unique<clang::clangd::IndexActionFactory>(Data));
if (Err) {
- errs() << toString(std::move(Err)) << "\n";
+ llvm::errs() << llvm::toString(std::move(Err)) << "\n";
}
// Emit collected data.
clang::clangd::IndexFileOut Out(Data);
Out.Format = clang::clangd::Format;
- outs() << Out;
+ llvm::outs() << Out;
return 0;
}
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..6aeb5efd
--- /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 linker does not remove global
+# constructors that register individual tweaks in a global registry.
+# To enable these tweaks in exectubales 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/tool/CMakeLists.txt b/clangd/tool/CMakeLists.txt
index c1887617..93d7f145 100644
--- a/clangd/tool/CMakeLists.txt
+++ b/clangd/tool/CMakeLists.txt
@@ -1,20 +1,30 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
+include_directories(${CMAKE_CURRENT_BINARY_DIR}/..)
add_clang_tool(clangd
ClangdMain.cpp
+ $<TARGET_OBJECTS:obj.clangDaemonTweaks>
)
set(LLVM_LINK_COMPONENTS
support
)
+set(CLANGD_XPC_LIBS "")
+if(CLANGD_BUILD_XPC)
+ list(APPEND CLANGD_XPC_LIBS "clangdXpcJsonConversions" "clangdXpcTransport")
+endif()
+
target_link_libraries(clangd
PRIVATE
+ clangAST
clangBasic
+ clangTidy
clangDaemon
clangFormat
clangFrontend
clangSema
clangTooling
clangToolingCore
+ ${CLANGD_XPC_LIBS}
)
diff --git a/clangd/tool/ClangdMain.cpp b/clangd/tool/ClangdMain.cpp
index 3d94401f..9495869b 100644
--- a/clangd/tool/ClangdMain.cpp
+++ b/clangd/tool/ClangdMain.cpp
@@ -1,12 +1,12 @@
//===--- 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 "Path.h"
#include "Trace.h"
@@ -25,176 +25,199 @@
#include <string>
#include <thread>
-using namespace llvm;
-using namespace clang;
-using namespace clang::clangd;
-
+namespace clang {
+namespace clangd {
// FIXME: remove this option when Dex is cheap enough.
-static cl::opt<bool> UseDex("use-dex-index",
- cl::desc("Use experimental Dex dynamic index."),
- cl::init(false), cl::Hidden);
+static llvm::cl::opt<bool>
+ UseDex("use-dex-index",
+ llvm::cl::desc("Use experimental Dex dynamic index."),
+ llvm::cl::init(true), llvm::cl::Hidden);
-static cl::opt<Path> CompileCommandsDir(
+static llvm::cl::opt<Path> CompileCommandsDir(
"compile-commands-dir",
- cl::desc("Specify a path to look for compile_commands.json. If path "
- "is invalid, clangd will look in the current directory and "
- "parent paths of each source file."));
+ llvm::cl::desc("Specify a path to look for compile_commands.json. If path "
+ "is invalid, clangd will look in the current directory and "
+ "parent paths of each source file."));
-static cl::opt<unsigned>
- WorkerThreadsCount("j", cl::desc("Number of async workers used by clangd"),
- cl::init(getDefaultAsyncThreadsCount()));
+static llvm::cl::opt<unsigned>
+ WorkerThreadsCount("j",
+ llvm::cl::desc("Number of async workers used by clangd"),
+ llvm::cl::init(getDefaultAsyncThreadsCount()));
// FIXME: also support "plain" style where signatures are always omitted.
enum CompletionStyleFlag { Detailed, Bundled };
-static cl::opt<CompletionStyleFlag> CompletionStyle(
- "completion-style", cl::desc("Granularity of code completion suggestions"),
- cl::values(
+static llvm::cl::opt<CompletionStyleFlag> CompletionStyle(
+ "completion-style",
+ llvm::cl::desc("Granularity of code completion suggestions"),
+ llvm::cl::values(
clEnumValN(Detailed, "detailed",
"One completion item for each semantically distinct "
"completion, with full type information."),
clEnumValN(Bundled, "bundled",
"Similar completion items (e.g. function overloads) are "
"combined. Type information shown where possible.")),
- cl::init(Detailed));
+ llvm::cl::init(Detailed));
// FIXME: Flags are the wrong mechanism for user preferences.
// We should probably read a dotfile or similar.
-static cl::opt<bool> IncludeIneligibleResults(
+static llvm::cl::opt<bool> IncludeIneligibleResults(
"include-ineligible-results",
- cl::desc("Include ineligible completion results (e.g. private members)"),
- cl::init(clangd::CodeCompleteOptions().IncludeIneligibleResults),
- cl::Hidden);
-
-static cl::opt<JSONStreamStyle> InputStyle(
- "input-style", cl::desc("Input JSON stream encoding"),
- cl::values(
+ llvm::cl::desc(
+ "Include ineligible completion results (e.g. private members)"),
+ llvm::cl::init(CodeCompleteOptions().IncludeIneligibleResults),
+ llvm::cl::Hidden);
+
+static llvm::cl::opt<JSONStreamStyle> InputStyle(
+ "input-style", llvm::cl::desc("Input JSON stream encoding"),
+ llvm::cl::values(
clEnumValN(JSONStreamStyle::Standard, "standard", "usual LSP protocol"),
clEnumValN(JSONStreamStyle::Delimited, "delimited",
"messages delimited by --- lines, with # comment support")),
- cl::init(JSONStreamStyle::Standard));
+ llvm::cl::init(JSONStreamStyle::Standard));
-static cl::opt<bool> PrettyPrint("pretty", cl::desc("Pretty-print JSON output"),
- cl::init(false));
+static llvm::cl::opt<bool>
+ PrettyPrint("pretty", llvm::cl::desc("Pretty-print JSON output"),
+ llvm::cl::init(false));
-static cl::opt<Logger::Level> LogLevel(
- "log", cl::desc("Verbosity of log messages written to stderr"),
- cl::values(clEnumValN(Logger::Error, "error", "Error messages only"),
- clEnumValN(Logger::Info, "info", "High level execution tracing"),
- clEnumValN(Logger::Debug, "verbose", "Low level details")),
- cl::init(Logger::Info));
+static llvm::cl::opt<Logger::Level> LogLevel(
+ "log", llvm::cl::desc("Verbosity of log messages written to stderr"),
+ llvm::cl::values(clEnumValN(Logger::Error, "error", "Error messages only"),
+ clEnumValN(Logger::Info, "info",
+ "High level execution tracing"),
+ clEnumValN(Logger::Debug, "verbose", "Low level details")),
+ llvm::cl::init(Logger::Info));
-static cl::opt<bool>
+static llvm::cl::opt<bool>
Test("lit-test",
- cl::desc("Abbreviation for -input-style=delimited -pretty "
- "-run-synchronously -enable-test-scheme. "
- "Intended to simplify lit tests."),
- cl::init(false), cl::Hidden);
+ llvm::cl::desc("Abbreviation for -input-style=delimited -pretty "
+ "-run-synchronously -enable-test-scheme. "
+ "Intended to simplify lit tests."),
+ llvm::cl::init(false), llvm::cl::Hidden);
-static cl::opt<bool> EnableTestScheme(
+static llvm::cl::opt<bool> EnableTestScheme(
"enable-test-uri-scheme",
- cl::desc("Enable 'test:' URI scheme. Only use in lit tests."),
- cl::init(false), cl::Hidden);
+ llvm::cl::desc("Enable 'test:' URI scheme. Only use in lit tests."),
+ llvm::cl::init(false), llvm::cl::Hidden);
enum PCHStorageFlag { Disk, Memory };
-static cl::opt<PCHStorageFlag> PCHStorage(
+static llvm::cl::opt<PCHStorageFlag> PCHStorage(
"pch-storage",
- cl::desc("Storing PCHs in memory increases memory usages, but may "
- "improve performance"),
- cl::values(clEnumValN(PCHStorageFlag::Disk, "disk", "store PCHs on disk"),
- clEnumValN(PCHStorageFlag::Memory, "memory",
- "store PCHs in memory")),
- cl::init(PCHStorageFlag::Disk));
-
-static cl::opt<int>
- LimitResults("limit-results",
- cl::desc("Limit the number of results returned by clangd. "
- "0 means no limit."),
- cl::init(100));
-
-static cl::opt<bool>
- RunSynchronously("run-synchronously",
- cl::desc("Parse on main thread. If set, -j is ignored"),
- cl::init(false), cl::Hidden);
-
-static cl::opt<Path> ResourceDir("resource-dir",
- cl::desc("Directory for system clang headers"),
- cl::init(""), cl::Hidden);
-
-static cl::opt<Path> InputMirrorFile(
+ llvm::cl::desc("Storing PCHs in memory increases memory usages, but may "
+ "improve performance"),
+ llvm::cl::values(
+ clEnumValN(PCHStorageFlag::Disk, "disk", "store PCHs on disk"),
+ clEnumValN(PCHStorageFlag::Memory, "memory", "store PCHs in memory")),
+ llvm::cl::init(PCHStorageFlag::Disk));
+
+static llvm::cl::opt<int> LimitResults(
+ "limit-results",
+ llvm::cl::desc("Limit the number of results returned by clangd. "
+ "0 means no limit."),
+ llvm::cl::init(100));
+
+static llvm::cl::opt<bool> RunSynchronously(
+ "run-synchronously",
+ llvm::cl::desc("Parse on main thread. If set, -j is ignored"),
+ llvm::cl::init(false), llvm::cl::Hidden);
+
+static llvm::cl::opt<Path>
+ ResourceDir("resource-dir",
+ llvm::cl::desc("Directory for system clang headers"),
+ llvm::cl::init(""), llvm::cl::Hidden);
+
+static llvm::cl::opt<Path> InputMirrorFile(
"input-mirror-file",
- cl::desc(
+ llvm::cl::desc(
"Mirror all LSP input to the specified file. Useful for debugging."),
- cl::init(""), cl::Hidden);
+ llvm::cl::init(""), llvm::cl::Hidden);
-static cl::opt<bool> EnableIndex(
+static llvm::cl::opt<bool> EnableIndex(
"index",
- cl::desc(
+ llvm::cl::desc(
"Enable index-based features. By default, clangd maintains an index "
"built from symbols in opened files. Global index support needs to "
"enabled separatedly."),
- cl::init(true), cl::Hidden);
+ llvm::cl::init(true), llvm::cl::Hidden);
-static cl::opt<bool> AllScopesCompletion(
+static llvm::cl::opt<bool> AllScopesCompletion(
"all-scopes-completion",
- cl::desc(
+ llvm::cl::desc(
"If set to true, code completion will include index symbols that are "
"not defined in the scopes (e.g. "
"namespaces) visible from the code completion point. Such completions "
"can insert scope qualifiers."),
- cl::init(true));
+ llvm::cl::init(true));
-static cl::opt<bool>
- ShowOrigins("debug-origin", cl::desc("Show origins of completion items"),
- cl::init(clangd::CodeCompleteOptions().ShowOrigins),
- cl::Hidden);
+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 cl::opt<bool> HeaderInsertionDecorators(
+static llvm::cl::opt<bool> HeaderInsertionDecorators(
"header-insertion-decorators",
- cl::desc("Prepend a circular dot or space before the completion "
- "label, depending on whether "
- "an include line will be inserted or not."),
- cl::init(true));
+ llvm::cl::desc("Prepend a circular dot or space before the completion "
+ "label, depending on whether "
+ "an include line will be inserted or not."),
+ llvm::cl::init(true));
-static cl::opt<Path> IndexFile(
+static llvm::cl::opt<Path> IndexFile(
"index-file",
- cl::desc(
+ llvm::cl::desc(
"Index file to build the static index. The file must have been created "
"by a compatible clangd-index.\n"
"WARNING: This option is experimental only, and will be removed "
"eventually. Don't rely on it."),
- cl::init(""), cl::Hidden);
+ llvm::cl::init(""), llvm::cl::Hidden);
-static cl::opt<bool> EnableBackgroundIndex(
+static llvm::cl::opt<bool> EnableBackgroundIndex(
"background-index",
- cl::desc("Index project code in the background and persist index on disk. "
- "Experimental"),
- cl::init(false), cl::Hidden);
+ llvm::cl::desc(
+ "Index project code in the background and persist index on disk. "
+ "Experimental"),
+ llvm::cl::init(false), llvm::cl::Hidden);
-static cl::opt<int> BackgroundIndexRebuildPeriod(
+static llvm::cl::opt<int> BackgroundIndexRebuildPeriod(
"background-index-rebuild-period",
- cl::desc(
+ llvm::cl::desc(
"If set to non-zero, the background index rebuilds the symbol index "
"periodically every X milliseconds; otherwise, the "
"symbol index will be updated for each indexed file."),
- cl::init(5000), cl::Hidden);
+ llvm::cl::init(5000), llvm::cl::Hidden);
enum CompileArgsFrom { LSPCompileArgs, FilesystemCompileArgs };
-static cl::opt<CompileArgsFrom> CompileArgsFrom(
- "compile_args_from", cl::desc("The source of compile commands"),
- cl::values(clEnumValN(LSPCompileArgs, "lsp",
- "All compile commands come from LSP and "
- "'compile_commands.json' files are ignored"),
- clEnumValN(FilesystemCompileArgs, "filesystem",
- "All compile commands come from the "
- "'compile_commands.json' files")),
- cl::init(FilesystemCompileArgs), cl::Hidden);
-
-static cl::opt<bool> EnableFunctionArgSnippets(
+static llvm::cl::opt<CompileArgsFrom> CompileArgsFrom(
+ "compile_args_from", llvm::cl::desc("The source of compile commands"),
+ llvm::cl::values(clEnumValN(LSPCompileArgs, "lsp",
+ "All compile commands come from LSP and "
+ "'compile_commands.json' files are ignored"),
+ clEnumValN(FilesystemCompileArgs, "filesystem",
+ "All compile commands come from the "
+ "'compile_commands.json' files")),
+ llvm::cl::init(FilesystemCompileArgs), llvm::cl::Hidden);
+
+static llvm::cl::opt<bool> EnableFunctionArgSnippets(
"function-arg-placeholders",
- cl::desc("When disabled, completions contain only parentheses for "
- "function calls. When enabled, completions also contain "
- "placeholders for method parameters."),
- cl::init(clangd::CodeCompleteOptions().EnableFunctionArgSnippets));
+ llvm::cl::desc("When disabled, completions contain only parentheses for "
+ "function calls. When enabled, completions also contain "
+ "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(false));
+
+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(false));
namespace {
@@ -204,33 +227,34 @@ namespace {
/// C:\clangd-test\a.cpp on Windows and /clangd-test/a.cpp on Unix.
class TestScheme : public URIScheme {
public:
- Expected<std::string> getAbsolutePath(StringRef /*Authority*/, StringRef Body,
- StringRef /*HintPath*/) const override {
+ llvm::Expected<std::string>
+ getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body,
+ llvm::StringRef /*HintPath*/) const override {
using namespace llvm::sys;
// Still require "/" in body to mimic file scheme, as we want lengths of an
// equivalent URI in both schemes to be the same.
if (!Body.startswith("/"))
- return make_error<StringError>(
+ return llvm::make_error<llvm::StringError>(
"Expect URI body to be an absolute path starting with '/': " + Body,
- inconvertibleErrorCode());
+ llvm::inconvertibleErrorCode());
Body = Body.ltrim('/');
- SmallVector<char, 16> Path(Body.begin(), Body.end());
+ llvm::SmallVector<char, 16> Path(Body.begin(), Body.end());
path::native(Path);
- auto Err = fs::make_absolute(TestScheme::TestDir, Path);
- if (Err)
- llvm_unreachable("Failed to make absolute path in test scheme.");
+ fs::make_absolute(TestScheme::TestDir, Path);
return std::string(Path.begin(), Path.end());
}
- Expected<URI> uriFromAbsolutePath(StringRef AbsolutePath) const override {
- StringRef Body = AbsolutePath;
+ llvm::Expected<URI>
+ uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override {
+ llvm::StringRef Body = AbsolutePath;
if (!Body.consume_front(TestScheme::TestDir)) {
- return make_error<StringError>("Path " + AbsolutePath +
- " doesn't start with root " + TestDir,
- inconvertibleErrorCode());
+ return llvm::make_error<llvm::StringError>(
+ "Path " + AbsolutePath + " doesn't start with root " + TestDir,
+ llvm::inconvertibleErrorCode());
}
- return URI("test", /*Authority=*/"", sys::path::convert_to_slash(Body));
+ return URI("test", /*Authority=*/"",
+ llvm::sys::path::convert_to_slash(Body));
}
private:
@@ -243,14 +267,24 @@ const char TestScheme::TestDir[] = "C:\\clangd-test";
const char TestScheme::TestDir[] = "/clangd-test";
#endif
-}
+} // namespace
+} // namespace clangd
+} // namespace clang
+
+enum class ErrorResultCode : int {
+ NoShutdownRequest = 1,
+ CantRunAsXPCService = 2
+};
int main(int argc, char *argv[]) {
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- cl::SetVersionPrinter([](raw_ostream &OS) {
+ using namespace clang;
+ using namespace clang::clangd;
+
+ llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+ llvm::cl::SetVersionPrinter([](llvm::raw_ostream &OS) {
OS << clang::getClangToolFullVersion("clangd") << "\n";
});
- cl::ParseCommandLineOptions(
+ llvm::cl::ParseCommandLineOptions(
argc, argv,
"clangd is a language server that provides IDE-like features to editors. "
"\n\nIt should be used via an editor plugin rather than invoked "
@@ -270,26 +304,27 @@ int main(int argc, char *argv[]) {
}
if (!RunSynchronously && WorkerThreadsCount == 0) {
- errs() << "A number of worker threads cannot be 0. Did you mean to "
- "specify -run-synchronously?";
+ llvm::errs() << "A number of worker threads cannot be 0. Did you mean to "
+ "specify -run-synchronously?";
return 1;
}
if (RunSynchronously) {
if (WorkerThreadsCount.getNumOccurrences())
- errs() << "Ignoring -j because -run-synchronously is set.\n";
+ llvm::errs() << "Ignoring -j because -run-synchronously is set.\n";
WorkerThreadsCount = 0;
}
// Validate command line arguments.
- Optional<raw_fd_ostream> InputMirrorStream;
+ llvm::Optional<llvm::raw_fd_ostream> InputMirrorStream;
if (!InputMirrorFile.empty()) {
std::error_code EC;
InputMirrorStream.emplace(InputMirrorFile, /*ref*/ EC,
- sys::fs::FA_Read | sys::fs::FA_Write);
+ llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
if (EC) {
InputMirrorStream.reset();
- errs() << "Error while opening an input mirror file: " << EC.message();
+ llvm::errs() << "Error while opening an input mirror file: "
+ << EC.message();
} else {
InputMirrorStream->SetUnbuffered();
}
@@ -298,51 +333,52 @@ int main(int argc, char *argv[]) {
// Setup tracing facilities if CLANGD_TRACE is set. In practice enabling a
// trace flag in your editor's config is annoying, launching with
// `CLANGD_TRACE=trace.json vim` is easier.
- Optional<raw_fd_ostream> TraceStream;
+ llvm::Optional<llvm::raw_fd_ostream> TraceStream;
std::unique_ptr<trace::EventTracer> Tracer;
if (auto *TraceFile = getenv("CLANGD_TRACE")) {
std::error_code EC;
TraceStream.emplace(TraceFile, /*ref*/ EC,
- sys::fs::FA_Read | sys::fs::FA_Write);
+ llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
if (EC) {
TraceStream.reset();
- errs() << "Error while opening trace file " << TraceFile << ": "
- << EC.message();
+ llvm::errs() << "Error while opening trace file " << TraceFile << ": "
+ << EC.message();
} else {
Tracer = trace::createJSONTracer(*TraceStream, PrettyPrint);
}
}
- Optional<trace::Session> TracingSession;
+ llvm::Optional<trace::Session> TracingSession;
if (Tracer)
TracingSession.emplace(*Tracer);
// Use buffered stream to stderr (we still flush each log message). Unbuffered
// stream can cause significant (non-deterministic) latency for the logger.
- errs().SetBuffered();
- StreamLogger Logger(errs(), LogLevel);
- clangd::LoggingSession LoggingSession(Logger);
+ llvm::errs().SetBuffered();
+ StreamLogger Logger(llvm::errs(), LogLevel);
+ LoggingSession LoggingSession(Logger);
// If --compile-commands-dir arg was invoked, check value and override default
// path.
- Optional<Path> CompileCommandsDirPath;
+ llvm::Optional<Path> CompileCommandsDirPath;
if (!CompileCommandsDir.empty()) {
- if (sys::fs::exists(CompileCommandsDir)) {
+ if (llvm::sys::fs::exists(CompileCommandsDir)) {
// We support passing both relative and absolute paths to the
// --compile-commands-dir argument, but we assume the path is absolute in
// the rest of clangd so we make sure the path is absolute before
// continuing.
- SmallString<128> Path(CompileCommandsDir);
- if (std::error_code EC = sys::fs::make_absolute(Path)) {
- errs() << "Error while converting the relative path specified by "
- "--compile-commands-dir to an absolute path: "
- << EC.message() << ". The argument will be ignored.\n";
+ llvm::SmallString<128> Path(CompileCommandsDir);
+ if (std::error_code EC = llvm::sys::fs::make_absolute(Path)) {
+ llvm::errs() << "Error while converting the relative path specified by "
+ "--compile-commands-dir to an absolute path: "
+ << EC.message() << ". The argument will be ignored.\n";
} else {
CompileCommandsDirPath = Path.str();
}
} else {
- errs() << "Path specified by --compile-commands-dir does not exist. The "
- "argument will be ignored.\n";
+ llvm::errs()
+ << "Path specified by --compile-commands-dir does not exist. The "
+ "argument will be ignored.\n";
}
}
@@ -390,17 +426,42 @@ int main(int argc, char *argv[]) {
CCOpts.EnableFunctionArgSnippets = EnableFunctionArgSnippets;
CCOpts.AllScopes = AllScopesCompletion;
+ RealFileSystemProvider FSProvider;
// Initialize and run ClangdLSPServer.
// Change stdin to binary to not lose \r\n on windows.
- sys::ChangeStdinToBinary();
- auto Transport = newJSONTransport(
- stdin, outs(),
- InputMirrorStream ? InputMirrorStream.getPointer() : nullptr, PrettyPrint,
- InputStyle);
+ llvm::sys::ChangeStdinToBinary();
+
+ std::unique_ptr<Transport> TransportLayer;
+ if (getenv("CLANGD_AS_XPC_SERVICE")) {
+#if CLANGD_BUILD_XPC
+ TransportLayer = newXPCTransport();
+#else
+ llvm::errs() << "This clangd binary wasn't built with XPC support.\n";
+ return (int)ErrorResultCode::CantRunAsXPCService;
+#endif
+ } else {
+ TransportLayer = newJSONTransport(
+ stdin, llvm::outs(),
+ InputMirrorStream ? InputMirrorStream.getPointer() : nullptr,
+ 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;
ClangdLSPServer LSPServer(
- *Transport, CCOpts, CompileCommandsDirPath,
+ *TransportLayer, FSProvider, CCOpts, CompileCommandsDirPath,
/*UseDirBasedCDB=*/CompileArgsFrom == FilesystemCompileArgs, Opts);
- constexpr int NoShutdownRequestErrorCode = 1;
- set_thread_name("clangd.main");
- return LSPServer.run() ? 0 : NoShutdownRequestErrorCode;
+ llvm::set_thread_name("clangd.main");
+ return LSPServer.run() ? 0
+ : static_cast<int>(ErrorResultCode::NoShutdownRequest);
}
diff --git a/clangd/xpc/CMakeLists.txt b/clangd/xpc/CMakeLists.txt
new file mode 100644
index 00000000..788a66f5
--- /dev/null
+++ b/clangd/xpc/CMakeLists.txt
@@ -0,0 +1,29 @@
+set(CLANGD_XPC_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+set(CLANGD_XPC_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
+
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
+include(CreateClangdXPCFramework)
+
+add_subdirectory(framework)
+add_subdirectory(test-client)
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}/../
+)
+
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+# Needed by LLVM's CMake checks because this file defines multiple targets.
+set(LLVM_OPTIONAL_SOURCES Conversion.cpp XPCTransport.cpp)
+
+add_clang_library(clangdXpcJsonConversions
+ Conversion.cpp
+ )
+
+add_clang_library(clangdXpcTransport
+ XPCTransport.cpp
+ DEPENDS clangdXpcJsonConversions
+ LINK_LIBS clangdXpcJsonConversions
+ )
diff --git a/clangd/xpc/Conversion.cpp b/clangd/xpc/Conversion.cpp
new file mode 100644
index 00000000..3e8d36b7
--- /dev/null
+++ b/clangd/xpc/Conversion.cpp
@@ -0,0 +1,39 @@
+//===--- Conversion.cpp - LSP data (de-)serialization through XPC - 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 "Logger.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include <string>
+#include <vector>
+
+using namespace llvm;
+namespace clang {
+namespace clangd {
+
+xpc_object_t jsonToXpc(const json::Value &JSON) {
+ const char *const Key = "LSP";
+ xpc_object_t PayloadObj = xpc_string_create(llvm::to_string(JSON).c_str());
+ return xpc_dictionary_create(&Key, &PayloadObj, 1);
+}
+
+json::Value xpcToJson(const xpc_object_t &XPCObject) {
+ if (xpc_get_type(XPCObject) == XPC_TYPE_DICTIONARY) {
+ const char *const LSP = xpc_dictionary_get_string(XPCObject, "LSP");
+ auto Json = json::parse(llvm::StringRef(LSP));
+ if (Json)
+ return *Json;
+ else
+ elog("JSON parse error: {0}", toString(Json.takeError()));
+ }
+ return json::Value(nullptr);
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/clangd/xpc/Conversion.h b/clangd/xpc/Conversion.h
new file mode 100644
index 00000000..fccc095b
--- /dev/null
+++ b/clangd/xpc/Conversion.h
@@ -0,0 +1,24 @@
+//===--- Conversion.h - LSP data (de-)serialization through XPC -*- 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_XPC_XPCJSONCONVERSIONS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_XPC_XPCJSONCONVERSIONS_H
+
+#include "llvm/Support/JSON.h"
+#include <xpc/xpc.h>
+
+namespace clang {
+namespace clangd {
+
+xpc_object_t jsonToXpc(const llvm::json::Value &JSON);
+llvm::json::Value xpcToJson(const xpc_object_t &XPCObject);
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/clangd/xpc/README.txt b/clangd/xpc/README.txt
new file mode 100644
index 00000000..70ac761c
--- /dev/null
+++ b/clangd/xpc/README.txt
@@ -0,0 +1,6 @@
+This directory contains:
+- the XPC transport layer (alternative transport layer to JSON-RPC)
+- XPC framework wrapper that wraps around Clangd to make it a valid XPC service
+- XPC test-client
+
+MacOS only. Feature is guarded by CLANGD_BUILD_XPC, including whole xpc/ dir. \ No newline at end of file
diff --git a/clangd/xpc/XPCTransport.cpp b/clangd/xpc/XPCTransport.cpp
new file mode 100644
index 00000000..f7df8a91
--- /dev/null
+++ b/clangd/xpc/XPCTransport.cpp
@@ -0,0 +1,216 @@
+//===--- XPCTransport.cpp - sending and receiving LSP messages over XPC ---===//
+//
+// Part of the LLVM Project, under the Apache 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"
+#include "Logger.h"
+#include "Protocol.h" // For LSPError
+#include "Transport.h"
+#include "llvm/Support/Errno.h"
+
+#include <xpc/xpc.h>
+
+using namespace llvm;
+using namespace clang;
+using namespace clangd;
+
+namespace {
+
+json::Object encodeError(Error E) {
+ std::string Message;
+ ErrorCode Code = ErrorCode::UnknownErrorCode;
+ if (Error Unhandled =
+ handleErrors(std::move(E), [&](const LSPError &L) -> Error {
+ Message = L.Message;
+ Code = L.Code;
+ return Error::success();
+ }))
+ Message = toString(std::move(Unhandled));
+
+ return json::Object{
+ {"message", std::move(Message)},
+ {"code", int64_t(Code)},
+ };
+}
+
+Error decodeError(const json::Object &O) {
+ std::string Msg = O.getString("message").getValueOr("Unspecified error");
+ if (auto Code = O.getInteger("code"))
+ return make_error<LSPError>(std::move(Msg), ErrorCode(*Code));
+ return make_error<StringError>(std::move(Msg), inconvertibleErrorCode());
+}
+
+// C "closure" for XPCTransport::loop() method
+namespace xpcClosure {
+void connection_handler(xpc_connection_t clientConnection);
+}
+
+class XPCTransport : public Transport {
+public:
+ XPCTransport() {}
+
+ void notify(StringRef Method, json::Value Params) override {
+ sendMessage(json::Object{
+ {"jsonrpc", "2.0"},
+ {"method", Method},
+ {"params", std::move(Params)},
+ });
+ }
+ void call(StringRef Method, json::Value Params, json::Value ID) override {
+ sendMessage(json::Object{
+ {"jsonrpc", "2.0"},
+ {"id", std::move(ID)},
+ {"method", Method},
+ {"params", std::move(Params)},
+ });
+ }
+ void reply(json::Value ID, Expected<json::Value> Result) override {
+ if (Result) {
+ sendMessage(json::Object{
+ {"jsonrpc", "2.0"},
+ {"id", std::move(ID)},
+ {"result", std::move(*Result)},
+ });
+ } else {
+ sendMessage(json::Object{
+ {"jsonrpc", "2.0"},
+ {"id", std::move(ID)},
+ {"error", encodeError(Result.takeError())},
+ });
+ }
+ }
+
+ Error loop(MessageHandler &Handler) override;
+
+private:
+ // Needs access to handleMessage() and resetClientConnection()
+ friend void xpcClosure::connection_handler(xpc_connection_t clientConnection);
+
+ // Dispatches incoming message to Handler onNotify/onCall/onReply.
+ bool handleMessage(json::Value Message, MessageHandler &Handler);
+ void sendMessage(json::Value Message) {
+ xpc_object_t response = jsonToXpc(Message);
+ xpc_connection_send_message(clientConnection, response);
+ xpc_release(response);
+ }
+ void resetClientConnection(xpc_connection_t newClientConnection) {
+ clientConnection = newClientConnection;
+ }
+ xpc_connection_t clientConnection;
+};
+
+bool XPCTransport::handleMessage(json::Value Message, MessageHandler &Handler) {
+ // Message must be an object with "jsonrpc":"2.0".
+ auto *Object = Message.getAsObject();
+ if (!Object || Object->getString("jsonrpc") != Optional<StringRef>("2.0")) {
+ elog("Not a JSON-RPC 2.0 message: {0:2}", Message);
+ return false;
+ }
+ // ID may be any JSON value. If absent, this is a notification.
+ Optional<json::Value> ID;
+ if (auto *I = Object->get("id"))
+ ID = std::move(*I);
+ auto Method = Object->getString("method");
+ if (!Method) { // This is a response.
+ if (!ID) {
+ elog("No method and no response ID: {0:2}", Message);
+ return false;
+ }
+ if (auto *Err = Object->getObject("error"))
+ return Handler.onReply(std::move(*ID), decodeError(*Err));
+ // Result should be given, use null if not.
+ json::Value Result = nullptr;
+ if (auto *R = Object->get("result"))
+ Result = std::move(*R);
+ return Handler.onReply(std::move(*ID), std::move(Result));
+ }
+ // Params should be given, use null if not.
+ json::Value Params = nullptr;
+ if (auto *P = Object->get("params"))
+ Params = std::move(*P);
+
+ if (ID)
+ return Handler.onCall(*Method, std::move(Params), std::move(*ID));
+ else
+ return Handler.onNotify(*Method, std::move(Params));
+}
+
+namespace xpcClosure {
+// "owner" of this "closure object" - necessary for propagating connection to
+// XPCTransport so it can send messages to the client.
+XPCTransport *TransportObject = nullptr;
+Transport::MessageHandler *HandlerPtr = nullptr;
+
+void connection_handler(xpc_connection_t clientConnection) {
+ xpc_connection_set_target_queue(clientConnection, dispatch_get_main_queue());
+
+ xpc_transaction_begin();
+
+ TransportObject->resetClientConnection(clientConnection);
+
+ xpc_connection_set_event_handler(clientConnection, ^(xpc_object_t message) {
+ if (message == XPC_ERROR_CONNECTION_INVALID) {
+ // connection is being terminated
+ log("Received XPC_ERROR_CONNECTION_INVALID message - returning from the "
+ "event_handler.");
+ return;
+ }
+
+ if (xpc_get_type(message) != XPC_TYPE_DICTIONARY) {
+ log("Received XPC message of unknown type - returning from the "
+ "event_handler.");
+ return;
+ }
+
+ const json::Value Doc = xpcToJson(message);
+ if (Doc == json::Value(nullptr)) {
+ log("XPC message was converted to Null JSON message - returning from the "
+ "event_handler.");
+ return;
+ }
+
+ vlog("<<< {0}\n", Doc);
+
+ if (!TransportObject->handleMessage(std::move(Doc), *HandlerPtr)) {
+ log("Received exit notification - cancelling connection.");
+ xpc_connection_cancel(xpc_dictionary_get_remote_connection(message));
+ xpc_transaction_end();
+ }
+ });
+
+ xpc_connection_resume(clientConnection);
+}
+} // namespace xpcClosure
+
+Error XPCTransport::loop(MessageHandler &Handler) {
+ assert(xpcClosure::TransportObject == nullptr &&
+ "TransportObject has already been set.");
+ // This looks scary since lifetime of this (or any) XPCTransport object has
+ // to fully contain lifetime of any XPC connection. In practise any Transport
+ // object is destroyed only at the end of main() which is always after
+ // exit of xpc_main().
+ xpcClosure::TransportObject = this;
+
+ assert(xpcClosure::HandlerPtr == nullptr &&
+ "HandlerPtr has already been set.");
+ xpcClosure::HandlerPtr = &Handler;
+
+ xpc_main(xpcClosure::connection_handler);
+ // xpc_main doesn't ever return
+ return errorCodeToError(std::make_error_code(std::errc::io_error));
+}
+
+} // namespace
+
+namespace clang {
+namespace clangd {
+
+std::unique_ptr<Transport> newXPCTransport() {
+ return llvm::make_unique<XPCTransport>();
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/clangd/xpc/cmake/Info.plist.in b/clangd/xpc/cmake/Info.plist.in
new file mode 100644
index 00000000..c5eb9fd0
--- /dev/null
+++ b/clangd/xpc/cmake/Info.plist.in
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${CLANGD_XPC_FRAMEWORK_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>org.llvm.${CLANGD_XPC_FRAMEWORK_NAME}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${CLANGD_XPC_FRAMEWORK_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string></string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+</dict>
+</plist>
diff --git a/clangd/xpc/cmake/XPCServiceInfo.plist.in b/clangd/xpc/cmake/XPCServiceInfo.plist.in
new file mode 100644
index 00000000..3c3f8dc9
--- /dev/null
+++ b/clangd/xpc/cmake/XPCServiceInfo.plist.in
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleExecutable</key>
+ <string>${CLANGD_XPC_SERVICE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>${CLANGD_XPC_SERVICE_BUNDLE_NAME}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${CLANGD_XPC_SERVICE_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>XPC!</string>
+ <key>CFBundleVersion</key>
+ <string></string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>XPCService</key>
+ <dict>
+ <key>ServiceType</key>
+ <string>Application</string>
+ <key>EnvironmentVariables</key>
+ <dict>
+ <key>CLANGD_AS_XPC_SERVICE</key>
+ <string>1</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/clangd/xpc/cmake/modules/CreateClangdXPCFramework.cmake b/clangd/xpc/cmake/modules/CreateClangdXPCFramework.cmake
new file mode 100644
index 00000000..2299bc8f
--- /dev/null
+++ b/clangd/xpc/cmake/modules/CreateClangdXPCFramework.cmake
@@ -0,0 +1,73 @@
+# Creates the ClangdXPC framework.
+macro(create_clangd_xpc_framework target name)
+ set(CLANGD_FRAMEWORK_LOCATION "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${name}.framework")
+ set(CLANGD_FRAMEWORK_OUT_LOCATION "${CLANGD_FRAMEWORK_LOCATION}/Versions/A")
+
+ # Create the framework info PLIST.
+ set(CLANGD_XPC_FRAMEWORK_NAME "${name}")
+ configure_file(
+ "${CLANGD_XPC_SOURCE_DIR}/cmake/Info.plist.in"
+ "${CLANGD_XPC_BINARY_DIR}/${name}.Info.plist")
+
+ set(CLANGD_XPC_SERVICE_NAME "clangd")
+ set(CLANGD_XPC_SERVICE_OUT_LOCATION
+ "${CLANGD_FRAMEWORK_OUT_LOCATION}/XPCServices/${CLANGD_XPC_SERVICE_NAME}.xpc/Contents")
+
+ # Create the XPC service info PLIST.
+ set(CLANGD_XPC_SERVICE_BUNDLE_NAME "org.llvm.${CLANGD_XPC_SERVICE_NAME}")
+ configure_file(
+ "${CLANGD_XPC_SOURCE_DIR}/cmake/XPCServiceInfo.plist.in"
+ "${CLANGD_XPC_BINARY_DIR}/${name}Service.Info.plist")
+
+ # Create the custom command
+ add_custom_command(OUTPUT ${CLANGD_FRAMEWORK_LOCATION}
+ # Copy the PLIST.
+ COMMAND ${CMAKE_COMMAND} -E copy
+ "${CLANGD_XPC_BINARY_DIR}/${name}.Info.plist"
+ "${CLANGD_FRAMEWORK_OUT_LOCATION}/Resources/Info.plist"
+
+ # Copy the framework binary.
+ COMMAND ${CMAKE_COMMAND} -E copy
+ "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${target}.dylib"
+ "${CLANGD_FRAMEWORK_OUT_LOCATION}/${name}"
+
+ # Copy the XPC Service PLIST.
+ COMMAND ${CMAKE_COMMAND} -E copy
+ "${CLANGD_XPC_BINARY_DIR}/${name}Service.Info.plist"
+ "${CLANGD_XPC_SERVICE_OUT_LOCATION}/Info.plist"
+
+ # Copy the Clangd binary.
+ COMMAND ${CMAKE_COMMAND} -E copy
+ "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/clangd"
+ "${CLANGD_XPC_SERVICE_OUT_LOCATION}/MacOS/clangd"
+
+ COMMAND ${CMAKE_COMMAND} -E create_symlink "A"
+ "${CLANGD_FRAMEWORK_LOCATION}/Versions/Current"
+
+ COMMAND ${CMAKE_COMMAND} -E create_symlink
+ "Versions/Current/Resources"
+ "${CLANGD_FRAMEWORK_LOCATION}/Resources"
+
+ COMMAND ${CMAKE_COMMAND} -E create_symlink
+ "Versions/Current/XPCServices"
+ "${CLANGD_FRAMEWORK_LOCATION}/XPCServices"
+
+ COMMAND ${CMAKE_COMMAND} -E create_symlink
+ "Versions/Current/${name}"
+ "${CLANGD_FRAMEWORK_LOCATION}/${name}"
+
+ DEPENDS
+ "${CLANGD_XPC_BINARY_DIR}/${name}.Info.plist"
+ "${CLANGD_XPC_BINARY_DIR}/${name}Service.Info.plist"
+ clangd
+ COMMENT "Creating ClangdXPC framework"
+ VERBATIM
+ )
+
+ add_custom_target(
+ ClangdXPC
+ DEPENDS
+ ${target}
+ ${CLANGD_FRAMEWORK_LOCATION}
+ )
+endmacro(create_clangd_xpc_framework)
diff --git a/clangd/xpc/framework/CMakeLists.txt b/clangd/xpc/framework/CMakeLists.txt
new file mode 100644
index 00000000..a20340fb
--- /dev/null
+++ b/clangd/xpc/framework/CMakeLists.txt
@@ -0,0 +1,9 @@
+
+set(SOURCES
+ ClangdXPC.cpp)
+add_clang_library(ClangdXPCLib SHARED
+ ${SOURCES}
+ DEPENDS
+ clangd
+)
+create_clangd_xpc_framework(ClangdXPCLib "ClangdXPC")
diff --git a/clangd/xpc/framework/ClangdXPC.cpp b/clangd/xpc/framework/ClangdXPC.cpp
new file mode 100644
index 00000000..6c68f5cd
--- /dev/null
+++ b/clangd/xpc/framework/ClangdXPC.cpp
@@ -0,0 +1,5 @@
+
+/// Returns the bundle identifier of the Clangd XPC service.
+extern "C" const char *clangd_xpc_get_bundle_identifier() {
+ return "org.llvm.clangd";
+}
diff --git a/clangd/xpc/test-client/CMakeLists.txt b/clangd/xpc/test-client/CMakeLists.txt
new file mode 100644
index 00000000..283599ec
--- /dev/null
+++ b/clangd/xpc/test-client/CMakeLists.txt
@@ -0,0 +1,26 @@
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../
+)
+
+add_clang_tool(
+ clangd-xpc-test-client
+ ClangdXPCTestClient.cpp
+
+ DEPENDS ClangdXPC
+)
+
+set(LLVM_LINK_COMPONENTS
+ support
+)
+
+target_link_libraries(clangd-xpc-test-client
+ PRIVATE
+ clangBasic
+ clangDaemon
+ clangFormat
+ clangFrontend
+ clangSema
+ clangTooling
+ clangToolingCore
+ clangdXpcJsonConversions
+)
diff --git a/clangd/xpc/test-client/ClangdXPCTestClient.cpp b/clangd/xpc/test-client/ClangdXPCTestClient.cpp
new file mode 100644
index 00000000..da204a69
--- /dev/null
+++ b/clangd/xpc/test-client/ClangdXPCTestClient.cpp
@@ -0,0 +1,96 @@
+#include "xpc/Conversion.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/LineIterator.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string>
+#include <xpc/xpc.h>
+
+typedef const char *(*clangd_xpc_get_bundle_identifier_t)(void);
+
+using namespace llvm;
+using namespace clang;
+
+std::string getLibraryPath() {
+ Dl_info info;
+ if (dladdr((void *)(uintptr_t)getLibraryPath, &info) == 0)
+ llvm_unreachable("Call to dladdr() failed");
+ llvm::SmallString<128> LibClangPath;
+ LibClangPath = llvm::sys::path::parent_path(
+ llvm::sys::path::parent_path(info.dli_fname));
+ llvm::sys::path::append(LibClangPath, "lib", "ClangdXPC.framework",
+ "ClangdXPC");
+ return LibClangPath.str();
+}
+
+static void dumpXPCObject(xpc_object_t Object, llvm::raw_ostream &OS) {
+ xpc_type_t Type = xpc_get_type(Object);
+ if (Type == XPC_TYPE_DICTIONARY) {
+ json::Value Json = clang::clangd::xpcToJson(Object);
+ OS << Json;
+ } else {
+ OS << "<UNKNOWN>";
+ }
+}
+
+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)
+ return 1;
+
+ // Lookup the XPC service bundle name, and launch it.
+ clangd_xpc_get_bundle_identifier_t clangd_xpc_get_bundle_identifier =
+ (clangd_xpc_get_bundle_identifier_t)dlsym(
+ dlHandle, "clangd_xpc_get_bundle_identifier");
+ xpc_connection_t conn = xpc_connection_create(
+ clangd_xpc_get_bundle_identifier(), dispatch_get_main_queue());
+
+ // Dump the XPC events.
+ xpc_connection_set_event_handler(conn, ^(xpc_object_t event) {
+ if (event == XPC_ERROR_CONNECTION_INVALID) {
+ llvm::errs() << "Received XPC_ERROR_CONNECTION_INVALID.";
+ exit(EXIT_SUCCESS);
+ }
+ if (event == XPC_ERROR_CONNECTION_INTERRUPTED) {
+ llvm::errs() << "Received XPC_ERROR_CONNECTION_INTERRUPTED.";
+ exit(EXIT_SUCCESS);
+ }
+
+ dumpXPCObject(event, llvm::outs());
+ llvm::outs() << "\n";
+ });
+
+ xpc_connection_resume(conn);
+
+ // Read the input to determine the things to send to clangd.
+ llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> Stdin =
+ llvm::MemoryBuffer::getSTDIN();
+ if (!Stdin) {
+ llvm::errs() << "Failed to get STDIN!\n";
+ return 1;
+ }
+ for (llvm::line_iterator It(**Stdin, /*SkipBlanks=*/true,
+ /*CommentMarker=*/'#');
+ !It.is_at_eof(); ++It) {
+ StringRef Line = *It;
+ if (auto Request = json::parse(Line)) {
+ xpc_object_t Object = clangd::jsonToXpc(*Request);
+ xpc_connection_send_message(conn, Object);
+ } else {
+ llvm::errs() << llvm::Twine("JSON parse error: ")
+ << llvm::toString(Request.takeError());
+ return 1;
+ }
+ }
+
+ dispatch_main();
+
+ // dispatch_main() doesn't return
+ return EXIT_FAILURE;
+}
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index 1976f788..f932af42 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,7 +57,7 @@ The improvements are...
Improvements to clang-query
---------------------------
-The improvements are...
+- ...
Improvements to clang-rename
----------------------------
@@ -67,186 +67,36 @@ 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 :doc:`abseil-faster-strsplit-delimiter
- <clang-tidy/checks/abseil-faster-strsplit-delimiter>` check.
-
- 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-no-internal-dependencies
- <clang-tidy/checks/abseil-no-internal-dependencies>` check.
-
- Gives a warning if code using Abseil depends on internal details.
-
-- New :doc:`abseil-no-namespace
- <clang-tidy/checks/abseil-no-namespace>` check.
-
- Ensures code does not open ``namespace absl`` as that violates Abseil's
- compatibility guidelines.
-
-- New :doc:`abseil-redundant-strcat-calls
- <clang-tidy/checks/abseil-redundant-strcat-calls>` check.
-
- Suggests removal of unnecessary calls to ``absl::StrCat`` when the result is
- being passed to another ``absl::StrCat`` or ``absl::StrAppend``.
-
-- New :doc:`abseil-str-cat-append
- <clang-tidy/checks/abseil-str-cat-append>` check.
-
- Flags uses of ``absl::StrCat()`` to append to a ``std::string``. Suggests
- ``absl::StrAppend()`` should be used instead.
-
-- New :doc:`abseil-upgrade-duration-conversions
- <clang-tidy/checks/abseil-upgrade-duration-conversions>` check.
-
- Finds calls to ``absl::Duration`` arithmetic operators and factories whose
- argument needs an explicit cast to continue compiling after upcoming API
- changes.
-
-- New :doc:`bugprone-too-small-loop-variable
- <clang-tidy/checks/bugprone-too-small-loop-variable>` check.
-
- 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:`cppcoreguidelines-macro-usage
- <clang-tidy/checks/cppcoreguidelines-macro-usage>` check.
-
- Finds macro usage that is considered problematic because better language
- constructs exist for the task.
-
-- New :doc:`google-objc-function-naming
- <clang-tidy/checks/google-objc-function-naming>` check.
-
- Checks that function names in function declarations comply with the naming
- conventions described in the Google Objective-C Style Guide.
-
-- New :doc:`misc-non-private-member-variables-in-classes
- <clang-tidy/checks/misc-non-private-member-variables-in-classes>` check.
-
- 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``.
-
-- New :doc:`modernize-avoid-c-arrays
- <clang-tidy/checks/modernize-avoid-c-arrays>` check.
-
- Finds C-style array types and recommend to use ``std::array<>`` /
- ``std::vector<>``.
-
-- New :doc:`modernize-concat-nested-namespaces
- <clang-tidy/checks/modernize-concat-nested-namespaces>` check.
-
- 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:`modernize-deprecated-ios-base-aliases
- <clang-tidy/checks/modernize-deprecated-ios-base-aliases>` check.
-
- Detects usage of the deprecated member types of ``std::ios_base`` and replaces
- those that have a non-deprecated equivalent.
-
-- 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-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 :doc:`abseil-duration-addition
+ <clang-tidy/checks/abseil-duration-addition>` check.
-- 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.
+ Checks for cases where addition should be performed in the ``absl::Time``
+ domain.
-- 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 :doc:`abseil-duration-conversion-cast
+ <clang-tidy/checks/abseil-duration-conversion-cast>` check.
-- 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.
+ Checks for casts of ``absl::Duration`` conversion functions, and recommends
+ the right conversion function instead.
-- 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 :doc:`abseil-duration-unnecessary-conversion
+ <clang-tidy/checks/abseil-duration-unnecessary-conversion>` check.
-- 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.
+ Finds and fixes cases where ``absl::Duration`` values are being converted to
+ numeric types and back again.
-- The :doc:`readability-redundant-smartptr-get
- <clang-tidy/checks/readability-redundant-smartptr-get>` check does not warn
- about calls inside macros anymore by default.
+- New :doc:`google-readability-avoid-underscore-in-googletest-name
+ <clang-tidy/checks/google-readability-avoid-underscore-in-googletest-name>`
+ check.
-- 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).
+ Checks whether there are underscores in googletest test and test case names in
+ test macros, which is prohibited by the Googletest FAQ.
-- The :doc:`objc-property-declaration
- <clang-tidy/checks/objc-property-declaration>` check now ignores the
- `Acronyms` and `IncludeDefaultAcronyms` options.
+- The :doc:`bugprone-argument-comment
+ <clang-tidy/checks/bugprone-argument-comment>` now supports
+ `CommentBoolLiterals`, `CommentIntegerLiterals`, `CommentFloatLiterals`,
+ `CommentUserDefiniedLiterals`, `CommentStringLiterals`,
+ `CommentCharacterLiterals` & `CommentNullPtrs` options.
Improvements to include-fixer
-----------------------------
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/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..719bed38
--- /dev/null
+++ b/docs/clang-tidy/Contributing.rst
@@ -0,0 +1,512 @@
+================
+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 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: 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 "../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
+<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-unnecessary-conversion.rst b/docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
new file mode 100644
index 00000000..938c46d5
--- /dev/null
+++ b/docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
@@ -0,0 +1,31 @@
+.. 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.
+
+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 - 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;
+
+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/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/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 e4542082..13d8f6fb 100644
--- a/docs/clang-tidy/checks/list.rst
+++ b/docs/clang-tidy/checks/list.rst
@@ -4,17 +4,20 @@ 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-string-find-startswith
abseil-str-cat-append
+ abseil-string-find-startswith
abseil-upgrade-duration-conversions
android-cloexec-accept
android-cloexec-accept4
@@ -91,8 +94,8 @@ Clang-Tidy Checks
cert-msc50-cpp
cert-msc51-cpp
cert-oop11-cpp (redirects to performance-move-constructor-init) <cert-oop11-cpp>
- cppcoreguidelines-avoid-goto
cppcoreguidelines-avoid-c-arrays (redirects to modernize-avoid-c-arrays) <cppcoreguidelines-avoid-c-arrays>
+ 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-interfaces-global-init
@@ -130,6 +133,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>
@@ -159,6 +163,7 @@ Clang-Tidy Checks
hicpp-special-member-functions (redirects to cppcoreguidelines-special-member-functions) <hicpp-special-member-functions>
hicpp-static-assert (redirects to misc-static-assert) <hicpp-static-assert>
hicpp-undelegated-constructor (redirects to bugprone-undelegated-constructor) <hicpp-undelegated-constructor>
+ hicpp-uppercase-literal-suffix (redirects to readability-uppercase-literal-suffix) <hicpp-uppercase-literal-suffix>
hicpp-use-auto (redirects to modernize-use-auto) <hicpp-use-auto>
hicpp-use-emplace (redirects to modernize-use-emplace) <hicpp-use-emplace>
hicpp-use-equals-default (redirects to modernize-use-equals-default) <hicpp-use-equals-default>
@@ -167,7 +172,6 @@ Clang-Tidy Checks
hicpp-use-nullptr (redirects to modernize-use-nullptr) <hicpp-use-nullptr>
hicpp-use-override (redirects to modernize-use-override) <hicpp-use-override>
hicpp-vararg (redirects to cppcoreguidelines-pro-type-vararg) <hicpp-vararg>
- hicpp-uppercase-literal-suffix (redirects to readability-uppercase-literal-suffix) <hicpp-uppercase-literal-suffix>
llvm-header-guard
llvm-include-order
llvm-namespace-comment
@@ -207,6 +211,7 @@ Clang-Tidy Checks
modernize-use-emplace
modernize-use-equals-default
modernize-use-equals-delete
+ modernize-use-nodiscard
modernize-use-noexcept
modernize-use-nullptr
modernize-use-override
@@ -253,6 +258,7 @@ Clang-Tidy Checks
readability-redundant-declaration
readability-redundant-function-ptr-dereference
readability-redundant-member-init
+ readability-redundant-preprocessor
readability-redundant-smartptr-get
readability-redundant-string-cstr
readability-redundant-string-init
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/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/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-nodiscard.rst b/docs/clang-tidy/checks/modernize-use-nodiscard.rst
new file mode 100644
index 00000000..3048db86
--- /dev/null
+++ b/docs/clang-tidy/checks/modernize-use-nodiscard.rst
@@ -0,0 +1,82 @@
+.. title:: clang-tidy - modernize-use-nodiscard
+
+modernize-use-nodiscard
+=======================
+
+Adds ``[[nodiscard]]`` attributes (introduced in C++17) to member functions in
+order to highlight at compile time which return values should not be ignored.
+
+Member functions need to satisfy the following conditions to be considered by
+this check:
+
+ - no ``[[nodiscard]]``, ``[[noreturn]]``,
+ ``__attribute__((warn_unused_result))``,
+ ``[[clang::warn_unused_result]]`` nor ``[[gcc::warn_unused_result]]``
+ attribute,
+ - non-void return type,
+ - non-template return types,
+ - const member function,
+ - non-variadic functions,
+ - no non-const reference parameters,
+ - no pointer parameters,
+ - no template parameters,
+ - no template function parameters,
+ - not be a member of a class with mutable member variables,
+ - no Lambdas,
+ - no conversion functions.
+
+Such functions have no means of altering any state or passing values other than
+via the return type. Unless the member functions are altering state via some
+external call (e.g. I/O).
+
+Example
+-------
+
+.. code-block:: c++
+
+ bool empty() const;
+ bool empty(int i) const;
+
+transforms to:
+
+.. code-block:: c++
+
+ [[nodiscard] bool empty() const;
+ [[nodiscard] bool empty(int i) const;
+
+Options
+-------
+
+.. option:: ReplacementString
+
+ Specifies a macro to use instead of ``[[nodiscard]]``. This is useful when
+ maintaining source code that needs to compile with a pre-C++17 compiler.
+
+Example
+^^^^^^^
+
+.. code-block:: c++
+
+ bool empty() const;
+ bool empty(int i) const;
+
+transforms to:
+
+.. code-block:: c++
+
+ NO_DISCARD bool empty() const;
+ NO_DISCARD bool empty(int i) const;
+
+if the :option:`ReplacementString` option is set to `NO_DISCARD`.
+
+.. note::
+
+ If the :option:`ReplacementString` is not a C++ attribute, but instead a
+ macro, then that macro must be defined in scope or the fix-it will not be
+ applied.
+
+.. note::
+
+ For alternative ``__attribute__`` syntax options to mark functions as
+ ``[[nodiscard]]`` in non-c++17 source code.
+ See https://clang.llvm.org/docs/AttributeReference.html#nodiscard-warn-unused-result
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-identifier-naming.rst b/docs/clang-tidy/checks/readability-identifier-naming.rst
index 30408c12..d7e88593 100644
--- a/docs/clang-tidy/checks/readability-identifier-naming.rst
+++ b/docs/clang-tidy/checks/readability-identifier-naming.rst
@@ -5,14 +5,1919 @@ readability-identifier-naming
Checks for identifiers naming style mismatch.
-This check will try to enforce coding guidelines on the identifiers naming.
-It supports `lower_case`, `UPPER_CASE`, `camelBack` and `CamelCase` casing and
-tries to convert from one to another if a mismatch is detected.
+This check will try to enforce coding guidelines on the identifiers naming. It
+supports one of the following casing types and tries to convert from one to
+another if a mismatch is detected
-It also supports a fixed prefix and suffix that will be prepended or
-appended to the identifiers, regardless of the casing.
+Casing types inclde:
+
+ - ``lower_case``,
+ - ``UPPER_CASE``,
+ - ``camelBack``,
+ - ``CamelCase``,
+ - ``camel_Snake_Back``,
+ - ``Camel_Snake_Case``,
+ - ``aNy_CasE``.
+
+It also supports a fixed prefix and suffix that will be prepended or appended
+to the identifiers, regardless of the casing.
Many configuration options are available, in order to be able to create
-different rules for different kind of identifier. In general, the
-rules are falling back to a more generic rule if the specific case is not
-configured.
+different rules for different kinds of identifiers. In general, the rules are
+falling back to a more generic rule if the specific case is not configured.
+
+Options
+-------
+
+The following options are describe below:
+
+ - :option:`AbstractClassCase`, :option:`AbstractClassPrefix`, :option:`AbstractClassSuffix`
+ - :option:`ClassCase`, :option:`ClassPrefix`, :option:`ClassSuffix`
+ - :option:`ClassConstantCase`, :option:`ClassConstantPrefix`, :option:`ClassConstantSuffix`
+ - :option:`ClassMemberCase`, :option:`ClassMemberPrefix`, :option:`ClassMemberSuffix`
+ - :option:`ClassMethodCase`, :option:`ClassMethodPrefix`, :option:`ClassMethodSuffix`
+ - :option:`ConstantCase`, :option:`ConstantPrefix`, :option:`ConstantSuffix`
+ - :option:`ConstantMemberCase`, :option:`ConstantMemberPrefix`, :option:`ConstantMemberSuffix`
+ - :option:`ConstantParameterCase`, :option:`ConstantParameterPrefix`, :option:`ConstantParameterSuffix`
+ - :option:`ConstantPointerParameterCase`, :option:`ConstantPointerParameterPrefix`, :option:`ConstantPointerParameterSuffix`
+ - :option:`ConstexprFunctionCase`, :option:`ConstexprFunctionPrefix`, :option:`ConstexprFunctionSuffix`
+ - :option:`ConstexprMethodCase`, :option:`ConstexprMethodPrefix`, :option:`ConstexprMethodSuffix`
+ - :option:`ConstexprVariableCase`, :option:`ConstexprVariablePrefix`, :option:`ConstexprVariableSuffix`
+ - :option:`EnumCase`, :option:`EnumPrefix`, :option:`EnumSuffix`
+ - :option:`EnumConstantCase`, :option:`EnumConstantPrefix`, :option:`EnumConstantSuffix`
+ - :option:`FunctionCase`, :option:`FunctionPrefix`, :option:`FunctionSuffix`
+ - :option:`GlobalConstantCase`, :option:`GlobalConstantPrefix`, :option:`GlobalConstantSuffix`
+ - :option:`GlobalConstantPointerCase`, :option:`GlobalConstantPointerPrefix`, :option:`GlobalConstantPointerSuffix`
+ - :option:`GlobalFunctionCase`, :option:`GlobalFunctionPrefix`, :option:`GlobalFunctionSuffix`
+ - :option:`GlobalPointerCase`, :option:`GlobalPointerPrefix`, :option:`GlobalPointerSuffix`
+ - :option:`GlobalVariableCase`, :option:`GlobalVariablePrefix`, :option:`GlobalVariableSuffix`
+ - :option:`InlineNamespaceCase`, :option:`InlineNamespacePrefix`, :option:`InlineNamespaceSuffix`
+ - :option:`LocalConstantCase`, :option:`LocalConstantPrefix`, :option:`LocalConstantSuffix`
+ - :option:`LocalConstantPointerCase`, :option:`LocalConstantPointerPrefix`, :option:`LocalConstantPointerSuffix`
+ - :option:`LocalPointerCase`, :option:`LocalPointerPrefix`, :option:`LocalPointerSuffix`
+ - :option:`LocalVariableCase`, :option:`LocalVariablePrefix`, :option:`LocalVariableSuffix`
+ - :option:`MemberCase`, :option:`MemberPrefix`, :option:`MemberSuffix`
+ - :option:`MethodCase`, :option:`MethodPrefix`, :option:`MethodSuffix`
+ - :option:`NamespaceCase`, :option:`NamespacePrefix`, :option:`NamespaceSuffix`
+ - :option:`ParameterCase`, :option:`ParameterPrefix`, :option:`ParameterSuffix`
+ - :option:`ParameterPackCase`, :option:`ParameterPackPrefix`, :option:`ParameterPackSuffix`
+ - :option:`PointerParameterCase`, :option:`PointerParameterPrefix`, :option:`PointerParameterSuffix`
+ - :option:`PrivateMemberCase`, :option:`PrivateMemberPrefix`, :option:`PrivateMemberSuffix`
+ - :option:`PrivateMethodCase`, :option:`PrivateMethodPrefix`, :option:`PrivateMethodSuffix`
+ - :option:`ProtectedMemberCase`, :option:`ProtectedMemberPrefix`, :option:`ProtectedMemberSuffix`
+ - :option:`ProtectedMethodCase`, :option:`ProtectedMethodPrefix`, :option:`ProtectedMethodSuffix`
+ - :option:`PublicMemberCase`, :option:`PublicMemberPrefix`, :option:`PublicMemberSuffix`
+ - :option:`PublicMethodCase`, :option:`PublicMethodPrefix`, :option:`PublicMethodSuffix`
+ - :option:`StaticConstantCase`, :option:`StaticConstantPrefix`, :option:`StaticConstantSuffix`
+ - :option:`StaticVariableCase`, :option:`StaticVariablePrefix`, :option:`StaticVariableSuffix`
+ - :option:`StructCase`, :option:`StructPrefix`, :option:`StructSuffix`
+ - :option:`TemplateParameterCase`, :option:`TemplateParameterPrefix`, :option:`TemplateParameterSuffix`
+ - :option:`TemplateTemplateParameterCase`, :option:`TemplateTemplateParameterPrefix`, :option:`TemplateTemplateParameterSuffix`
+ - :option:`TypeAliasCase`, :option:`TypeAliasPrefix`, :option:`TypeAliasSuffix`
+ - :option:`TypedefCase`, :option:`TypedefPrefix`, :option:`TypedefSuffix`
+ - :option:`TypeTemplateParameterCase`, :option:`TypeTemplateParameterPrefix`, :option:`TypeTemplateParameterSuffix`
+ - :option:`UnionCase`, :option:`UnionPrefix`, :option:`UnionSuffix`
+ - :option:`ValueTemplateParameterCase`, :option:`ValueTemplateParameterPrefix`, :option:`ValueTemplateParameterSuffix`
+ - :option:`VariableCase`, :option:`VariablePrefix`, :option:`VariableSuffix`
+ - :option:`VirtualMethodCase`, :option:`VirtualMethodPrefix`, :option:`VirtualMethodSuffix`
+
+.. option:: AbstractClassCase
+
+ When defined, the check will ensure abstract class names conform to the
+ selected casing.
+
+.. option:: AbstractClassPrefix
+
+ When defined, the check will ensure abstract class names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: AbstractClassSuffix
+
+ When defined, the check will ensure abstract class names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - AbstractClassCase of ``lower_case``
+ - AbstractClassPrefix of ``pre_``
+ - AbstractClassSuffix of ``_post``
+
+Identifies and/or transforms abstract class names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class ABSTRACT_CLASS {
+ public:
+ ABSTRACT_CLASS();
+ };
+
+After:
+
+.. code-block:: c++
+
+ class pre_abstract_class_post {
+ public:
+ pre_abstract_class_post();
+ };
+
+.. option:: ClassCase
+
+ When defined, the check will ensure class names conform to the
+ selected casing.
+
+.. option:: ClassPrefix
+
+ When defined, the check will ensure class names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ClassSuffix
+
+ When defined, the check will ensure class names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ClassCase of ``lower_case``
+ - ClassPrefix of ``pre_``
+ - ClassSuffix of ``_post``
+
+Identifies and/or transforms class names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class FOO {
+ public:
+ FOO();
+ ~FOO();
+ };
+
+After:
+
+.. code-block:: c++
+
+ class pre_foo_post {
+ public:
+ pre_foo_post();
+ ~pre_foo_post();
+ };
+
+.. option:: ClassConstantCase
+
+ When defined, the check will ensure class constant names conform to the
+ selected casing.
+
+.. option:: ClassConstantPrefix
+
+ When defined, the check will ensure class constant names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ClassConstantSuffix
+
+ When defined, the check will ensure class constant names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ClassConstantCase of ``lower_case``
+ - ClassConstantPrefix of ``pre_``
+ - ClassConstantSuffix of ``_post``
+
+Identifies and/or transforms class constant names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class FOO {
+ public:
+ static const int CLASS_CONSTANT;
+ };
+
+After:
+
+.. code-block:: c++
+
+ class FOO {
+ public:
+ static const int pre_class_constant_post;
+ };
+
+.. option:: ClassMemberCase
+
+ When defined, the check will ensure class member names conform to the
+ selected casing.
+
+.. option:: ClassMemberPrefix
+
+ When defined, the check will ensure class member names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ClassMemberSuffix
+
+ When defined, the check will ensure class member names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ClassMemberCase of ``lower_case``
+ - ClassMemberPrefix of ``pre_``
+ - ClassMemberSuffix of ``_post``
+
+Identifies and/or transforms class member names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class FOO {
+ public:
+ static int CLASS_CONSTANT;
+ };
+
+After:
+
+.. code-block:: c++
+
+ class FOO {
+ public:
+ static int pre_class_constant_post;
+ };
+
+.. option:: ClassMethodCase
+
+ When defined, the check will ensure class method names conform to the
+ selected casing.
+
+.. option:: ClassMethodPrefix
+
+ When defined, the check will ensure class method names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ClassMethodSuffix
+
+ When defined, the check will ensure class method names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ClassMethodCase of ``lower_case``
+ - ClassMethodPrefix of ``pre_``
+ - ClassMethodSuffix of ``_post``
+
+Identifies and/or transforms class method names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class FOO {
+ public:
+ int CLASS_MEMBER();
+ };
+
+After:
+
+.. code-block:: c++
+
+ class FOO {
+ public:
+ int pre_class_member_post();
+ };
+
+.. option:: ConstantCase
+
+ When defined, the check will ensure constant names conform to the
+ selected casing.
+
+.. option:: ConstantPrefix
+
+ When defined, the check will ensure constant names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ConstantSuffix
+
+ When defined, the check will ensure constant names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ConstantCase of ``lower_case``
+ - ConstantPrefix of ``pre_``
+ - ConstantSuffix of ``_post``
+
+Identifies and/or transforms constant names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ void function() { unsigned const MyConst_array[] = {1, 2, 3}; }
+
+After:
+
+.. code-block:: c++
+
+ void function() { unsigned const pre_myconst_array_post[] = {1, 2, 3}; }
+
+.. option:: ConstantMemberCase
+
+ When defined, the check will ensure constant member names conform to the
+ selected casing.
+
+.. option:: ConstantMemberPrefix
+
+ When defined, the check will ensure constant member names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ConstantMemberSuffix
+
+ When defined, the check will ensure constant member names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ConstantMemberCase of ``lower_case``
+ - ConstantMemberPrefix of ``pre_``
+ - ConstantMemberSuffix of ``_post``
+
+Identifies and/or transforms constant member names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class Foo {
+ char const MY_ConstMember_string[4] = "123";
+ }
+
+After:
+
+.. code-block:: c++
+
+ class Foo {
+ char const pre_my_constmember_string_post[4] = "123";
+ }
+
+.. option:: ConstantParameterCase
+
+ When defined, the check will ensure constant parameter names conform to the
+ selected casing.
+
+.. option:: ConstantParameterPrefix
+
+ When defined, the check will ensure constant parameter names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ConstantParameterSuffix
+
+ When defined, the check will ensure constant parameter names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ConstantParameterCase of ``lower_case``
+ - ConstantParameterPrefix of ``pre_``
+ - ConstantParameterSuffix of ``_post``
+
+Identifies and/or transforms constant parameter names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ void GLOBAL_FUNCTION(int PARAMETER_1, int const CONST_parameter);
+
+After:
+
+.. code-block:: c++
+
+ void GLOBAL_FUNCTION(int PARAMETER_1, int const pre_const_parameter_post);
+
+.. option:: ConstantPointerParameterCase
+
+ When defined, the check will ensure constant pointer parameter names conform to the
+ selected casing.
+
+.. option:: ConstantPointerParameterPrefix
+
+ When defined, the check will ensure constant pointer parameter names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ConstantPointerParameterSuffix
+
+ When defined, the check will ensure constant pointer parameter names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ConstantPointerParameterCase of ``lower_case``
+ - ConstantPointerParameterPrefix of ``pre_``
+ - ConstantPointerParameterSuffix of ``_post``
+
+Identifies and/or transforms constant pointer parameter names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ void GLOBAL_FUNCTION(int const *CONST_parameter);
+
+After:
+
+.. code-block:: c++
+
+ void GLOBAL_FUNCTION(int const *pre_const_parameter_post);
+
+.. option:: ConstexprFunctionCase
+
+ When defined, the check will ensure constexpr function names conform to the
+ selected casing.
+
+.. option:: ConstexprFunctionPrefix
+
+ When defined, the check will ensure constexpr function names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ConstexprFunctionSuffix
+
+ When defined, the check will ensure constexpr function names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ConstexprFunctionCase of ``lower_case``
+ - ConstexprFunctionPrefix of ``pre_``
+ - ConstexprFunctionSuffix of ``_post``
+
+Identifies and/or transforms constexpr function names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ constexpr int CE_function() { return 3; }
+
+After:
+
+.. code-block:: c++
+
+ constexpr int pre_ce_function_post() { return 3; }
+
+.. option:: ConstexprMethodCase
+
+ When defined, the check will ensure constexpr method names conform to the
+ selected casing.
+
+.. option:: ConstexprMethodPrefix
+
+ When defined, the check will ensure constexpr method names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ConstexprMethodSuffix
+
+ When defined, the check will ensure constexpr method names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ConstexprMethodCase of ``lower_case``
+ - ConstexprMethodPrefix of ``pre_``
+ - ConstexprMethodSuffix of ``_post``
+
+Identifies and/or transforms constexpr method names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class Foo {
+ public:
+ constexpr int CST_expr_Method() { return 2; }
+ }
+
+After:
+
+.. code-block:: c++
+
+ class Foo {
+ public:
+ constexpr int pre_cst_expr_method_post() { return 2; }
+ }
+
+.. option:: ConstexprVariableCase
+
+ When defined, the check will ensure constexpr variable names conform to the
+ selected casing.
+
+.. option:: ConstexprVariablePrefix
+
+ When defined, the check will ensure constexpr variable names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ConstexprVariableSuffix
+
+ When defined, the check will ensure constexpr variable names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ConstexprVariableCase of ``lower_case``
+ - ConstexprVariablePrefix of ``pre_``
+ - ConstexprVariableSuffix of ``_post``
+
+Identifies and/or transforms constexpr variable names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ constexpr int ConstExpr_variable = MyConstant;
+
+After:
+
+.. code-block:: c++
+
+ constexpr int pre_constexpr_variable_post = MyConstant;
+
+.. option:: EnumCase
+
+ When defined, the check will ensure enumeration names conform to the
+ selected casing.
+
+.. option:: EnumPrefix
+
+ When defined, the check will ensure enumeration names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: EnumSuffix
+
+ When defined, the check will ensure enumeration names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - EnumCase of ``lower_case``
+ - EnumPrefix of ``pre_``
+ - EnumSuffix of ``_post``
+
+Identifies and/or transforms enumeration names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ enum FOO { One, Two, Three };
+
+After:
+
+.. code-block:: c++
+
+ enum pre_foo_post { One, Two, Three };
+
+.. option:: EnumConstantCase
+
+ When defined, the check will ensure enumeration constant names conform to the
+ selected casing.
+
+.. option:: EnumConstantPrefix
+
+ When defined, the check will ensure enumeration constant names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: EnumConstantSuffix
+
+ When defined, the check will ensure enumeration constant names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - EnumConstantCase of ``lower_case``
+ - EnumConstantPrefix of ``pre_``
+ - EnumConstantSuffix of ``_post``
+
+Identifies and/or transforms enumeration constant names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ enum FOO { One, Two, Three };
+
+After:
+
+.. code-block:: c++
+
+ enum FOO { pre_One_post, pre_Two_post, pre_Three_post };
+
+.. option:: FunctionCase
+
+ When defined, the check will ensure function names conform to the
+ selected casing.
+
+.. option:: FunctionPrefix
+
+ When defined, the check will ensure function names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: FunctionSuffix
+
+ When defined, the check will ensure function names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - FunctionCase of ``lower_case``
+ - FunctionPrefix of ``pre_``
+ - FunctionSuffix of ``_post``
+
+Identifies and/or transforms function names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ char MY_Function_string();
+
+After:
+
+.. code-block:: c++
+
+ char pre_my_function_string_post();
+
+.. option:: GlobalConstantCase
+
+ When defined, the check will ensure global constant names conform to the
+ selected casing.
+
+.. option:: GlobalConstantPrefix
+
+ When defined, the check will ensure global constant names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: GlobalConstantSuffix
+
+ When defined, the check will ensure global constant names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - GlobalConstantCase of ``lower_case``
+ - GlobalConstantPrefix of ``pre_``
+ - GlobalConstantSuffix of ``_post``
+
+Identifies and/or transforms global constant names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ unsigned const MyConstGlobal_array[] = {1, 2, 3};
+
+After:
+
+.. code-block:: c++
+
+ unsigned const pre_myconstglobal_array_post[] = {1, 2, 3};
+
+.. option:: GlobalConstantPointerCase
+
+ When defined, the check will ensure global constant pointer names conform to the
+ selected casing.
+
+.. option:: GlobalConstantPointerPrefix
+
+ When defined, the check will ensure global constant pointer names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: GlobalConstantPointerSuffix
+
+ When defined, the check will ensure global constant pointer names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - GlobalConstantPointerCase of ``lower_case``
+ - GlobalConstantPointerPrefix of ``pre_``
+ - GlobalConstantPointerSuffix of ``_post``
+
+Identifies and/or transforms global constant pointer names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ int *const MyConstantGlobalPointer = nullptr;
+
+After:
+
+.. code-block:: c++
+
+ int *const pre_myconstantglobalpointer_post = nullptr;
+
+.. option:: GlobalFunctionCase
+
+ When defined, the check will ensure global function names conform to the
+ selected casing.
+
+.. option:: GlobalFunctionPrefix
+
+ When defined, the check will ensure global function names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: GlobalFunctionSuffix
+
+ When defined, the check will ensure global function names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - GlobalFunctionCase of ``lower_case``
+ - GlobalFunctionPrefix of ``pre_``
+ - GlobalFunctionSuffix of ``_post``
+
+Identifies and/or transforms global function names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ void GLOBAL_FUNCTION(int PARAMETER_1, int const CONST_parameter);
+
+After:
+
+.. code-block:: c++
+
+ void pre_global_function_post(int PARAMETER_1, int const CONST_parameter);
+
+.. option:: GlobalPointerCase
+
+ When defined, the check will ensure global pointer names conform to the
+ selected casing.
+
+.. option:: GlobalPointerPrefix
+
+ When defined, the check will ensure global pointer names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: GlobalPointerSuffix
+
+ When defined, the check will ensure global pointer names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - GlobalPointerCase of ``lower_case``
+ - GlobalPointerPrefix of ``pre_``
+ - GlobalPointerSuffix of ``_post``
+
+Identifies and/or transforms global pointer names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ int *GLOBAL3;
+
+After:
+
+.. code-block:: c++
+
+ int *pre_global3_post;
+
+.. option:: GlobalVariableCase
+
+ When defined, the check will ensure global variable names conform to the
+ selected casing.
+
+.. option:: GlobalVariablePrefix
+
+ When defined, the check will ensure global variable names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: GlobalVariableSuffix
+
+ When defined, the check will ensure global variable names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - GlobalVariableCase of ``lower_case``
+ - GlobalVariablePrefix of ``pre_``
+ - GlobalVariableSuffix of ``_post``
+
+Identifies and/or transforms global variable names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ int GLOBAL3;
+
+After:
+
+.. code-block:: c++
+
+ int pre_global3_post;
+
+.. option:: InlineNamespaceCase
+
+ When defined, the check will ensure inline namespaces names conform to the
+ selected casing.
+
+.. option:: InlineNamespacePrefix
+
+ When defined, the check will ensure inline namespaces names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: InlineNamespaceSuffix
+
+ When defined, the check will ensure inline namespaces names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - InlineNamespaceCase of ``lower_case``
+ - InlineNamespacePrefix of ``pre_``
+ - InlineNamespaceSuffix of ``_post``
+
+Identifies and/or transforms inline namespaces names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ namespace FOO_NS {
+ inline namespace InlineNamespace {
+ ...
+ }
+ } // namespace FOO_NS
+
+After:
+
+.. code-block:: c++
+
+ namespace FOO_NS {
+ inline namespace pre_inlinenamespace_post {
+ ...
+ }
+ } // namespace FOO_NS
+
+.. option:: LocalConstantCase
+
+ When defined, the check will ensure local constant names conform to the
+ selected casing.
+
+.. option:: LocalConstantPrefix
+
+ When defined, the check will ensure local constant names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: LocalConstantSuffix
+
+ When defined, the check will ensure local constant names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - LocalConstantCase of ``lower_case``
+ - LocalConstantPrefix of ``pre_``
+ - LocalConstantSuffix of ``_post``
+
+Identifies and/or transforms local constant names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ void foo() { int const local_Constant = 3; }
+
+After:
+
+.. code-block:: c++
+
+ void foo() { int const pre_local_constant_post = 3; }
+
+.. option:: LocalConstantPointerCase
+
+ When defined, the check will ensure local constant pointer names conform to the
+ selected casing.
+
+.. option:: LocalConstantPointerPrefix
+
+ When defined, the check will ensure local constant pointer names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: LocalConstantPointerSuffix
+
+ When defined, the check will ensure local constant pointer names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - LocalConstantPointerCase of ``lower_case``
+ - LocalConstantPointerPrefix of ``pre_``
+ - LocalConstantPointerSuffix of ``_post``
+
+Identifies and/or transforms local constant pointer names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ void foo() { int const *local_Constant = 3; }
+
+After:
+
+.. code-block:: c++
+
+ void foo() { int const *pre_local_constant_post = 3; }
+
+.. option:: LocalPointerCase
+
+ When defined, the check will ensure local pointer names conform to the
+ selected casing.
+
+.. option:: LocalPointerPrefix
+
+ When defined, the check will ensure local pointer names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: LocalPointerSuffix
+
+ When defined, the check will ensure local pointer names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - LocalPointerCase of ``lower_case``
+ - LocalPointerPrefix of ``pre_``
+ - LocalPointerSuffix of ``_post``
+
+Identifies and/or transforms local pointer names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ void foo() { int *local_Constant; }
+
+After:
+
+.. code-block:: c++
+
+ void foo() { int *pre_local_constant_post; }
+
+.. option:: LocalVariableCase
+
+ When defined, the check will ensure local variable names conform to the
+ selected casing.
+
+.. option:: LocalVariablePrefix
+
+ When defined, the check will ensure local variable names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: LocalVariableSuffix
+
+ When defined, the check will ensure local variable names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - LocalVariableCase of ``lower_case``
+ - LocalVariablePrefix of ``pre_``
+ - LocalVariableSuffix of ``_post``
+
+Identifies and/or transforms local variable names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ void foo() { int local_Constant; }
+
+After:
+
+.. code-block:: c++
+
+ void foo() { int pre_local_constant_post; }
+
+.. option:: MemberCase
+
+ When defined, the check will ensure member names conform to the
+ selected casing.
+
+.. option:: MemberPrefix
+
+ When defined, the check will ensure member names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: MemberSuffix
+
+ When defined, the check will ensure member names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - MemberCase of ``lower_case``
+ - MemberPrefix of ``pre_``
+ - MemberSuffix of ``_post``
+
+Identifies and/or transforms member names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class Foo {
+ char MY_ConstMember_string[4];
+ }
+
+After:
+
+.. code-block:: c++
+
+ class Foo {
+ char pre_my_constmember_string_post[4];
+ }
+
+.. option:: MethodCase
+
+ When defined, the check will ensure method names conform to the
+ selected casing.
+
+.. option:: MethodPrefix
+
+ When defined, the check will ensure method names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: MethodSuffix
+
+ When defined, the check will ensure method names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - MethodCase of ``lower_case``
+ - MethodPrefix of ``pre_``
+ - MethodSuffix of ``_post``
+
+Identifies and/or transforms method names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class Foo {
+ char MY_Method_string();
+ }
+
+After:
+
+.. code-block:: c++
+
+ class Foo {
+ char pre_my_method_string_post();
+ }
+
+.. option:: NamespaceCase
+
+ When defined, the check will ensure namespace names conform to the
+ selected casing.
+
+.. option:: NamespacePrefix
+
+ When defined, the check will ensure namespace names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: NamespaceSuffix
+
+ When defined, the check will ensure namespace names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - NamespaceCase of ``lower_case``
+ - NamespacePrefix of ``pre_``
+ - NamespaceSuffix of ``_post``
+
+Identifies and/or transforms namespace names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ namespace FOO_NS {
+ ...
+ }
+
+After:
+
+.. code-block:: c++
+
+ namespace pre_foo_ns_post {
+ ...
+ }
+
+.. option:: ParameterCase
+
+ When defined, the check will ensure parameter names conform to the
+ selected casing.
+
+.. option:: ParameterPrefix
+
+ When defined, the check will ensure parameter names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ParameterSuffix
+
+ When defined, the check will ensure parameter names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ParameterCase of ``lower_case``
+ - ParameterPrefix of ``pre_``
+ - ParameterSuffix of ``_post``
+
+Identifies and/or transforms parameter names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ void GLOBAL_FUNCTION(int PARAMETER_1, int const CONST_parameter);
+
+After:
+
+.. code-block:: c++
+
+ void GLOBAL_FUNCTION(int pre_parameter_post, int const CONST_parameter);
+
+.. option:: ParameterPackCase
+
+ When defined, the check will ensure parameter pack names conform to the
+ selected casing.
+
+.. option:: ParameterPackPrefix
+
+ When defined, the check will ensure parameter pack names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ParameterPackSuffix
+
+ When defined, the check will ensure parameter pack names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ParameterPackCase of ``lower_case``
+ - ParameterPackPrefix of ``pre_``
+ - ParameterPackSuffix of ``_post``
+
+Identifies and/or transforms parameter pack names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ template <typename... TYPE_parameters> {
+ void FUNCTION(int... TYPE_parameters);
+ }
+
+After:
+
+.. code-block:: c++
+
+ template <typename... TYPE_parameters> {
+ void FUNCTION(int... pre_type_parameters_post);
+ }
+
+.. option:: PointerParameterCase
+
+ When defined, the check will ensure pointer parameter names conform to the
+ selected casing.
+
+.. option:: PointerParameterPrefix
+
+ When defined, the check will ensure pointer parameter names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: PointerParameterSuffix
+
+ When defined, the check will ensure pointer parameter names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - PointerParameterCase of ``lower_case``
+ - PointerParameterPrefix of ``pre_``
+ - PointerParameterSuffix of ``_post``
+
+Identifies and/or transforms pointer parameter names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ void FUNCTION(int *PARAMETER);
+
+After:
+
+.. code-block:: c++
+
+ void FUNCTION(int *pre_parameter_post);
+
+.. option:: PrivateMemberCase
+
+ When defined, the check will ensure private member names conform to the
+ selected casing.
+
+.. option:: PrivateMemberPrefix
+
+ When defined, the check will ensure private member names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: PrivateMemberSuffix
+
+ When defined, the check will ensure private member names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - PrivateMemberCase of ``lower_case``
+ - PrivateMemberPrefix of ``pre_``
+ - PrivateMemberSuffix of ``_post``
+
+Identifies and/or transforms private member names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class Foo {
+ private:
+ int Member_Variable;
+ }
+
+After:
+
+.. code-block:: c++
+
+ class Foo {
+ private:
+ int pre_member_variable_post;
+ }
+
+.. option:: PrivateMethodCase
+
+ When defined, the check will ensure private method names conform to the
+ selected casing.
+
+.. option:: PrivateMethodPrefix
+
+ When defined, the check will ensure private method names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: PrivateMethodSuffix
+
+ When defined, the check will ensure private method names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - PrivateMethodCase of ``lower_case``
+ - PrivateMethodPrefix of ``pre_``
+ - PrivateMethodSuffix of ``_post``
+
+Identifies and/or transforms private method names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class Foo {
+ private:
+ int Member_Method();
+ }
+
+After:
+
+.. code-block:: c++
+
+ class Foo {
+ private:
+ int pre_member_method_post();
+ }
+
+.. option:: ProtectedMemberCase
+
+ When defined, the check will ensure protected member names conform to the
+ selected casing.
+
+.. option:: ProtectedMemberPrefix
+
+ When defined, the check will ensure protected member names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ProtectedMemberSuffix
+
+ When defined, the check will ensure protected member names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ProtectedMemberCase of ``lower_case``
+ - ProtectedMemberPrefix of ``pre_``
+ - ProtectedMemberSuffix of ``_post``
+
+Identifies and/or transforms protected member names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class Foo {
+ protected:
+ int Member_Variable;
+ }
+
+After:
+
+.. code-block:: c++
+
+ class Foo {
+ protected:
+ int pre_member_variable_post;
+ }
+
+.. option:: ProtectedMethodCase
+
+ When defined, the check will ensure protect method names conform to the
+ selected casing.
+
+.. option:: ProtectedMethodPrefix
+
+ When defined, the check will ensure protect method names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ProtectedMethodSuffix
+
+ When defined, the check will ensure protect method names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ProtectedMethodCase of ``lower_case``
+ - ProtectedMethodPrefix of ``pre_``
+ - ProtectedMethodSuffix of ``_post``
+
+Identifies and/or transforms protect method names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class Foo {
+ protected:
+ int Member_Method();
+ }
+
+After:
+
+.. code-block:: c++
+
+ class Foo {
+ protected:
+ int pre_member_method_post();
+ }
+
+.. option:: PublicMemberCase
+
+ When defined, the check will ensure public member names conform to the
+ selected casing.
+
+.. option:: PublicMemberPrefix
+
+ When defined, the check will ensure public member names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: PublicMemberSuffix
+
+ When defined, the check will ensure public member names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - PublicMemberCase of ``lower_case``
+ - PublicMemberPrefix of ``pre_``
+ - PublicMemberSuffix of ``_post``
+
+Identifies and/or transforms public member names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class Foo {
+ public:
+ int Member_Variable;
+ }
+
+After:
+
+.. code-block:: c++
+
+ class Foo {
+ public:
+ int pre_member_variable_post;
+ }
+
+.. option:: PublicMethodCase
+
+ When defined, the check will ensure public method names conform to the
+ selected casing.
+
+.. option:: PublicMethodPrefix
+
+ When defined, the check will ensure public method names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: PublicMethodSuffix
+
+ When defined, the check will ensure public method names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - PublicMethodCase of ``lower_case``
+ - PublicMethodPrefix of ``pre_``
+ - PublicMethodSuffix of ``_post``
+
+Identifies and/or transforms public method names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class Foo {
+ public:
+ int Member_Method();
+ }
+
+After:
+
+.. code-block:: c++
+
+ class Foo {
+ public:
+ int pre_member_method_post();
+ }
+
+.. option:: StaticConstantCase
+
+ When defined, the check will ensure static constant names conform to the
+ selected casing.
+
+.. option:: StaticConstantPrefix
+
+ When defined, the check will ensure static constant names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: StaticConstantSuffix
+
+ When defined, the check will ensure static constant names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - StaticConstantCase of ``lower_case``
+ - StaticConstantPrefix of ``pre_``
+ - StaticConstantSuffix of ``_post``
+
+Identifies and/or transforms static constant names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ static unsigned const MyConstStatic_array[] = {1, 2, 3};
+
+After:
+
+.. code-block:: c++
+
+ static unsigned const pre_myconststatic_array_post[] = {1, 2, 3};
+
+.. option:: StaticVariableCase
+
+ When defined, the check will ensure static variable names conform to the
+ selected casing.
+
+.. option:: StaticVariablePrefix
+
+ When defined, the check will ensure static variable names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: StaticVariableSuffix
+
+ When defined, the check will ensure static variable names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - StaticVariableCase of ``lower_case``
+ - StaticVariablePrefix of ``pre_``
+ - StaticVariableSuffix of ``_post``
+
+Identifies and/or transforms static variable names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ static unsigned MyStatic_array[] = {1, 2, 3};
+
+After:
+
+.. code-block:: c++
+
+ static unsigned pre_mystatic_array_post[] = {1, 2, 3};
+
+.. option:: StructCase
+
+ When defined, the check will ensure struct names conform to the
+ selected casing.
+
+.. option:: StructPrefix
+
+ When defined, the check will ensure struct names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: StructSuffix
+
+ When defined, the check will ensure struct names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - StructCase of ``lower_case``
+ - StructPrefix of ``pre_``
+ - StructSuffix of ``_post``
+
+Identifies and/or transforms struct names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ struct FOO {
+ FOO();
+ ~FOO();
+ };
+
+After:
+
+.. code-block:: c++
+
+ struct pre_foo_post {
+ pre_foo_post();
+ ~pre_foo_post();
+ };
+
+.. option:: TemplateParameterCase
+
+ When defined, the check will ensure template parameter names conform to the
+ selected casing.
+
+.. option:: TemplateParameterPrefix
+
+ When defined, the check will ensure template parameter names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: TemplateParameterSuffix
+
+ When defined, the check will ensure template parameter names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - TemplateParameterCase of ``lower_case``
+ - TemplateParameterPrefix of ``pre_``
+ - TemplateParameterSuffix of ``_post``
+
+Identifies and/or transforms template parameter names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ template <typename T> class Foo {};
+
+After:
+
+.. code-block:: c++
+
+ template <typename pre_t_post> class Foo {};
+
+.. option:: TemplateTemplateParameterCase
+
+ When defined, the check will ensure template template parameter names conform to the
+ selected casing.
+
+.. option:: TemplateTemplateParameterPrefix
+
+ When defined, the check will ensure template template parameter names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: TemplateTemplateParameterSuffix
+
+ When defined, the check will ensure template template parameter names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - TemplateTemplateParameterCase of ``lower_case``
+ - TemplateTemplateParameterPrefix of ``pre_``
+ - TemplateTemplateParameterSuffix of ``_post``
+
+Identifies and/or transforms template template parameter names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ template <template <typename> class TPL_parameter, int COUNT_params,
+ typename... TYPE_parameters>
+
+After:
+
+.. code-block:: c++
+
+ template <template <typename> class pre_tpl_parameter_post, int COUNT_params,
+ typename... TYPE_parameters>
+
+.. option:: TypeAliasCase
+
+ When defined, the check will ensure type alias names conform to the
+ selected casing.
+
+.. option:: TypeAliasPrefix
+
+ When defined, the check will ensure type alias names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: TypeAliasSuffix
+
+ When defined, the check will ensure type alias names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - TypeAliasCase of ``lower_case``
+ - TypeAliasPrefix of ``pre_``
+ - TypeAliasSuffix of ``_post``
+
+Identifies and/or transforms type alias names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ using MY_STRUCT_TYPE = my_structure;
+
+After:
+
+.. code-block:: c++
+
+ using pre_my_struct_type_post = my_structure;
+
+.. option:: TypedefCase
+
+ When defined, the check will ensure typedef names conform to the
+ selected casing.
+
+.. option:: TypedefPrefix
+
+ When defined, the check will ensure typedef names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: TypedefSuffix
+
+ When defined, the check will ensure typedef names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - TypedefCase of ``lower_case``
+ - TypedefPrefix of ``pre_``
+ - TypedefSuffix of ``_post``
+
+Identifies and/or transforms typedef names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ typedef int MYINT;
+
+After:
+
+.. code-block:: c++
+
+ typedef int pre_myint_post;
+
+.. option:: TypeTemplateParameterCase
+
+ When defined, the check will ensure type template parameter names conform to the
+ selected casing.
+
+.. option:: TypeTemplateParameterPrefix
+
+ When defined, the check will ensure type template parameter names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: TypeTemplateParameterSuffix
+
+ When defined, the check will ensure type template parameter names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - TypeTemplateParameterCase of ``lower_case``
+ - TypeTemplateParameterPrefix of ``pre_``
+ - TypeTemplateParameterSuffix of ``_post``
+
+Identifies and/or transforms type template parameter names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ template <template <typename> class TPL_parameter, int COUNT_params,
+ typename... TYPE_parameters>
+
+After:
+
+.. code-block:: c++
+
+ template <template <typename> class TPL_parameter, int COUNT_params,
+ typename... pre_type_parameters_post>
+
+.. option:: UnionCase
+
+ When defined, the check will ensure union names conform to the
+ selected casing.
+
+.. option:: UnionPrefix
+
+ When defined, the check will ensure union names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: UnionSuffix
+
+ When defined, the check will ensure union names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - UnionCase of ``lower_case``
+ - UnionPrefix of ``pre_``
+ - UnionSuffix of ``_post``
+
+Identifies and/or transforms union names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ union FOO {
+ int a;
+ char b;
+ };
+
+After:
+
+.. code-block:: c++
+
+ union pre_foo_post {
+ int a;
+ char b;
+ };
+
+.. option:: ValueTemplateParameterCase
+
+ When defined, the check will ensure value template parameter names conform to the
+ selected casing.
+
+.. option:: ValueTemplateParameterPrefix
+
+ When defined, the check will ensure value template parameter names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: ValueTemplateParameterSuffix
+
+ When defined, the check will ensure value template parameter names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - ValueTemplateParameterCase of ``lower_case``
+ - ValueTemplateParameterPrefix of ``pre_``
+ - ValueTemplateParameterSuffix of ``_post``
+
+Identifies and/or transforms value template parameter names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ template <template <typename> class TPL_parameter, int COUNT_params,
+ typename... TYPE_parameters>
+
+After:
+
+.. code-block:: c++
+
+ template <template <typename> class TPL_parameter, int pre_count_params_post,
+ typename... TYPE_parameters>
+
+.. option:: VariableCase
+
+ When defined, the check will ensure variable names conform to the
+ selected casing.
+
+.. option:: VariablePrefix
+
+ When defined, the check will ensure variable names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: VariableSuffix
+
+ When defined, the check will ensure variable names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - VariableCase of ``lower_case``
+ - VariablePrefix of ``pre_``
+ - VariableSuffix of ``_post``
+
+Identifies and/or transforms variable names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ unsigned MyVariable;
+
+After:
+
+.. code-block:: c++
+
+ unsigned pre_myvariable_post;
+
+.. option:: VirtualMethodCase
+
+ When defined, the check will ensure virtual method names conform to the
+ selected casing.
+
+.. option:: VirtualMethodPrefix
+
+ When defined, the check will ensure virtual method names will add the
+ prefixed with the given value (regardless of casing).
+
+.. option:: VirtualMethodSuffix
+
+ When defined, the check will ensure virtual method names will add the
+ suffix with the given value (regardless of casing).
+
+For example using values of:
+
+ - VirtualMethodCase of ``lower_case``
+ - VirtualMethodPrefix of ``pre_``
+ - VirtualMethodSuffix of ``_post``
+
+Identifies and/or transforms virtual method names as follows:
+
+Before:
+
+.. code-block:: c++
+
+ class Foo {
+ public:
+ virtual int MemberFunction();
+ }
+
+After:
+
+.. code-block:: c++
+
+ class Foo {
+ public:
+ virtual int pre_member_function_post();
+ }
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/checks/readability-redundant-preprocessor.rst b/docs/clang-tidy/checks/readability-redundant-preprocessor.rst
new file mode 100644
index 00000000..f013a341
--- /dev/null
+++ b/docs/clang-tidy/checks/readability-redundant-preprocessor.rst
@@ -0,0 +1,61 @@
+.. title:: clang-tidy - readability-redundant-preprocessor
+
+readability-redundant-preprocessor
+==================================
+
+Finds potentially redundant preprocessor directives. At the moment the
+following cases are detected:
+
+* `#ifdef` .. `#endif` pairs which are nested inside an outer pair with the
+ same condition. For example:
+
+.. code-block:: c++
+
+ #ifdef FOO
+ #ifdef FOO // inner ifdef is considered redundant
+ void f();
+ #endif
+ #endif
+
+* Same for `#ifndef` .. `#endif` pairs. For example:
+
+.. code-block:: c++
+
+ #ifndef FOO
+ #ifndef FOO // inner ifndef is considered redundant
+ void f();
+ #endif
+ #endif
+
+* `#ifndef` inside an `#ifdef` with the same condition:
+
+.. code-block:: c++
+
+ #ifdef FOO
+ #ifndef FOO // inner ifndef is considered redundant
+ void f();
+ #endif
+ #endif
+
+* `#ifdef` inside an `#ifndef` with the same condition:
+
+.. code-block:: c++
+
+ #ifndef FOO
+ #ifdef FOO // inner ifdef is considered redundant
+ void f();
+ #endif
+ #endif
+
+* `#if` .. `#endif` pairs which are nested inside an outer pair with the same
+ condition. For example:
+
+.. code-block:: c++
+
+ #define FOO 4
+ #if FOO == 4
+ #if FOO == 4 // inner if is considered redundant
+ void f();
+ #endif
+ #endif
+
diff --git a/docs/clang-tidy/checks/readability-uppercase-literal-suffix.rst b/docs/clang-tidy/checks/readability-uppercase-literal-suffix.rst
index e3da0864..82c083da 100644
--- a/docs/clang-tidy/checks/readability-uppercase-literal-suffix.rst
+++ b/docs/clang-tidy/checks/readability-uppercase-literal-suffix.rst
@@ -49,3 +49,8 @@ Given a list `L;uL`:
* ``uL`` will be kept as is.
* ``ull`` will be kept as is, since it is not in the list
* and so on.
+
+.. option:: IgnoreMacros
+
+ If this option is set to non-zero (default is `1`), the check will not warn
+ about literal suffixes inside macros.
diff --git a/docs/clang-tidy/index.rst b/docs/clang-tidy/index.rst
index 20b18b4b..1cbd8dc5 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
@@ -223,7 +225,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 +260,50 @@ 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>`_ can be
+silenced by re-initializing the variable after it has been moved out,
+`bugprone-string-integer-assignment
+<checks/bugprone-string-integer-assignment>`_ can be suppressed by explicitly
+casting the integer to ``char``, `readability-implicit-bool-conversion
+<checks/readability-implicit-bool-conversion>`_ 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 +327,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..0843bcaf 100644
--- a/docs/clangd.rst
+++ b/docs/clangd.rst
@@ -31,7 +31,7 @@ Installing Clangd
==================
Packages are available for debian-based distributions, see the `LLVM packages
-page <http://apt.llvm.org/>`_. :program:`Clangd` is included in the
+page <https://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.
@@ -143,18 +143,37 @@ Emacs Integration
:program:`Emacs` provides `lsp-mode <github.com/emacs-lsp/lsp-mode>`_ and
`Eglot <https://github.com/joaotavora/eglot>`_ plugins for LSP integration.
+Project-wide Index
+==================
+
+By default :program:`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 :program:`Clangd`.
+
+There are two ways you can generate a project-wide index for clangd:
+
+- Passing experimental `-background-index` commandline argument, which will
+ incrementally build an index of projects that you work on and make use of that
+ in clangd automatically.
+- Generate an index file using `clangd-indexer
+ <https://github.com/llvm-mirror/clang-tools-extra/blob/master/clangd/indexer/IndexerMain.cpp>`_
+ Afterwards 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 standard clang-tools package. You will likely have to
+ build from source to use this option*
+
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
+<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
-<http://lists.llvm.org/mailman/listinfo/cfe-dev>`_.
+<https://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
+<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 :program:`Clangd` can eventually implement them in a
diff --git a/docs/conf.py b/docs/conf.py
index 1b07e8ef..a79558f0 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.
diff --git a/docs/include-fixer.rst b/docs/include-fixer.rst
index fcd2998b..9898840c 100644
--- a/docs/include-fixer.rst
+++ b/docs/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
---------------------------------------------------
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..9cfbef59 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`.
@@ -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:
@@ -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/include-fixer/FuzzySymbolIndex.cpp b/include-fixer/FuzzySymbolIndex.cpp
index d91f4552..099d7389 100644
--- a/include-fixer/FuzzySymbolIndex.cpp
+++ b/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/include-fixer/FuzzySymbolIndex.h
index 245191eb..2ea16609 100644
--- a/include-fixer/FuzzySymbolIndex.h
+++ b/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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/InMemorySymbolIndex.cpp b/include-fixer/InMemorySymbolIndex.cpp
index 14753bd9..e7858939 100644
--- a/include-fixer/InMemorySymbolIndex.cpp
+++ b/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/include-fixer/InMemorySymbolIndex.h
index 0e1310e3..bea8be91 100644
--- a/include-fixer/InMemorySymbolIndex.h
+++ b/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/include-fixer/IncludeFixer.cpp
index c6dfd7fc..540b263e 100644
--- a/include-fixer/IncludeFixer.cpp
+++ b/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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/IncludeFixer.h b/include-fixer/IncludeFixer.h
index 13092a34..5528e895 100644
--- a/include-fixer/IncludeFixer.h
+++ b/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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/IncludeFixerContext.cpp b/include-fixer/IncludeFixerContext.cpp
index 8106e20e..a9fef45c 100644
--- a/include-fixer/IncludeFixerContext.cpp
+++ b/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/include-fixer/IncludeFixerContext.h
index 3c44574b..bbb87e2b 100644
--- a/include-fixer/IncludeFixerContext.h
+++ b/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/include-fixer/SymbolIndex.h
index f3e6ecd9..ca04d50a 100644
--- a/include-fixer/SymbolIndex.h
+++ b/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/include-fixer/SymbolIndexManager.cpp
index e4312bf1..603b9d4f 100644
--- a/include-fixer/SymbolIndexManager.cpp
+++ b/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
//
//===----------------------------------------------------------------------===//
diff --git a/include-fixer/SymbolIndexManager.h b/include-fixer/SymbolIndexManager.h
index 12963ddb..ca2d7399 100644
--- a/include-fixer/SymbolIndexManager.h
+++ b/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/include-fixer/YamlSymbolIndex.cpp
index f3f2d5a8..de72e9a9 100644
--- a/include-fixer/YamlSymbolIndex.cpp
+++ b/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/include-fixer/YamlSymbolIndex.h
index d5d699a2..3c4f5144 100644
--- a/include-fixer/YamlSymbolIndex.h
+++ b/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/FindAllMacros.cpp b/include-fixer/find-all-symbols/FindAllMacros.cpp
index 3dc2b96f..ed1bc2f4 100644
--- a/include-fixer/find-all-symbols/FindAllMacros.cpp
+++ b/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/include-fixer/find-all-symbols/FindAllMacros.h
index 10b4a696..5aaf3884 100644
--- a/include-fixer/find-all-symbols/FindAllMacros.h
+++ b/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/include-fixer/find-all-symbols/FindAllSymbols.cpp
index bd5032d0..bb6a3fa9 100644
--- a/include-fixer/find-all-symbols/FindAllSymbols.cpp
+++ b/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/include-fixer/find-all-symbols/FindAllSymbols.h
index fca849f5..d78da668 100644
--- a/include-fixer/find-all-symbols/FindAllSymbols.h
+++ b/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/include-fixer/find-all-symbols/FindAllSymbolsAction.cpp
index bc00547a..9f1d31dc 100644
--- a/include-fixer/find-all-symbols/FindAllSymbolsAction.cpp
+++ b/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/include-fixer/find-all-symbols/FindAllSymbolsAction.h
index 7be9fe2b..ccffa4b3 100644
--- a/include-fixer/find-all-symbols/FindAllSymbolsAction.h
+++ b/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/include-fixer/find-all-symbols/HeaderMapCollector.cpp
index 379df81a..6ec49cae 100644
--- a/include-fixer/find-all-symbols/HeaderMapCollector.cpp
+++ b/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/include-fixer/find-all-symbols/HeaderMapCollector.h
index 65edd754..21358275 100644
--- a/include-fixer/find-all-symbols/HeaderMapCollector.h
+++ b/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/include-fixer/find-all-symbols/PathConfig.cpp
index de799b99..4f1ebc77 100644
--- a/include-fixer/find-all-symbols/PathConfig.cpp
+++ b/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/include-fixer/find-all-symbols/PathConfig.h
index 50de5480..9c430f25 100644
--- a/include-fixer/find-all-symbols/PathConfig.h
+++ b/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/include-fixer/find-all-symbols/PragmaCommentHandler.cpp
index 0242d385..49489752 100644
--- a/include-fixer/find-all-symbols/PragmaCommentHandler.cpp
+++ b/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/include-fixer/find-all-symbols/PragmaCommentHandler.h
index 9eb4972c..752c82f5 100644
--- a/include-fixer/find-all-symbols/PragmaCommentHandler.h
+++ b/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/include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
index 4a49479b..0d0bbd9f 100644
--- a/include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
+++ b/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/include-fixer/find-all-symbols/STLPostfixHeaderMap.h
index 162580d8..49bc5f30 100644
--- a/include-fixer/find-all-symbols/STLPostfixHeaderMap.h
+++ b/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/include-fixer/find-all-symbols/SymbolInfo.cpp
index 00bfbe5f..e5b4dba4 100644
--- a/include-fixer/find-all-symbols/SymbolInfo.cpp
+++ b/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/include-fixer/find-all-symbols/SymbolInfo.h
index 92d360d3..6def1c70 100644
--- a/include-fixer/find-all-symbols/SymbolInfo.h
+++ b/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/include-fixer/find-all-symbols/SymbolReporter.h
index 2398234c..25e86219 100644
--- a/include-fixer/find-all-symbols/SymbolReporter.h
+++ b/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/FindAllSymbolsMain.cpp b/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
index e09a5aaf..dbbe0738 100644
--- a/include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
+++ b/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/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/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/IncludeFixerPlugin.cpp b/include-fixer/plugin/IncludeFixerPlugin.cpp
index 0d6bdb75..bc9c4973 100644
--- a/include-fixer/plugin/IncludeFixerPlugin.cpp
+++ b/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/ClangIncludeFixer.cpp b/include-fixer/tool/ClangIncludeFixer.cpp
index d9d97d23..64bfdb75 100644
--- a/include-fixer/tool/ClangIncludeFixer.cpp
+++ b/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
//
//===----------------------------------------------------------------------===//
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..4ed40b38 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
//
//===----------------------------------------------------------------------===//
///
diff --git a/pp-trace/PPCallbacksTracker.h b/pp-trace/PPCallbacksTracker.h
index b46210ef..ec52feec 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
//
//===----------------------------------------------------------------------===//
///
diff --git a/pp-trace/PPTrace.cpp b/pp-trace/PPTrace.cpp
index 08e0f514..65248285 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 451c181f..adeb0368 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -16,7 +16,8 @@ endif ()
string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} CLANG_TOOLS_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR})
llvm_canonicalize_cmake_booleans(
- CLANG_ENABLE_STATIC_ANALYZER)
+ CLANG_ENABLE_STATIC_ANALYZER
+ CLANGD_BUILD_XPC_SUPPORT)
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
@@ -61,7 +62,11 @@ set(CLANG_TOOLS_TEST_DEPS
clang-headers
clang-tidy
- )
+)
+
+if(CLANGD_BUILD_XPC_SUPPORT)
+ list(APPEND CLANG_TOOLS_TEST_DEPS clangd-xpc-test-client)
+endif()
set(CLANGD_TEST_DEPS
clangd
diff --git a/test/clang-tidy/Inputs/absl/time/time.h b/test/clang-tidy/Inputs/absl/time/time.h
index 9d136a5d..8da3c2c3 100644
--- a/test/clang-tidy/Inputs/absl/time/time.h
+++ b/test/clang-tidy/Inputs/absl/time/time.h
@@ -14,6 +14,8 @@ 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);
@@ -55,6 +57,19 @@ 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);
+
// Relational Operators
constexpr bool operator<(Duration lhs, Duration rhs);
constexpr bool operator>(Duration lhs, Duration rhs);
diff --git a/test/clang-tidy/Inputs/mock-libcxx/bin/clang b/test/clang-tidy/Inputs/mock-libcxx/bin/clang
new file mode 100644
index 00000000..ed34c1f8
--- /dev/null
+++ b/test/clang-tidy/Inputs/mock-libcxx/bin/clang
@@ -0,0 +1 @@
+This file is a placeholder to keep its parent directory in git.
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-comparison.cpp b/test/clang-tidy/abseil-duration-comparison.cpp
index 7a70db6c..9fa422be 100644
--- a/test/clang-tidy/abseil-duration-comparison.cpp
+++ b/test/clang-tidy/abseil-duration-comparison.cpp
@@ -127,6 +127,33 @@ void f() {
// CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
// CHECK-FIXES: absl::Milliseconds((y + 5) * 10) > d1;
+ // 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::ToDoubleSeconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: perform comparison in the duration domain [abseil-duration-comparison]
+ // CHECK-FIXES: VALUE_IF(1, absl::Seconds(5) > d1);
+#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::ToDoubleSeconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:24: warning: perform comparison in the duration domain [abseil-duration-comparison]
+ // CHECK-FIXES: VALUE_IF(1, absl::Seconds(5) > d1);
+#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, d1, Double);
+#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, d1, Double);
+#undef VALUE_IF
+#undef VALUE_IF_2
+
// These should not match
b = 6 < 4;
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-factory-scale.cpp b/test/clang-tidy/abseil-duration-factory-scale.cpp
index dc94773f..04c36132 100644
--- a/test/clang-tidy/abseil-duration-factory-scale.cpp
+++ b/test/clang-tidy/abseil-duration-factory-scale.cpp
@@ -2,6 +2,9 @@
#include "absl/time/time.h"
+namespace std { typedef long long int64_t; }
+using int64_t = std::int64_t;
+
void ScaleTest() {
absl::Duration d;
@@ -30,6 +33,15 @@ void ScaleTest() {
d = absl::Seconds(0x0.000001p-126f);
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
// CHECK-FIXES: absl::ZeroDuration();
+ d = absl::Seconds(int{0});
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+ // CHECK-FIXES: absl::ZeroDuration();
+ d = absl::Seconds(int64_t{0});
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+ // CHECK-FIXES: absl::ZeroDuration();
+ d = absl::Seconds(float{0});
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+ // CHECK-FIXES: absl::ZeroDuration();
// Fold seconds into minutes
d = absl::Seconds(30 * 60);
@@ -83,6 +95,8 @@ void ScaleTest() {
// None of these should trigger the check
d = absl::Seconds(60);
+ d = absl::Seconds(int{60});
+ d = absl::Seconds(float{60});
d = absl::Seconds(60 + 30);
d = absl::Seconds(60 - 30);
d = absl::Seconds(50 * 30);
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..9414182c
--- /dev/null
+++ b/test/clang-tidy/abseil-duration-unnecessary-conversion.cpp
@@ -0,0 +1,69 @@
+// 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: d1
+ d2 = absl::Minutes(absl::ToDoubleMinutes(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d1
+ d2 = absl::Seconds(absl::ToDoubleSeconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d1
+ d2 = absl::Milliseconds(absl::ToDoubleMilliseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d1
+ d2 = absl::Microseconds(absl::ToDoubleMicroseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d1
+ d2 = absl::Nanoseconds(absl::ToDoubleNanoseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: 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: d1
+ d2 = absl::Minutes(absl::ToInt64Minutes(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d1
+ d2 = absl::Seconds(absl::ToInt64Seconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d1
+ d2 = absl::Milliseconds(absl::ToInt64Milliseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d1
+ d2 = absl::Microseconds(absl::ToInt64Microseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: d1
+ d2 = absl::Nanoseconds(absl::ToInt64Nanoseconds(d1));
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+ // CHECK-FIXES: 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);
+}
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/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-string-constructor.cpp b/test/clang-tidy/bugprone-string-constructor.cpp
index 51d91305..3ab4f424 100644
--- a/test/clang-tidy/bugprone-string-constructor.cpp
+++ b/test/clang-tidy/bugprone-string-constructor.cpp
@@ -9,6 +9,7 @@ template <typename C, typename T = std::char_traits<C>, typename A = std::alloca
struct basic_string {
basic_string();
basic_string(const C*, unsigned int size);
+ basic_string(const C *, const A &allocator = A());
basic_string(unsigned int size, C c);
};
typedef basic_string<char> string;
@@ -45,6 +46,15 @@ void Test() {
// CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger then string literal size
std::string q5(kText3, 0x1000000);
// CHECK-MESSAGES: [[@LINE-1]]:15: warning: suspicious large length parameter
+ std::string q6(nullptr);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructing string from nullptr is undefined behaviour
+ std::string q7 = 0;
+ // CHECK-MESSAGES: [[@LINE-1]]:20: warning: constructing string from nullptr is undefined behaviour
+}
+
+std::string StringFromZero() {
+ return 0;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: constructing string from nullptr is undefined behaviour
}
void Valid() {
@@ -53,4 +63,5 @@ void Valid() {
std::wstring wstr(4, L'x');
std::string s1("test", 4);
std::string s2("test", 3);
+ std::string s3("test");
}
diff --git a/test/clang-tidy/bugprone-use-after-move.cpp b/test/clang-tidy/bugprone-use-after-move.cpp
index 59dcb90c..dd37aec6 100644
--- a/test/clang-tidy/bugprone-use-after-move.cpp
+++ b/test/clang-tidy/bugprone-use-after-move.cpp
@@ -244,6 +244,19 @@ void standardSmartPtr() {
std::move(ptr);
ptr.get();
}
+ // Make sure we treat references to smart pointers correctly.
+ {
+ std::unique_ptr<A> ptr;
+ std::unique_ptr<A>& ref_to_ptr = ptr;
+ std::move(ref_to_ptr);
+ ref_to_ptr.get();
+ }
+ {
+ std::unique_ptr<A> ptr;
+ std::unique_ptr<A>&& rvalue_ref_to_ptr = std::move(ptr);
+ std::move(rvalue_ref_to_ptr);
+ rvalue_ref_to_ptr.get();
+ }
// We don't give any special treatment to types that are called "unique_ptr"
// or "shared_ptr" but are not in the "::std" namespace.
{
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/fuchsia-overloaded-operator.cpp b/test/clang-tidy/fuchsia-overloaded-operator.cpp
index be65a329..7f7a36e8 100644
--- a/test/clang-tidy/fuchsia-overloaded-operator.cpp
+++ b/test/clang-tidy/fuchsia-overloaded-operator.cpp
@@ -19,3 +19,5 @@ A operator-(const A &A1, const A &A2);
void operator delete(void*, void*) throw();
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: overloading 'operator delete' is disallowed
+
+auto x = []{};
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-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-nodiscard-clang-unused.cpp b/test/clang-tidy/modernize-use-nodiscard-clang-unused.cpp
new file mode 100644
index 00000000..0951e611
--- /dev/null
+++ b/test/clang-tidy/modernize-use-nodiscard-clang-unused.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s modernize-use-nodiscard %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-nodiscard.ReplacementString, value: '[[clang::warn_unused_result]]'}]}" \
+// RUN: -- -std=c++11
+
+class Foo
+{
+public:
+ bool f1() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f1' should be marked {{\[\[clang::warn_unused_result\]\]}} [modernize-use-nodiscard]
+ // CHECK-FIXES: {{\[\[clang::warn_unused_result\]\]}} bool f1() const;
+
+ bool f2(int) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f2' should be marked {{\[\[clang::warn_unused_result\]\]}} [modernize-use-nodiscard]
+ // CHECK-FIXES: {{\[\[clang::warn_unused_result\]\]}} bool f2(int) const;
+
+ bool f3(const int &) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' should be marked {{\[\[clang::warn_unused_result\]\]}} [modernize-use-nodiscard]
+ // CHECK-FIXES: {{\[\[clang::warn_unused_result\]\]}} bool f3(const int &) const;
+
+ bool f4(void) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f4' should be marked {{\[\[clang::warn_unused_result\]\]}} [modernize-use-nodiscard]
+ // CHECK-FIXES: {{\[\[clang::warn_unused_result\]\]}} bool f4(void) const;
+
+};
+
diff --git a/test/clang-tidy/modernize-use-nodiscard-cxx11.cpp b/test/clang-tidy/modernize-use-nodiscard-cxx11.cpp
new file mode 100644
index 00000000..cbf0cead
--- /dev/null
+++ b/test/clang-tidy/modernize-use-nodiscard-cxx11.cpp
@@ -0,0 +1,24 @@
+// RUN: %check_clang_tidy %s modernize-use-nodiscard %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-nodiscard.ReplacementString, value: '__attribute__((warn_unused_result))'}]}" \
+// RUN: -- -std=c++11
+
+class Foo
+{
+public:
+ bool f1() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f1' should be marked __attribute__((warn_unused_result)) [modernize-use-nodiscard]
+ // CHECK-FIXES: __attribute__((warn_unused_result)) bool f1() const;
+
+ bool f2(int) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f2' should be marked __attribute__((warn_unused_result)) [modernize-use-nodiscard]
+ // CHECK-FIXES: __attribute__((warn_unused_result)) bool f2(int) const;
+
+ bool f3(const int &) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' should be marked __attribute__((warn_unused_result)) [modernize-use-nodiscard]
+ // CHECK-FIXES: __attribute__((warn_unused_result)) bool f3(const int &) const;
+
+ bool f4(void) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f4' should be marked __attribute__((warn_unused_result)) [modernize-use-nodiscard]
+ // CHECK-FIXES: __attribute__((warn_unused_result)) bool f4(void) const;
+};
+
diff --git a/test/clang-tidy/modernize-use-nodiscard-gcc-unused.cpp b/test/clang-tidy/modernize-use-nodiscard-gcc-unused.cpp
new file mode 100644
index 00000000..54b808ed
--- /dev/null
+++ b/test/clang-tidy/modernize-use-nodiscard-gcc-unused.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s modernize-use-nodiscard %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-nodiscard.ReplacementString, value: '[[gcc::warn_unused_result]]'}]}" \
+// RUN: -- -std=c++11
+
+class Foo
+{
+public:
+ bool f1() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f1' should be marked {{\[\[gcc::warn_unused_result\]\]}} [modernize-use-nodiscard]
+ // CHECK-FIXES: {{\[\[gcc::warn_unused_result\]\]}} bool f1() const;
+
+ bool f2(int) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f2' should be marked {{\[\[gcc::warn_unused_result\]\]}} [modernize-use-nodiscard]
+ // CHECK-FIXES: {{\[\[gcc::warn_unused_result\]\]}} bool f2(int) const;
+
+ bool f3(const int &) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' should be marked {{\[\[gcc::warn_unused_result\]\]}} [modernize-use-nodiscard]
+ // CHECK-FIXES: {{\[\[gcc::warn_unused_result\]\]}} bool f3(const int &) const;
+
+ bool f4(void) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f4' should be marked {{\[\[gcc::warn_unused_result\]\]}} [modernize-use-nodiscard]
+ // CHECK-FIXES: {{\[\[gcc::warn_unused_result\]\]}} bool f4(void) const;
+
+};
+
diff --git a/test/clang-tidy/modernize-use-nodiscard-no-macro-inscope-cxx11.cpp b/test/clang-tidy/modernize-use-nodiscard-no-macro-inscope-cxx11.cpp
new file mode 100644
index 00000000..0564a133
--- /dev/null
+++ b/test/clang-tidy/modernize-use-nodiscard-no-macro-inscope-cxx11.cpp
@@ -0,0 +1,13 @@
+// RUN: %check_clang_tidy %s modernize-use-nodiscard %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-nodiscard.ReplacementString, value: 'CUSTOM_NO_DISCARD'}]}" -- -std=c++11
+
+// As if the macro was not defined.
+// #define CUSTOM_NO_DISCARD __attribute_((warn_unused_result))
+
+class Foo
+{
+public:
+ bool f1() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f1' should be marked CUSTOM_NO_DISCARD [modernize-use-nodiscard]
+};
+
diff --git a/test/clang-tidy/modernize-use-nodiscard-no-macro.cpp b/test/clang-tidy/modernize-use-nodiscard-no-macro.cpp
new file mode 100644
index 00000000..7898b6ed
--- /dev/null
+++ b/test/clang-tidy/modernize-use-nodiscard-no-macro.cpp
@@ -0,0 +1,22 @@
+// RUN: %check_clang_tidy %s modernize-use-nodiscard %t -- -- -std=c++17
+
+class Foo
+{
+public:
+ bool f1() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f1' should be marked {{\[\[nodiscard\]\]}} [modernize-use-nodiscard]
+ // CHECK-FIXES: {{\[\[nodiscard\]\]}} bool f1() const;
+
+ bool f2(int) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f2' should be marked {{\[\[nodiscard\]\]}} [modernize-use-nodiscard]
+ // CHECK-FIXES: {{\[\[nodiscard\]\]}} bool f2(int) const;
+
+ bool f3(const int &) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' should be marked {{\[\[nodiscard\]\]}} [modernize-use-nodiscard]
+ // CHECK-FIXES: {{\[\[nodiscard\]\]}} bool f3(const int &) const;
+
+ bool f4(void) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f4' should be marked {{\[\[nodiscard\]\]}} [modernize-use-nodiscard]
+ // CHECK-FIXES: {{\[\[nodiscard\]\]}} bool f4(void) const;
+
+};
diff --git a/test/clang-tidy/modernize-use-nodiscard.cpp b/test/clang-tidy/modernize-use-nodiscard.cpp
new file mode 100644
index 00000000..a571f096
--- /dev/null
+++ b/test/clang-tidy/modernize-use-nodiscard.cpp
@@ -0,0 +1,262 @@
+// RUN: %check_clang_tidy %s modernize-use-nodiscard %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-nodiscard.ReplacementString, value: 'NO_DISCARD'}]}" \
+// RUN: -- -std=c++17
+
+namespace std {
+template <class>
+class function;
+class string {};
+}
+
+namespace boost {
+template <class>
+class function;
+}
+
+#define MUST_USE_RESULT __attribute__((warn_unused_result))
+#define NO_DISCARD [[nodiscard]]
+#define NO_RETURN [[noreturn]]
+
+#define BOOLEAN_FUNC bool f23() const
+
+typedef unsigned my_unsigned;
+typedef unsigned &my_unsigned_reference;
+typedef const unsigned &my_unsigned_const_reference;
+
+class Foo {
+public:
+ using size_type = unsigned;
+
+ bool f1() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f1' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD bool f1() const;
+
+ bool f2(int) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f2' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD bool f2(int) const;
+
+ bool f3(const int &) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD bool f3(const int &) const;
+
+ bool f4(void) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f4' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD bool f4(void) const;
+
+ // negative tests
+
+ void f5() const;
+
+ bool f6();
+
+ bool f7(int &);
+
+ bool f8(int &) const;
+
+ bool f9(int *) const;
+
+ bool f10(const int &, int &) const;
+
+ NO_DISCARD bool f12() const;
+
+ MUST_USE_RESULT bool f13() const;
+
+ [[nodiscard]] bool f11() const;
+
+ [[clang::warn_unused_result]] bool f11a() const;
+
+ [[gnu::warn_unused_result]] bool f11b() const;
+
+ bool _f20() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function '_f20' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD bool _f20() const;
+
+ NO_RETURN bool f21() const;
+
+ ~Foo();
+
+ bool operator+=(int) const;
+
+ // extra keywords (virtual,inline,const) on return type
+
+ virtual bool f14() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f14' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD virtual bool f14() const;
+
+ const bool f15() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f15' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD const bool f15() const;
+
+ inline const bool f16() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f16' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD inline const bool f16() const;
+
+ inline const std::string &f45() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f45' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD inline const std::string &f45() const;
+
+ inline virtual const bool f17() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f17' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD inline virtual const bool f17() const;
+
+ // inline with body
+ bool f18() const
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f18' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD bool f18() const
+ {
+ return true;
+ }
+
+ bool f19() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f19' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD bool f19() const;
+
+ BOOLEAN_FUNC;
+
+ bool f24(size_type) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f24' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD bool f24(size_type) const;
+
+ bool f28(my_unsigned) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f28' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD bool f28(my_unsigned) const;
+
+ bool f29(my_unsigned_reference) const;
+
+ bool f30(my_unsigned_const_reference) const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f30' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD bool f30(my_unsigned_const_reference) const;
+
+ template <class F>
+ F f37(F a, F b) const;
+
+ template <class F>
+ bool f38(F a) const;
+
+ bool f39(const std::function<bool()> &predicate) const;
+
+ bool f39a(std::function<bool()> predicate) const;
+
+ bool f39b(const std::function<bool()> predicate) const;
+
+ bool f45(const boost::function<bool()> &predicate) const;
+
+ bool f45a(boost::function<bool()> predicate) const;
+
+ bool f45b(const boost::function<bool()> predicate) const;
+
+ // Do not add ``[[nodiscard]]`` to parameter packs.
+ template <class... Args>
+ bool ParameterPack(Args... args) const;
+
+ template <typename... Targs>
+ bool ParameterPack2(Targs... Fargs) const;
+
+ // Do not add ``[[nodiscard]]`` to variadic functions.
+ bool VariadicFunctionTest(const int &, ...) const;
+
+ // Do not add ``[[nodiscard]]`` to non constant static functions.
+ static bool not_empty();
+
+ // Do not add ``[[nodiscard]]`` to conversion functions.
+ // explicit operator bool() const { return true; }
+};
+
+// Do not add ``[[nodiscard]]`` to Lambda.
+const auto nonConstReferenceType = [] {
+ return true;
+};
+
+auto lambda1 = [](int a, int b) { return a < b; };
+auto lambda1a = [](int a) { return a; };
+auto lambda1b = []() { return true;};
+
+auto get_functor = [](bool check) {
+ return [&](const std::string& sr)->std::string {
+ if(check){
+ return std::string();
+ }
+ return std::string();
+ };
+};
+
+// Do not add ``[[nodiscard]]`` to function definition.
+bool Foo::f19() const {
+ return true;
+}
+
+template <class T>
+class Bar {
+public:
+ using value_type = T;
+ using reference = value_type &;
+ using const_reference = const value_type &;
+
+ // Do not add ``[[nodiscard]]`` to non explicit conversion functions.
+ operator bool() const { return true; }
+
+ bool empty() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'empty' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD bool empty() const;
+
+ // we cannot assume that the template parameter isn't a pointer
+ bool f25(value_type) const;
+
+ bool f27(reference) const;
+
+ typename T::value_type f35() const;
+
+ T f34() const;
+
+ bool f31(T) const;
+
+ bool f33(T &) const;
+
+ bool f26(const_reference) const;
+
+ bool f32(const T &) const;
+};
+
+template <typename _Tp, int cn>
+class Vec {
+public:
+ Vec(_Tp v0, _Tp v1); //!< 2-element vector constructor
+
+ Vec cross(const Vec &v) const;
+
+ template <typename T2>
+ operator Vec<T2, cn>() const;
+};
+
+template <class T>
+class Bar2 {
+public:
+ typedef T value_type;
+ typedef value_type &reference;
+ typedef const value_type &const_reference;
+
+ // we cannot assume that the template parameter isn't a pointer
+ bool f40(value_type) const;
+
+ bool f41(reference) const;
+
+ value_type f42() const;
+
+ typename T::value_type f43() const;
+
+ bool f44(const_reference) const;
+};
+
+template <class T>
+bool Bar<T>::empty() const {
+ return true;
+}
+
+// don't mark typical ``[[nodiscard]]`` candidates if the class
+// has mutable member variables
+class MutableExample {
+ mutable bool m_isempty;
+
+public:
+ bool empty() const;
+};
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-redundant-preprocessor-ifdef.cpp b/test/clang-tidy/readability-redundant-preprocessor-ifdef.cpp
new file mode 100644
index 00000000..72b608b1
--- /dev/null
+++ b/test/clang-tidy/readability-redundant-preprocessor-ifdef.cpp
@@ -0,0 +1,36 @@
+// RUN: %check_clang_tidy %s readability-redundant-preprocessor %t -- -- -DFOO
+
+// Positive testing.
+#ifdef FOO
+// CHECK-NOTES: [[@LINE+1]]:2: warning: nested redundant #ifdef; consider removing it [readability-redundant-preprocessor]
+#ifdef FOO
+// CHECK-NOTES: [[@LINE-3]]:2: note: previous #ifdef was here
+void f();
+#endif
+#endif
+
+// Positive testing of inverted condition.
+#ifdef FOO
+// CHECK-NOTES: [[@LINE+1]]:2: warning: nested redundant #ifndef; consider removing it [readability-redundant-preprocessor]
+#ifndef FOO
+// CHECK-NOTES: [[@LINE-3]]:2: note: previous #ifdef was here
+void f2();
+#endif
+#endif
+
+// Negative testing.
+#ifdef BAR
+void g();
+#endif
+
+#ifdef FOO
+#ifdef BAR
+void h();
+#endif
+#endif
+
+#ifdef FOO
+#ifndef BAR
+void i();
+#endif
+#endif
diff --git a/test/clang-tidy/readability-redundant-preprocessor.cpp b/test/clang-tidy/readability-redundant-preprocessor.cpp
new file mode 100644
index 00000000..6cffd8f4
--- /dev/null
+++ b/test/clang-tidy/readability-redundant-preprocessor.cpp
@@ -0,0 +1,84 @@
+// RUN: %check_clang_tidy %s readability-redundant-preprocessor %t -- -- -I %S
+
+// Positive testing.
+#ifndef FOO
+// CHECK-NOTES: [[@LINE+1]]:2: warning: nested redundant #ifndef; consider removing it [readability-redundant-preprocessor]
+#ifndef FOO
+// CHECK-NOTES: [[@LINE-3]]:2: note: previous #ifndef was here
+void f();
+#endif
+#endif
+
+// Positive testing of inverted condition.
+#ifndef FOO
+// CHECK-NOTES: [[@LINE+1]]:2: warning: nested redundant #ifdef; consider removing it [readability-redundant-preprocessor]
+#ifdef FOO
+// CHECK-NOTES: [[@LINE-3]]:2: note: previous #ifndef was here
+void f2();
+#endif
+#endif
+
+// Negative testing.
+#include "readability-redundant-preprocessor.h"
+
+#ifndef BAR
+void g();
+#endif
+
+#ifndef FOO
+#ifndef BAR
+void h();
+#endif
+#endif
+
+#ifndef FOO
+#ifdef BAR
+void i();
+#endif
+#endif
+
+// Positive #if testing.
+#define FOO 4
+
+#if FOO == 4
+// CHECK-NOTES: [[@LINE+1]]:2: warning: nested redundant #if; consider removing it [readability-redundant-preprocessor]
+#if FOO == 4
+// CHECK-NOTES: [[@LINE-3]]:2: note: previous #if was here
+void j();
+#endif
+#endif
+
+#if FOO == 3 + 1
+// CHECK-NOTES: [[@LINE+1]]:2: warning: nested redundant #if; consider removing it [readability-redundant-preprocessor]
+#if FOO == 3 + 1
+// CHECK-NOTES: [[@LINE-3]]:2: note: previous #if was here
+void j();
+#endif
+#endif
+
+#if FOO == \
+ 4
+// CHECK-NOTES: [[@LINE+1]]:2: warning: nested redundant #if; consider removing it [readability-redundant-preprocessor]
+#if FOO == \
+ 4
+// CHECK-NOTES: [[@LINE-5]]:2: note: previous #if was here
+void j();
+#endif
+#endif
+
+// Negative #if testing.
+#define BAR 4
+
+#if FOO == 4
+#if BAR == 4
+void k();
+#endif
+#endif
+
+#if FOO == \
+ 4
+#if BAR == \
+ 5
+void k();
+#endif
+#endif
diff --git a/test/clang-tidy/readability-redundant-preprocessor.h b/test/clang-tidy/readability-redundant-preprocessor.h
new file mode 100644
index 00000000..dfe5f973
--- /dev/null
+++ b/test/clang-tidy/readability-redundant-preprocessor.h
@@ -0,0 +1,5 @@
+#ifndef FOO
+#ifndef FOO // this would warn, but not in a header
+void f();
+#endif
+#endif
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/readability-uppercase-literal-suffix-integer-macro.cpp b/test/clang-tidy/readability-uppercase-literal-suffix-integer-macro.cpp
index 9668a9ea..40a9c265 100644
--- a/test/clang-tidy/readability-uppercase-literal-suffix-integer-macro.cpp
+++ b/test/clang-tidy/readability-uppercase-literal-suffix-integer-macro.cpp
@@ -1,4 +1,6 @@
-// RUN: %check_clang_tidy %s readability-uppercase-literal-suffix %t -- -- -I %S
+// RUN: %check_clang_tidy %s readability-uppercase-literal-suffix %t -- \
+// RUN: -config="{CheckOptions: [{key: readability-uppercase-literal-suffix.IgnoreMacros, value: 0}]}" \
+// RUN: -- -I %S
void macros() {
#define INMACRO(X) 1.f
diff --git a/test/clang-tidy/readability-uppercase-literal-suffix-integer.cpp b/test/clang-tidy/readability-uppercase-literal-suffix-integer.cpp
index c4fcd18a..a6f38a8e 100644
--- a/test/clang-tidy/readability-uppercase-literal-suffix-integer.cpp
+++ b/test/clang-tidy/readability-uppercase-literal-suffix-integer.cpp
@@ -235,6 +235,10 @@ void macros() {
// CHECK-FIXES: static constexpr auto m0 = PASSTHROUGH(1U);
static_assert(is_same<decltype(m0), const unsigned int>::value, "");
static_assert(m0 == 1, "");
+
+ // This location is inside a macro, no warning on that by default.
+#define MACRO 1u
+ int foo = MACRO;
}
// Check that user-defined literals do not cause any diags.
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/Inputs/background-index/definition.jsonrpc b/test/clangd/Inputs/background-index/definition.jsonrpc
index 89d50482..933e7791 100644
--- a/test/clangd/Inputs/background-index/definition.jsonrpc
+++ b/test/clangd/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/background-index.test b/test/clangd/background-index.test
index 7826ef27..34c419ac 100644
--- a/test/clangd/background-index.test
+++ b/test/clangd/background-index.test
@@ -16,6 +16,5 @@
# RUN: ls %t/.clangd-index/foo.cpp.*.idx
# Test the index is read from disk: delete code and restart clangd.
-# FIXME: This test currently fails as we don't read the index yet.
# RUN: rm %t/foo.cpp
-# RUN: clangd -background-index -lit-test < %t/definition.jsonrpc | not FileCheck %t/definition.jsonrpc
+# RUN: clangd -background-index -lit-test < %t/definition.jsonrpc | FileCheck %t/definition.jsonrpc
diff --git a/test/clangd/completion-auto-trigger.test b/test/clangd/completion-auto-trigger.test
new file mode 100644
index 00000000..db3cc537
--- /dev/null
+++ b/test/clangd/completion-auto-trigger.test
@@ -0,0 +1,106 @@
+# 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":"namespace ns { int ns_member; } struct vector { int size; static int default_capacity; };\nvoid test(vector *a, vector *b) {\n if (a > b) {} \n a->size = 10;\n\n a ? a : b;\n ns::ns_member = 10;\n}"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":2,"character":9},"context":{"triggerKind":2,"triggerCharacter":">"}}}
+# CHECK: "error": {
+# CHECK-NEXT: "code": -32001,
+# CHECK-NEXT: "message": "ignored auto-triggered completion, preceding char did not match"
+# CHECK-NEXT: },
+# CHECK-NEXT: "id": 1,
+---
+{"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":3,"character":5},"context":{"triggerKind":2,"triggerCharacter":">"}}}
+# CHECK: "id": 2,
+# CHECK-NEXT: "jsonrpc": "2.0"
+# CHECK-NEXT: "result": {
+# CHECK-NEXT: "isIncomplete": false,
+# CHECK-NEXT: "items": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "detail": "int",
+# CHECK-NEXT: "filterText": "size",
+# CHECK-NEXT: "insertText": "size",
+# CHECK-NEXT: "insertTextFormat": 1,
+# CHECK-NEXT: "kind": 5,
+# CHECK-NEXT: "label": " size",
+# CHECK-NEXT: "sortText": "3eacccccsize",
+# CHECK-NEXT: "textEdit": {
+# CHECK-NEXT: "newText": "size",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 5,
+# CHECK-NEXT: "line": 3
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 5,
+# CHECK-NEXT: "line": 3
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: {
+# CHECK-NEXT: "detail": "int",
+# CHECK-NEXT: "filterText": "default_capacity",
+# CHECK-NEXT: "insertText": "default_capacity",
+# CHECK-NEXT: "insertTextFormat": 1,
+# CHECK-NEXT: "kind": 10,
+# CHECK-NEXT: "label": " default_capacity",
+# CHECK-NEXT: "sortText": "3fd70a3ddefault_capacity",
+# CHECK-NEXT: "textEdit": {
+# CHECK-NEXT: "newText": "default_capacity",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 5,
+# CHECK-NEXT: "line": 3
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 5,
+# CHECK-NEXT: "line": 3
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
+---
+{"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":5,"character":9},"context":{"triggerKind":2,"triggerCharacter":":"}}}
+# CHECK: "error": {
+# CHECK-NEXT: "code": -32001,
+# CHECK-NEXT: "message": "ignored auto-triggered completion, preceding char did not match"
+# CHECK-NEXT: },
+# CHECK-NEXT: "id": 3,
+---
+{"jsonrpc":"2.0","id":4,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":6,"character":6},"context":{"triggerKind":2,"triggerCharacter":":"}}}
+---
+# CHECK: "id": 4,
+# CHECK-NEXT: "jsonrpc": "2.0"
+# CHECK-NEXT: "result": {
+# CHECK-NEXT: "isIncomplete": false,
+# CHECK-NEXT: "items": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "detail": "int",
+# CHECK-NEXT: "filterText": "ns_member",
+# CHECK-NEXT: "insertText": "ns_member",
+# CHECK-NEXT: "insertTextFormat": 1,
+# CHECK-NEXT: "kind": 6,
+# CHECK-NEXT: "label": " ns_member",
+# CHECK-NEXT: "sortText": "3f2cccccns_member",
+# CHECK-NEXT: "textEdit": {
+# CHECK-NEXT: "newText": "ns_member",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 6,
+# CHECK-NEXT: "line": 6
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 6,
+# CHECK-NEXT: "line": 6
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
+{"jsonrpc":"2.0","id":5,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/test/clangd/diagnostic-category.test b/test/clangd/diagnostic-category.test
index 440afbb1..08ad581c 100644
--- a/test/clangd/diagnostic-category.test
+++ b/test/clangd/diagnostic-category.test
@@ -7,7 +7,7 @@
# 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: "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,
diff --git a/test/clangd/diagnostics.test b/test/clangd/diagnostics.test
index a191c082..ae662693 100644
--- a/test/clangd/diagnostics.test
+++ b/test/clangd/diagnostics.test
@@ -6,7 +6,7 @@
# CHECK-NEXT: "params": {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
-# CHECK-NEXT: "message": "Return type of 'main' is not 'int'",
+# CHECK-NEXT: "message": "Return type of 'main' is not 'int' (fix available)",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 4,
diff --git a/test/clangd/did-change-configuration-params.test b/test/clangd/did-change-configuration-params.test
index 51b4a874..5c216014 100644
--- a/test/clangd/did-change-configuration-params.test
+++ b/test/clangd/did-change-configuration-params.test
@@ -24,7 +24,7 @@
# CHECK-NEXT: "params": {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
-# CHECK-NEXT: "message": "Variable 'i' is uninitialized when used here",
+# CHECK-NEXT: "message": "Variable 'i' is uninitialized when used here (fix available)",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 28,
diff --git a/test/clangd/execute-command.test b/test/clangd/execute-command.test
index 85d4b9b8..3c9c45f8 100644
--- a/test/clangd/execute-command.test
+++ b/test/clangd/execute-command.test
@@ -6,7 +6,7 @@
# CHECK-NEXT: "params": {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
-# CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses",
+# 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,
diff --git a/test/clangd/filestatus.test b/test/clangd/filestatus.test
new file mode 100644
index 00000000..c485939b
--- /dev/null
+++ b/test/clangd/filestatus.test
@@ -0,0 +1,13 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"initializationOptions":{"clangdFileStatus": true},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"int x; int y = x;"}}}
+# CHECK: "method": "textDocument/clangd.fileStatus",
+# CHECK-NEXT: "params": {
+# CHECK-NEXT: "state": "parsing includes",
+# CHECK-NEXT: "uri": "{{.*}}/main.cpp"
+# CHECK-NEXT: }
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/test/clangd/fixits-codeaction.test b/test/clangd/fixits-codeaction.test
index 97dd4ff2..47d75655 100644
--- a/test/clangd/fixits-codeaction.test
+++ b/test/clangd/fixits-codeaction.test
@@ -6,7 +6,7 @@
# CHECK-NEXT: "params": {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
-# CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses",
+# 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,
@@ -23,14 +23,14 @@
# 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": [
# CHECK-NEXT: {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
-# CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses",
+# 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,
@@ -82,7 +82,7 @@
# CHECK-NEXT: {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
-# CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses",
+# 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,
diff --git a/test/clangd/fixits-command.test b/test/clangd/fixits-command.test
index 67f70dbe..da508321 100644
--- a/test/clangd/fixits-command.test
+++ b/test/clangd/fixits-command.test
@@ -6,7 +6,7 @@
# CHECK-NEXT: "params": {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
-# CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses",
+# 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,
@@ -23,7 +23,7 @@
# 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 +92,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/test/clangd/fixits-embed-in-diagnostic.test
index f1aa1cfe..560fca6b 100644
--- a/test/clangd/fixits-embed-in-diagnostic.test
+++ b/test/clangd/fixits-embed-in-diagnostic.test
@@ -31,7 +31,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,
diff --git a/test/clangd/initialize-params.test b/test/clangd/initialize-params.test
index 62f7b41a..b9fec65e 100644
--- a/test/clangd/initialize-params.test
+++ b/test/clangd/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,
diff --git a/test/clangd/tweaks-format.test b/test/clangd/tweaks-format.test
new file mode 100644
index 00000000..8fe7a112
--- /dev/null
+++ b/test/clangd/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/test/clangd/xpc/initialize.test b/test/clangd/xpc/initialize.test
new file mode 100644
index 00000000..44bef65b
--- /dev/null
+++ b/test/clangd/xpc/initialize.test
@@ -0,0 +1,10 @@
+# RUN: clangd-xpc-test-client < %s | FileCheck %s
+# REQUIRES: clangd-xpc-support
+
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootUri":"test:///workspace","capabilities":{},"trace":"off"}}
+# CHECK: {"id":0,"jsonrpc":"2.0","result":{"capabilities"
+
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+# CHECK: {"id":3,"jsonrpc":"2.0","result":null}
+
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/test/clangd/xrefs.test b/test/clangd/xrefs.test
index 58ca44cb..128c97ff 100644
--- a/test/clangd/xrefs.test
+++ b/test/clangd/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/test/lit.cfg b/test/lit.cfg
index 8f8ebaf9..ed7bb83c 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -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,6 +115,10 @@ 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.in
index bf33b151..d71ca188 100644
--- a/test/lit.site.cfg.in
+++ b/test/lit.site.cfg.in
@@ -11,6 +11,7 @@ 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.
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..8e7ce887 100644
--- a/test/pp-trace/pp-trace-conditional.cpp
+++ b/test/pp-trace/pp-trace-conditional.cpp
@@ -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-macro.cpp b/test/pp-trace/pp-trace-macro.cpp
index e6ba761d..1202aa20 100644
--- a/test/pp-trace/pp-trace-macro.cpp
+++ b/test/pp-trace/pp-trace-macro.cpp
@@ -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/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/change-namespace/ChangeNamespaceTests.cpp b/unittests/change-namespace/ChangeNamespaceTests.cpp
index 4008600b..d66fede2 100644
--- a/unittests/change-namespace/ChangeNamespaceTests.cpp
+++ b/unittests/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-apply-replacements/ApplyReplacementsTest.cpp b/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp
index 85aaebf7..c532a37a 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
//
//===----------------------------------------------------------------------===//
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/clang-move/ClangMoveTests.cpp b/unittests/clang-move/ClangMoveTests.cpp
index 97c7ce07..0385a799 100644
--- a/unittests/clang-move/ClangMoveTests.cpp
+++ b/unittests/clang-move/ClangMoveTests.cpp
@@ -1,9 +1,8 @@
//===-- ClangMoveTest.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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clang-query/QueryEngineTest.cpp b/unittests/clang-query/QueryEngineTest.cpp
index c1d67a17..df3be130 100644
--- a/unittests/clang-query/QueryEngineTest.cpp
+++ b/unittests/clang-query/QueryEngineTest.cpp
@@ -1,9 +1,8 @@
//===---- QueryTest.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/ClangTidyTest.h b/unittests/clang-tidy/ClangTidyTest.h
index 32bb53c1..ca886e42 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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/clang-tidy/IncludeInserterTest.cpp b/unittests/clang-tidy/IncludeInserterTest.cpp
index 7a70f66a..bf9a3505 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
//
//===----------------------------------------------------------------------===//
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
index a53f70ca..7a3f94ac 100644
--- a/unittests/clangd/Annotations.cpp
+++ b/unittests/clangd/Annotations.cpp
@@ -1,35 +1,33 @@
//===--- 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.
+// Part of the LLVM Project, under the Apache 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"
-using namespace llvm;
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, StringRef Code) {
+static void require(bool Assertion, const char *Msg, llvm::StringRef Code) {
if (!Assertion) {
- errs() << "Annotated testcase: " << Msg << "\n" << Code << "\n";
+ llvm::errs() << "Annotated testcase: " << Msg << "\n" << Code << "\n";
llvm_unreachable("Annotated testcase assertion failed!");
}
}
-Annotations::Annotations(StringRef Text) {
+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);
};
- Optional<StringRef> Name;
- SmallVector<std::pair<StringRef, Position>, 8> OpenRanges;
+ llvm::Optional<llvm::StringRef> Name;
+ llvm::SmallVector<std::pair<llvm::StringRef, Position>, 8> OpenRanges;
Code.reserve(Text.size());
while (!Text.empty()) {
@@ -52,7 +50,7 @@ Annotations::Annotations(StringRef Text) {
continue;
}
if (Text.consume_front("$")) {
- Name = Text.take_while(isAlnum);
+ Name = Text.take_while(llvm::isAlnum);
Text = Text.drop_front(Name->size());
continue;
}
@@ -63,23 +61,23 @@ Annotations::Annotations(StringRef Text) {
Require(OpenRanges.empty(), "unmatched [[");
}
-Position Annotations::point(StringRef Name) const {
+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(StringRef Name) const {
+std::vector<Position> Annotations::points(llvm::StringRef Name) const {
auto P = Points.lookup(Name);
return {P.begin(), P.end()};
}
-Range Annotations::range(StringRef Name) const {
+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(StringRef Name) const {
+std::vector<Range> Annotations::ranges(llvm::StringRef Name) const {
auto R = Ranges.lookup(Name);
return {R.begin(), R.end()};
}
diff --git a/unittests/clangd/Annotations.h b/unittests/clangd/Annotations.h
index 4d787c25..07f79b55 100644
--- a/unittests/clangd/Annotations.h
+++ b/unittests/clangd/Annotations.h
@@ -1,9 +1,8 @@
//===--- 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.
+// Part of the LLVM Project, under the Apache License v2.0 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/BackgroundIndexTests.cpp b/unittests/clangd/BackgroundIndexTests.cpp
index 377e5014..09a117db 100644
--- a/unittests/clangd/BackgroundIndexTests.cpp
+++ b/unittests/clangd/BackgroundIndexTests.cpp
@@ -9,11 +9,11 @@
using testing::_;
using testing::AllOf;
+using testing::Contains;
using testing::ElementsAre;
using testing::Not;
using testing::UnorderedElementsAre;
-using namespace llvm;
namespace clang {
namespace clangd {
@@ -76,7 +76,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 +113,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;
@@ -125,7 +125,7 @@ TEST_F(BackgroundIndexTest, IndexTwoFiles) {
ASSERT_TRUE(Idx.blockUntilIdleForTest());
EXPECT_THAT(
runFuzzyFind(Idx, ""),
- UnorderedElementsAre(Named("common"), Named("A_CC"),
+ UnorderedElementsAre(Named("common"), Named("A_CC"), Named("g"),
AllOf(Named("f_b"), Declared(), Not(Defined()))));
Cmd.Filename = testPath("root/B.cc");
@@ -135,7 +135,7 @@ TEST_F(BackgroundIndexTest, IndexTwoFiles) {
ASSERT_TRUE(Idx.blockUntilIdleForTest());
// B_CC is dropped as we don't collect symbols from A.h in this compilation.
EXPECT_THAT(runFuzzyFind(Idx, ""),
- UnorderedElementsAre(Named("common"), Named("A_CC"),
+ UnorderedElementsAre(Named("common"), Named("A_CC"), Named("g"),
AllOf(Named("f_b"), Declared(), Defined())));
auto Syms = runFuzzyFind(Idx, "common");
@@ -147,7 +147,7 @@ TEST_F(BackgroundIndexTest, IndexTwoFiles) {
FileURI("unittest:///root/B.cc")}));
}
-TEST_F(BackgroundIndexTest, ShardStorageWriteTest) {
+TEST_F(BackgroundIndexTest, ShardStorageTest) {
MockFSProvider FS;
FS.Files[testPath("root/A.h")] = R"cpp(
void common();
@@ -168,7 +168,7 @@ TEST_F(BackgroundIndexTest, ShardStorageWriteTest) {
// 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());
@@ -176,6 +176,16 @@ TEST_F(BackgroundIndexTest, ShardStorageWriteTest) {
EXPECT_EQ(CacheHits, 0U);
EXPECT_EQ(Storage.size(), 2U);
+ {
+ OverlayCDB CDB(/*Base=*/nullptr);
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
+ [&](llvm::StringRef) { return &MSS; });
+ CDB.setCompileCommand(testPath("root"), Cmd);
+ ASSERT_TRUE(Idx.blockUntilIdleForTest());
+ }
+ EXPECT_EQ(CacheHits, 2U); // Check both A.cc and A.h loaded from cache.
+ EXPECT_EQ(Storage.size(), 2U);
+
auto ShardHeader = MSS.loadShard(testPath("root/A.h"));
EXPECT_NE(ShardHeader, nullptr);
EXPECT_THAT(
@@ -188,7 +198,7 @@ TEST_F(BackgroundIndexTest, ShardStorageWriteTest) {
auto ShardSource = MSS.loadShard(testPath("root/A.cc"));
EXPECT_NE(ShardSource, nullptr);
- EXPECT_THAT(*ShardSource->Symbols, UnorderedElementsAre());
+ EXPECT_THAT(*ShardSource->Symbols, UnorderedElementsAre(Named("g")));
EXPECT_THAT(*ShardSource->Refs, RefsAre({FileURI("unittest:///root/A.cc")}));
}
@@ -214,7 +224,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());
@@ -243,15 +253,17 @@ TEST_F(BackgroundIndexTest, DirectIncludesTest) {
EmptyIncludeNode());
}
-TEST_F(BackgroundIndexTest, PeriodicalIndex) {
+// FIXME: figure out the right timeouts or rewrite to not use the timeouts and
+// re-enable.
+TEST_F(BackgroundIndexTest, DISABLED_PeriodicalIndex) {
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; },
- /*BuildIndexPeriodMs=*/100);
+ Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ /*BuildIndexPeriodMs=*/500);
FS.Files[testPath("root/A.cc")] = "#include \"A.h\"";
@@ -263,7 +275,7 @@ TEST_F(BackgroundIndexTest, PeriodicalIndex) {
ASSERT_TRUE(Idx.blockUntilIdleForTest());
EXPECT_THAT(runFuzzyFind(Idx, ""), ElementsAre());
- std::this_thread::sleep_for(std::chrono::milliseconds(150));
+ std::this_thread::sleep_for(std::chrono::milliseconds(1000));
EXPECT_THAT(runFuzzyFind(Idx, ""), ElementsAre(Named("X")));
FS.Files[testPath("root/A.h")] = "class Y {};";
@@ -273,9 +285,148 @@ TEST_F(BackgroundIndexTest, PeriodicalIndex) {
ASSERT_TRUE(Idx.blockUntilIdleForTest());
EXPECT_THAT(runFuzzyFind(Idx, ""), ElementsAre(Named("X")));
- std::this_thread::sleep_for(std::chrono::milliseconds(150));
+ std::this_thread::sleep_for(std::chrono::milliseconds(1000));
EXPECT_THAT(runFuzzyFind(Idx, ""), ElementsAre(Named("Y")));
}
+TEST_F(BackgroundIndexTest, ShardStorageLoad) {
+ MockFSProvider FS;
+ FS.Files[testPath("root/A.h")] = R"cpp(
+ void common();
+ void f_b();
+ class A_CC {};
+ )cpp";
+ FS.Files[testPath("root/A.cc")] =
+ "#include \"A.h\"\nvoid g() { (void)common; }";
+
+ llvm::StringMap<std::string> Storage;
+ size_t CacheHits = 0;
+ MemoryShardStorage MSS(Storage, CacheHits);
+
+ tooling::CompileCommand Cmd;
+ Cmd.Filename = testPath("root/A.cc");
+ Cmd.Directory = testPath("root");
+ Cmd.CommandLine = {"clang++", testPath("root/A.cc")};
+ // 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,
+ [&](llvm::StringRef) { return &MSS; });
+ CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
+ ASSERT_TRUE(Idx.blockUntilIdleForTest());
+ }
+
+ // Change header.
+ FS.Files[testPath("root/A.h")] = R"cpp(
+ void common();
+ void f_b();
+ class A_CC {};
+ class A_CCnew {};
+ )cpp";
+ {
+ OverlayCDB CDB(/*Base=*/nullptr);
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
+ [&](llvm::StringRef) { return &MSS; });
+ CDB.setCompileCommand(testPath("root"), Cmd);
+ ASSERT_TRUE(Idx.blockUntilIdleForTest());
+ }
+ EXPECT_EQ(CacheHits, 2U); // Check both A.cc and A.h loaded from cache.
+
+ // Check if the new symbol has arrived.
+ auto ShardHeader = MSS.loadShard(testPath("root/A.h"));
+ EXPECT_NE(ShardHeader, nullptr);
+ EXPECT_THAT(*ShardHeader->Symbols, Contains(Named("A_CCnew")));
+
+ // Change source.
+ FS.Files[testPath("root/A.cc")] =
+ "#include \"A.h\"\nvoid g() { (void)common; }\nvoid f_b() {}";
+ {
+ CacheHits = 0;
+ OverlayCDB CDB(/*Base=*/nullptr);
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
+ [&](llvm::StringRef) { return &MSS; });
+ CDB.setCompileCommand(testPath("root"), Cmd);
+ ASSERT_TRUE(Idx.blockUntilIdleForTest());
+ }
+ EXPECT_EQ(CacheHits, 2U); // Check both A.cc and A.h loaded from cache.
+
+ // Check if the new symbol has arrived.
+ ShardHeader = MSS.loadShard(testPath("root/A.h"));
+ EXPECT_NE(ShardHeader, nullptr);
+ EXPECT_THAT(*ShardHeader->Symbols, Contains(Named("A_CCnew")));
+ auto ShardSource = MSS.loadShard(testPath("root/A.cc"));
+ EXPECT_NE(ShardSource, nullptr);
+ EXPECT_THAT(*ShardSource->Symbols,
+ Contains(AllOf(Named("f_b"), Declared(), Defined())));
+}
+
+TEST_F(BackgroundIndexTest, ShardStorageEmptyFile) {
+ MockFSProvider FS;
+ FS.Files[testPath("root/A.h")] = R"cpp(
+ void common();
+ void f_b();
+ class A_CC {};
+ )cpp";
+ FS.Files[testPath("root/B.h")] = R"cpp(
+ #include "A.h"
+ )cpp";
+ FS.Files[testPath("root/A.cc")] =
+ "#include \"B.h\"\nvoid g() { (void)common; }";
+
+ llvm::StringMap<std::string> Storage;
+ size_t CacheHits = 0;
+ MemoryShardStorage MSS(Storage, CacheHits);
+
+ tooling::CompileCommand Cmd;
+ Cmd.Filename = testPath("root/A.cc");
+ Cmd.Directory = testPath("root");
+ Cmd.CommandLine = {"clang++", testPath("root/A.cc")};
+ // Check that A.cc, A.h and B.h has been stored.
+ {
+ OverlayCDB CDB(/*Base=*/nullptr);
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
+ [&](llvm::StringRef) { return &MSS; });
+ CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
+ ASSERT_TRUE(Idx.blockUntilIdleForTest());
+ }
+ EXPECT_THAT(Storage.keys(),
+ UnorderedElementsAre(testPath("root/A.cc"), testPath("root/A.h"),
+ testPath("root/B.h")));
+ auto ShardHeader = MSS.loadShard(testPath("root/B.h"));
+ EXPECT_NE(ShardHeader, nullptr);
+ EXPECT_TRUE(ShardHeader->Symbols->empty());
+
+ // Check that A.cc, A.h and B.h has been loaded.
+ {
+ CacheHits = 0;
+ OverlayCDB CDB(/*Base=*/nullptr);
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
+ [&](llvm::StringRef) { return &MSS; });
+ CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
+ ASSERT_TRUE(Idx.blockUntilIdleForTest());
+ }
+ EXPECT_EQ(CacheHits, 3U);
+
+ // Update B.h to contain some symbols.
+ FS.Files[testPath("root/B.h")] = R"cpp(
+ #include "A.h"
+ void new_func();
+ )cpp";
+ // Check that B.h has been stored with new contents.
+ {
+ CacheHits = 0;
+ OverlayCDB CDB(/*Base=*/nullptr);
+ BackgroundIndex Idx(Context::empty(), FS, CDB,
+ [&](llvm::StringRef) { return &MSS; });
+ CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
+ ASSERT_TRUE(Idx.blockUntilIdleForTest());
+ }
+ EXPECT_EQ(CacheHits, 3U);
+ ShardHeader = MSS.loadShard(testPath("root/B.h"));
+ EXPECT_NE(ShardHeader, nullptr);
+ EXPECT_THAT(*ShardHeader->Symbols,
+ Contains(AllOf(Named("new_func"), Declared(), Not(Defined()))));
+}
+
} // namespace clangd
} // namespace clang
diff --git a/unittests/clangd/CMakeLists.txt b/unittests/clangd/CMakeLists.txt
index f47b1fc9..deae9ceb 100644
--- a/unittests/clangd/CMakeLists.txt
+++ b/unittests/clangd/CMakeLists.txt
@@ -18,6 +18,7 @@ add_extra_unittest(ClangdTests
CodeCompletionStringsTests.cpp
ContextTests.cpp
DexTests.cpp
+ DiagnosticsTests.cpp
DraftStoreTests.cpp
ExpectedTypeTest.cpp
FileDistanceTests.cpp
@@ -33,6 +34,7 @@ add_extra_unittest(ClangdTests
JSONTransportTests.cpp
QualityTests.cpp
RIFFTests.cpp
+ SelectionTests.cpp
SerializationTests.cpp
SourceCodeTests.cpp
SymbolCollectorTests.cpp
@@ -44,8 +46,11 @@ add_extra_unittest(ClangdTests
TestTU.cpp
ThreadingTests.cpp
TraceTests.cpp
+ TweakTests.cpp
URITests.cpp
XRefsTests.cpp
+
+ $<TARGET_OBJECTS:obj.clangDaemonTweaks>
)
target_link_libraries(ClangdTests
@@ -59,9 +64,14 @@ target_link_libraries(ClangdTests
clangLex
clangSema
clangSerialization
+ clangTidy
clangTooling
clangToolingCore
clangToolingInclusions
LLVMSupport
LLVMTestingSupport
)
+
+if (CLANGD_BUILD_XPC)
+ add_subdirectory(xpc)
+endif ()
diff --git a/unittests/clangd/CancellationTests.cpp b/unittests/clangd/CancellationTests.cpp
index 45a01700..611ce07d 100644
--- a/unittests/clangd/CancellationTests.cpp
+++ b/unittests/clangd/CancellationTests.cpp
@@ -8,7 +8,6 @@
#include <memory>
#include <thread>
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -22,7 +21,7 @@ TEST(CancellationTest, CancellationTest) {
}
TEST(CancellationTest, CancelerDiesContextLives) {
- Optional<WithContext> ContextWithCancellation;
+ llvm::Optional<WithContext> ContextWithCancellation;
{
auto Task = cancelableTask();
ContextWithCancellation.emplace(std::move(Task.first));
diff --git a/unittests/clangd/ClangdTests.cpp b/unittests/clangd/ClangdTests.cpp
index 7f954fd8..6454ec8a 100644
--- a/unittests/clangd/ClangdTests.cpp
+++ b/unittests/clangd/ClangdTests.cpp
@@ -1,15 +1,15 @@
//===-- 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"
@@ -30,7 +30,6 @@
#include <thread>
#include <vector>
-using namespace llvm;
namespace clang {
namespace clangd {
@@ -44,8 +43,9 @@ 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) {
@@ -109,14 +109,14 @@ public:
private:
mutable std::mutex Mutex;
- StringMap<bool> LastDiagsHadError;
+ llvm::StringMap<bool> LastDiagsHadError;
};
/// Replaces all patterns of the form 0x123abc with spaces
std::string replacePtrsInDump(std::string const &Dump) {
- Regex RE("0x[0-9a-fA-F]+");
- SmallVector<StringRef, 1> Matches;
- StringRef Pending = Dump;
+ llvm::Regex RE("0x[0-9a-fA-F]+");
+ llvm::SmallVector<llvm::StringRef, 1> Matches;
+ llvm::StringRef Pending = Dump;
std::string Result;
while (RE.match(Pending, &Matches)) {
@@ -139,8 +139,8 @@ std::string dumpASTWithoutMemoryLocs(ClangdServer &Server, PathRef File) {
class ClangdVFSTest : public ::testing::Test {
protected:
std::string parseSourceAndDumpAST(
- PathRef SourceFileRelPath, StringRef SourceContents,
- std::vector<std::pair<PathRef, StringRef>> ExtraFiles = {},
+ PathRef SourceFileRelPath, llvm::StringRef SourceContents,
+ std::vector<std::pair<PathRef, llvm::StringRef>> ExtraFiles = {},
bool ExpectErrors = false) {
MockFSProvider FS;
ErrorCheckingDiagConsumer DiagConsumer;
@@ -269,7 +269,7 @@ int b = a;
TEST_F(ClangdVFSTest, PropagatesContexts) {
static Key<int> Secret;
struct FSProvider : public FileSystemProvider {
- IntrusiveRefCntPtr<vfs::FileSystem> getFileSystem() const override {
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> getFileSystem() const override {
Got = Context::current().getExisting(Secret);
return buildTestFS({});
}
@@ -313,19 +313,19 @@ TEST_F(ClangdVFSTest, SearchLibDir) {
// A lib dir for gcc installation
SmallString<64> LibDir("/randomusr/lib/gcc/x86_64-linux-gnu");
- sys::path::append(LibDir, Version);
+ llvm::sys::path::append(LibDir, Version);
// Put crtbegin.o into LibDir/64 to trick clang into thinking there's a gcc
// installation there.
SmallString<64> DummyLibFile;
- sys::path::append(DummyLibFile, LibDir, "64", "crtbegin.o");
+ llvm::sys::path::append(DummyLibFile, LibDir, "64", "crtbegin.o");
FS.Files[DummyLibFile] = "";
SmallString<64> IncludeDir("/randomusr/include/c++");
- sys::path::append(IncludeDir, Version);
+ llvm::sys::path::append(IncludeDir, Version);
SmallString<64> StringPath;
- sys::path::append(StringPath, IncludeDir, "string");
+ llvm::sys::path::append(StringPath, IncludeDir, "string");
FS.Files[StringPath] = "class mock_string {};";
auto FooCpp = testPath("foo.cpp");
@@ -459,10 +459,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();
@@ -475,10 +474,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) {
@@ -533,7 +531,7 @@ 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
@@ -598,7 +596,7 @@ int d;
void onDiagnosticsReady(PathRef File,
std::vector<Diag> Diagnostics) override {
- StringRef FileIndexStr = sys::path::stem(File);
+ StringRef FileIndexStr = llvm::sys::path::stem(File);
ASSERT_TRUE(FileIndexStr.consume_front("Foo"));
unsigned long FileIndex = std::stoul(FileIndexStr.str());
@@ -718,7 +716,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)
@@ -728,13 +726,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(
@@ -976,28 +974,28 @@ TEST_F(ClangdVFSTest, ChangedHeaderFromISystem) {
TEST(ClangdTests, PreambleVFSStatCache) {
class ListenStatsFSProvider : public FileSystemProvider {
public:
- ListenStatsFSProvider(StringMap<unsigned> &CountStats)
+ ListenStatsFSProvider(llvm::StringMap<unsigned> &CountStats)
: CountStats(CountStats) {}
- IntrusiveRefCntPtr<vfs::FileSystem> getFileSystem() const override {
- class ListenStatVFS : public vfs::ProxyFileSystem {
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> getFileSystem() const override {
+ class ListenStatVFS : public llvm::vfs::ProxyFileSystem {
public:
- ListenStatVFS(IntrusiveRefCntPtr<vfs::FileSystem> FS,
- StringMap<unsigned> &CountStats)
+ ListenStatVFS(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
+ llvm::StringMap<unsigned> &CountStats)
: ProxyFileSystem(std::move(FS)), CountStats(CountStats) {}
- ErrorOr<std::unique_ptr<vfs::File>>
+ llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
openFileForRead(const Twine &Path) override {
- ++CountStats[sys::path::filename(Path.str())];
+ ++CountStats[llvm::sys::path::filename(Path.str())];
return ProxyFileSystem::openFileForRead(Path);
}
- ErrorOr<vfs::Status> status(const Twine &Path) override {
- ++CountStats[sys::path::filename(Path.str())];
+ llvm::ErrorOr<llvm::vfs::Status> status(const Twine &Path) override {
+ ++CountStats[llvm::sys::path::filename(Path.str())];
return ProxyFileSystem::status(Path);
}
private:
- StringMap<unsigned> &CountStats;
+ llvm::StringMap<unsigned> &CountStats;
};
return IntrusiveRefCntPtr<ListenStatVFS>(
@@ -1005,11 +1003,11 @@ TEST(ClangdTests, PreambleVFSStatCache) {
}
// If relative paths are used, they are resolved with testPath().
- StringMap<std::string> Files;
- StringMap<unsigned> &CountStats;
+ llvm::StringMap<std::string> Files;
+ llvm::StringMap<unsigned> &CountStats;
};
- StringMap<unsigned> CountStats;
+ llvm::StringMap<unsigned> CountStats;
ListenStatsFSProvider FS(CountStats);
ErrorCheckingDiagConsumer DiagConsumer;
MockCompilationDatabase CDB;
@@ -1038,6 +1036,28 @@ 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>");
+}
+
} // namespace
} // namespace clangd
} // namespace clang
diff --git a/unittests/clangd/ClangdUnitTests.cpp b/unittests/clangd/ClangdUnitTests.cpp
index 4b31677a..dd3fc6dd 100644
--- a/unittests/clangd/ClangdUnitTests.cpp
+++ b/unittests/clangd/ClangdUnitTests.cpp
@@ -1,9 +1,8 @@
//===-- 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.
+// Part of the LLVM Project, under the Apache 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,266 +14,11 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace llvm;
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 " + to_string(Range) + " = [" + Message + "]") {
- return arg.Range == Range && arg.Message == Message;
-}
-
-MATCHER_P3(Fix, Range, Replacement, Message,
- "Fix " + 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 " + 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 " + 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(
diff --git a/unittests/clangd/CodeCompleteTests.cpp b/unittests/clangd/CodeCompleteTests.cpp
index d29e8b5a..3a0082a2 100644
--- a/unittests/clangd/CodeCompleteTests.cpp
+++ b/unittests/clangd/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,6 +16,7 @@
#include "SourceCode.h"
#include "SyncAPI.h"
#include "TestFS.h"
+#include "TestIndex.h"
#include "index/MemIndex.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "llvm/Support/Error.h"
@@ -24,11 +24,11 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
+using ::llvm::Failed;
using ::testing::AllOf;
using ::testing::Contains;
using ::testing::Each;
@@ -87,7 +87,7 @@ std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol> Symbols) {
return MemIndex::build(std::move(Slab).build(), RefSlab());
}
-CodeCompleteResult completions(ClangdServer &Server, StringRef TestCode,
+CodeCompleteResult completions(ClangdServer &Server, llvm::StringRef TestCode,
Position point,
std::vector<Symbol> IndexSymbols = {},
clangd::CodeCompleteOptions Opts = {}) {
@@ -100,11 +100,12 @@ CodeCompleteResult completions(ClangdServer &Server, StringRef TestCode,
auto File = testPath("foo.cpp");
runAddDocument(Server, File, TestCode);
- auto CompletionList = cantFail(runCodeComplete(Server, File, point, Opts));
+ auto CompletionList =
+ llvm::cantFail(runCodeComplete(Server, File, point, Opts));
return CompletionList;
}
-CodeCompleteResult completions(ClangdServer &Server, StringRef Text,
+CodeCompleteResult completions(ClangdServer &Server, llvm::StringRef Text,
std::vector<Symbol> IndexSymbols = {},
clangd::CodeCompleteOptions Opts = {},
PathRef FilePath = "foo.cpp") {
@@ -119,13 +120,13 @@ CodeCompleteResult completions(ClangdServer &Server, StringRef Text,
Annotations Test(Text);
runAddDocument(Server, File, Test.code());
auto CompletionList =
- cantFail(runCodeComplete(Server, File, Test.point(), Opts));
+ llvm::cantFail(runCodeComplete(Server, File, Test.point(), Opts));
return CompletionList;
}
// Builds a server and runs code completion.
// If IndexSymbols is non-empty, an index will be built and passed to opts.
-CodeCompleteResult completions(StringRef Text,
+CodeCompleteResult completions(llvm::StringRef Text,
std::vector<Symbol> IndexSymbols = {},
clangd::CodeCompleteOptions Opts = {},
PathRef FilePath = "foo.cpp") {
@@ -137,51 +138,6 @@ CodeCompleteResult completions(StringRef Text,
FilePath);
}
-std::string replace(StringRef Haystack, StringRef Needle, StringRef Repl) {
- std::string Result;
- raw_string_ostream OS(Result);
- std::pair<StringRef, 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(StringRef QName, index::SymbolKind Kind, 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 == 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 += 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(StringRef Name) { // Assumes the function has no args.
- return sym(Name, index::SymbolKind::Function, "@F@\\0#"); // no args
-}
-Symbol cls(StringRef Name) {
- return sym(Name, index::SymbolKind::Class, "@S@\\0");
-}
-Symbol var(StringRef Name) {
- return sym(Name, index::SymbolKind::Variable, "@\\0");
-}
-Symbol ns(StringRef Name) {
- return sym(Name, index::SymbolKind::Namespace, "@N@\\0");
-}
Symbol withReferences(int N, Symbol S) {
S.References = N;
return S;
@@ -195,7 +151,7 @@ struct ClassWithMembers {
int AAA();
int BBB();
int CCC();
-}
+};
int main() { ClassWithMembers().^ }
)cpp",
/*IndexSymbols=*/{}, Opts);
@@ -516,7 +472,8 @@ TEST(CompletionTest, ScopedWithFilter) {
TEST(CompletionTest, ReferencesAffectRanking) {
auto Results = completions("int main() { abs^ }", {ns("absl"), func("absb")});
- EXPECT_THAT(Results.Completions, HasSubsequence(Named("absb"), Named("absl")));
+ EXPECT_THAT(Results.Completions,
+ HasSubsequence(Named("absb"), Named("absl")));
Results = completions("int main() { abs^ }",
{withReferences(10000, ns("absl")), func("absb")});
EXPECT_THAT(Results.Completions,
@@ -628,7 +585,7 @@ TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) {
R"cpp(
namespace ns {
class X;
- class Y {}
+ class Y {};
}
int main() { ns::^ }
)cpp",
@@ -651,7 +608,7 @@ TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
#include "bar.h"
namespace ns { int local; }
void f() { ns::^; }
- void f() { ns::preamble().$2^; }
+ void f2() { ns::preamble().$2^; }
)cpp");
runAddDocument(Server, File, Test.code());
clangd::CodeCompleteOptions Opts = {};
@@ -688,6 +645,36 @@ 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(
+ 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('"' + testPath("foo_header.h") + '"'),
+ InsertInclude())));
+}
+
TEST(CompletionTest, DynamicIndexMultiFile) {
MockFSProvider FS;
MockCompilationDatabase CDB;
@@ -861,7 +848,7 @@ TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {
EXPECT_TRUE(Results.Completions.empty());
}
-SignatureHelp signatures(StringRef Text, Position Point,
+SignatureHelp signatures(llvm::StringRef Text, Position Point,
std::vector<Symbol> IndexSymbols = {}) {
std::unique_ptr<SymbolIndex> Index;
if (!IndexSymbols.empty())
@@ -876,10 +863,10 @@ SignatureHelp signatures(StringRef Text, Position Point,
ClangdServer Server(CDB, FS, DiagConsumer, Opts);
auto File = testPath("foo.cpp");
runAddDocument(Server, File, Text);
- return cantFail(runSignatureHelp(Server, File, Point));
+ return llvm::cantFail(runSignatureHelp(Server, File, Point));
}
-SignatureHelp signatures(StringRef Text,
+SignatureHelp signatures(llvm::StringRef Text,
std::vector<Symbol> IndexSymbols = {}) {
Annotations Test(Text);
return signatures(Test.code(), Test.point(), std::move(IndexSymbols));
@@ -997,18 +984,19 @@ TEST(SignatureHelpTest, OpeningParen) {
class IndexRequestCollector : public SymbolIndex {
public:
- bool fuzzyFind(const FuzzyFindRequest &Req,
- function_ref<void(const Symbol &)> Callback) const override {
+ bool
+ fuzzyFind(const FuzzyFindRequest &Req,
+ llvm::function_ref<void(const Symbol &)> Callback) const override {
std::lock_guard<std::mutex> Lock(Mut);
Requests.push_back(Req);
return true;
}
void lookup(const LookupRequest &,
- function_ref<void(const Symbol &)>) const override {}
+ llvm::function_ref<void(const Symbol &)>) const override {}
void refs(const RefsRequest &,
- function_ref<void(const Ref &)>) const override {}
+ llvm::function_ref<void(const Ref &)>) const override {}
// This is incorrect, but IndexRequestCollector is not an actual index and it
// isn't used in production code.
@@ -1027,7 +1015,7 @@ private:
mutable std::vector<FuzzyFindRequest> Requests;
};
-std::vector<FuzzyFindRequest> captureIndexRequests(StringRef Code) {
+std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code) {
clangd::CodeCompleteOptions Opts;
IndexRequestCollector Requests;
Opts.Index = &Requests;
@@ -1662,7 +1650,8 @@ TEST(CompletionTest, CompletionTokenRange) {
auto Results = completions(Server, TestCode.code(), TestCode.point());
EXPECT_EQ(Results.Completions.size(), 1u);
- EXPECT_THAT(Results.Completions.front().CompletionTokenRange, TestCode.range());
+ EXPECT_THAT(Results.Completions.front().CompletionTokenRange,
+ TestCode.range());
}
}
@@ -1787,6 +1776,37 @@ TEST(SignatureHelpTest, IndexDocumentation) {
SigDoc("Doc from sema"))));
}
+TEST(SignatureHelpTest, DynamicIndexDocumentation) {
+ MockFSProvider FS;
+ MockCompilationDatabase CDB;
+ IgnoreDiagnostics DiagConsumer;
+ ClangdServer::Options Opts = ClangdServer::optsForTest();
+ Opts.BuildDynamicSymbolIndex = true;
+ ClangdServer Server(CDB, FS, DiagConsumer, Opts);
+
+ FS.Files[testPath("foo.h")] = R"cpp(
+ struct Foo {
+ // Member doc
+ int foo();
+ };
+ )cpp";
+ Annotations FileContent(R"cpp(
+ #include "foo.h"
+ void test() {
+ Foo f;
+ f.foo(^);
+ }
+ )cpp");
+ auto File = testPath("test.cpp");
+ Server.addDocument(File, FileContent.code());
+ // Wait for the dynamic index being built.
+ ASSERT_TRUE(Server.blockUntilIdleForTest());
+ EXPECT_THAT(
+ llvm::cantFail(runSignatureHelp(Server, File, FileContent.point()))
+ .signatures,
+ ElementsAre(AllOf(Sig("foo() -> int", {}), SigDoc("Member doc"))));
+}
+
TEST(CompletionTest, CompletionFunctionArgsDisabled) {
CodeCompleteOptions Opts;
Opts.EnableSnippets = true;
@@ -1927,7 +1947,7 @@ TEST(CompletionTest, EnableSpeculativeIndexRequest) {
namespace ns1 { int abc; }
namespace ns2 { int abc; }
void f() { ns1::ab$1^; ns1::ab$2^; }
- void f() { ns2::ab$3^; }
+ void f2() { ns2::ab$3^; }
)cpp");
runAddDocument(Server, File, Test.code());
clangd::CodeCompleteOptions Opts = {};
@@ -2095,11 +2115,10 @@ TEST(SignatureHelpTest, ConstructorInitializeFields) {
A a_elem;
};
)cpp");
- EXPECT_THAT(Results.signatures, UnorderedElementsAre(
- Sig("A(int)", {"int"}),
- Sig("A(A &&)", {"A &&"}),
- Sig("A(const A &)", {"const A &"})
- ));
+ EXPECT_THAT(Results.signatures,
+ UnorderedElementsAre(Sig("A(int)", {"int"}),
+ Sig("A(A &&)", {"A &&"}),
+ Sig("A(const A &)", {"const A &"})));
}
{
const auto Results = signatures(R"cpp(
@@ -2115,11 +2134,10 @@ TEST(SignatureHelpTest, ConstructorInitializeFields) {
C c_elem;
};
)cpp");
- EXPECT_THAT(Results.signatures, UnorderedElementsAre(
- Sig("A(int)", {"int"}),
- Sig("A(A &&)", {"A &&"}),
- Sig("A(const A &)", {"const A &"})
- ));
+ EXPECT_THAT(Results.signatures,
+ UnorderedElementsAre(Sig("A(int)", {"int"}),
+ Sig("A(A &&)", {"A &&"}),
+ Sig("A(const A &)", {"const A &"})));
}
}
@@ -2134,10 +2152,9 @@ TEST(CompletionTest, IncludedCompletionKinds) {
IgnoreDiagnostics DiagConsumer;
ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
auto Results = completions(Server,
- R"cpp(
+ R"cpp(
#include "^"
- )cpp"
- );
+ )cpp");
EXPECT_THAT(Results.Completions,
AllOf(Has("sub/", CompletionItemKind::Folder),
Has("bar.h\"", CompletionItemKind::File)));
@@ -2147,8 +2164,7 @@ TEST(CompletionTest, NoCrashAtNonAlphaIncludeHeader) {
auto Results = completions(
R"cpp(
#include "./^"
- )cpp"
- );
+ )cpp");
EXPECT_TRUE(Results.Completions.empty());
}
@@ -2221,9 +2237,8 @@ TEST(CompletionTest, ObjectiveCMethodNoArguments) {
@end
Foo *foo = [Foo new]; int y = [foo v^]
)objc",
- /*IndexSymbols=*/{},
- /*Opts=*/{},
- "Foo.m");
+ /*IndexSymbols=*/{},
+ /*Opts=*/{}, "Foo.m");
auto C = Results.Completions;
EXPECT_THAT(C, ElementsAre(Named("value")));
@@ -2240,9 +2255,8 @@ TEST(CompletionTest, ObjectiveCMethodOneArgument) {
@end
Foo *foo = [Foo new]; int y = [foo v^]
)objc",
- /*IndexSymbols=*/{},
- /*Opts=*/{},
- "Foo.m");
+ /*IndexSymbols=*/{},
+ /*Opts=*/{}, "Foo.m");
auto C = Results.Completions;
EXPECT_THAT(C, ElementsAre(Named("valueForCharacter:")));
@@ -2259,17 +2273,16 @@ TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromBeginning) {
@end
id val = [Foo foo^]
)objc",
- /*IndexSymbols=*/{},
- /*Opts=*/{},
- "Foo.m");
+ /*IndexSymbols=*/{},
+ /*Opts=*/{}, "Foo.m");
auto C = Results.Completions;
EXPECT_THAT(C, ElementsAre(Named("fooWithValue:")));
EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method)));
EXPECT_THAT(C, ElementsAre(ReturnType("id")));
EXPECT_THAT(C, ElementsAre(Signature("(int) fooey:(unsigned int)")));
- EXPECT_THAT(C,
- ElementsAre(SnippetSuffix("${1:(int)} fooey:${2:(unsigned int)}")));
+ EXPECT_THAT(
+ C, ElementsAre(SnippetSuffix("${1:(int)} fooey:${2:(unsigned int)}")));
}
TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
@@ -2279,9 +2292,8 @@ TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
@end
id val = [Foo fooWithValue:10 f^]
)objc",
- /*IndexSymbols=*/{},
- /*Opts=*/{},
- "Foo.m");
+ /*IndexSymbols=*/{},
+ /*Opts=*/{}, "Foo.m");
auto C = Results.Completions;
EXPECT_THAT(C, ElementsAre(Named("fooey:")));
@@ -2291,6 +2303,17 @@ 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")));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
diff --git a/unittests/clangd/CodeCompletionStringsTests.cpp b/unittests/clangd/CodeCompletionStringsTests.cpp
index eab35e14..43429c86 100644
--- a/unittests/clangd/CodeCompletionStringsTests.cpp
+++ b/unittests/clangd/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/unittests/clangd/ContextTests.cpp
index d5cb3ce6..d760f4eb 100644
--- a/unittests/clangd/ContextTests.cpp
+++ b/unittests/clangd/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/unittests/clangd/DexTests.cpp
index 72657304..cd52daac 100644
--- a/unittests/clangd/DexTests.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -27,7 +26,6 @@ using ::testing::AnyOf;
using ::testing::ElementsAre;
using ::testing::UnorderedElementsAre;
-using namespace llvm;
namespace clang {
namespace clangd {
namespace dex {
@@ -248,17 +246,17 @@ TEST(DexIterators, StringRepresentation) {
// No token given, prints full posting list.
auto I1 = L1.iterator();
- EXPECT_EQ(to_string(*I1), "[1 3 5]");
+ EXPECT_EQ(llvm::to_string(*I1), "[1 3 5]");
// Token given, uses token's string representation.
Token Tok(Token::Kind::Trigram, "L2");
auto I2 = L1.iterator(&Tok);
- EXPECT_EQ(to_string(*I2), "T=L2");
+ EXPECT_EQ(llvm::to_string(*I2), "T=L2");
auto Tree = C.limit(C.intersect(move(I1), move(I2)), 10);
// AND reorders its children, we don't care which order it prints.
- EXPECT_THAT(to_string(*Tree), AnyOf("(LIMIT 10 (& [1 3 5] T=L2))",
- "(LIMIT 10 (& T=L2 [1 3 5]))"));
+ EXPECT_THAT(llvm::to_string(*Tree), AnyOf("(LIMIT 10 (& [1 3 5] T=L2))",
+ "(LIMIT 10 (& T=L2 [1 3 5]))"));
}
TEST(DexIterators, Limit) {
@@ -323,27 +321,28 @@ TEST(DexIterators, Optimizations) {
const PostingList L3{3};
// empty and/or yield true/false
- EXPECT_EQ(to_string(*C.intersect()), "true");
- EXPECT_EQ(to_string(*C.unionOf()), "false");
+ EXPECT_EQ(llvm::to_string(*C.intersect()), "true");
+ EXPECT_EQ(llvm::to_string(*C.unionOf()), "false");
// true/false inside and/or short-circuit
- EXPECT_EQ(to_string(*C.intersect(L1.iterator(), C.all())), "[1]");
- EXPECT_EQ(to_string(*C.intersect(L1.iterator(), C.none())), "false");
+ EXPECT_EQ(llvm::to_string(*C.intersect(L1.iterator(), C.all())), "[1]");
+ EXPECT_EQ(llvm::to_string(*C.intersect(L1.iterator(), C.none())), "false");
// Not optimized to avoid breaking boosts.
- EXPECT_EQ(to_string(*C.unionOf(L1.iterator(), C.all())), "(| [1] true)");
- EXPECT_EQ(to_string(*C.unionOf(L1.iterator(), C.none())), "[1]");
+ EXPECT_EQ(llvm::to_string(*C.unionOf(L1.iterator(), C.all())),
+ "(| [1] true)");
+ EXPECT_EQ(llvm::to_string(*C.unionOf(L1.iterator(), C.none())), "[1]");
// and/or nested inside and/or are flattened
- EXPECT_EQ(to_string(*C.intersect(L1.iterator(),
- C.intersect(L1.iterator(), L1.iterator()))),
+ EXPECT_EQ(llvm::to_string(*C.intersect(
+ L1.iterator(), C.intersect(L1.iterator(), L1.iterator()))),
"(& [1] [1] [1])");
- EXPECT_EQ(to_string(*C.unionOf(L1.iterator(),
- C.unionOf(L2.iterator(), L3.iterator()))),
+ EXPECT_EQ(llvm::to_string(*C.unionOf(
+ L1.iterator(), C.unionOf(L2.iterator(), L3.iterator()))),
"(| [1] [2] [3])");
// optimizations combine over multiple levels
- EXPECT_EQ(to_string(*C.intersect(C.intersect(L1.iterator(), C.intersect()),
- C.unionOf(C.all()))),
+ EXPECT_EQ(llvm::to_string(*C.intersect(
+ C.intersect(L1.iterator(), C.intersect()), C.unionOf(C.all()))),
"[1]");
}
@@ -657,9 +656,9 @@ TEST(DexTest, ProximityPathsBoosting) {
}
TEST(DexTests, Refs) {
- DenseMap<SymbolID, std::vector<Ref>> Refs;
+ llvm::DenseMap<SymbolID, std::vector<Ref>> Refs;
auto AddRef = [&](const Symbol &Sym, const char *Filename, RefKind Kind) {
- auto& SymbolRefs = Refs[Sym.ID];
+ auto &SymbolRefs = Refs[Sym.ID];
SymbolRefs.emplace_back();
SymbolRefs.back().Kind = Kind;
SymbolRefs.back().Location.FileURI = Filename;
@@ -667,18 +666,48 @@ TEST(DexTests, Refs) {
auto Foo = symbol("foo");
auto Bar = symbol("bar");
AddRef(Foo, "foo.h", RefKind::Declaration);
+ AddRef(Foo, "foo.cc", RefKind::Definition);
AddRef(Foo, "reffoo.h", RefKind::Reference);
AddRef(Bar, "bar.h", RefKind::Declaration);
- std::vector<std::string> Files;
RefsRequest Req;
Req.IDs.insert(Foo.ID);
Req.Filter = RefKind::Declaration | RefKind::Definition;
+
+ std::vector<std::string> Files;
+ Dex(std::vector<Symbol>{Foo, Bar}, Refs).refs(Req, [&](const Ref &R) {
+ Files.push_back(R.Location.FileURI);
+ });
+ EXPECT_THAT(Files, UnorderedElementsAre("foo.h", "foo.cc"));
+
+ Req.Limit = 1;
+ Files.clear();
Dex(std::vector<Symbol>{Foo, Bar}, Refs).refs(Req, [&](const Ref &R) {
Files.push_back(R.Location.FileURI);
});
+ 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"));
- EXPECT_THAT(Files, ElementsAre("foo.h"));
+ Req.PreferredTypes = {Sym2.Type};
+ EXPECT_THAT(match(I, Req), ElementsAre("t2"));
}
} // namespace
diff --git a/unittests/clangd/DiagnosticsTests.cpp b/unittests/clangd/DiagnosticsTests.cpp
new file mode 100644
index 00000000..d9c9dfc9
--- /dev/null
+++ b/unittests/clangd/DiagnosticsTests.cpp
@@ -0,0 +1,455 @@
+//===--- 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 "SourceCode.h"
+#include "TestIndex.h"
+#include "TestTU.h"
+#include "index/MemIndex.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 &> 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)) {
+ 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.
+ 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 [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 (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 =
+ 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())));
+}
+
+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;
+}
+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("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;
+ $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"))),
+ AllOf(Diag(Test.range("unqualified2"),
+ "use of undeclared identifier 'X'"),
+ WithFix(Fix(Test.range("insert"), "#include \"x.h\"\n",
+ "Add include \"x.h\" for symbol ns::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'")));
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
+
diff --git a/unittests/clangd/DraftStoreTests.cpp b/unittests/clangd/DraftStoreTests.cpp
index 44faa8bd..ba1007b2 100644
--- a/unittests/clangd/DraftStoreTests.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -13,29 +12,28 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
struct IncrementalTestStep {
- StringRef Src;
- StringRef Contents;
+ llvm::StringRef Src;
+ llvm::StringRef Contents;
};
-int rangeLength(StringRef Code, const Range &Rng) {
- Expected<size_t> Start = positionToOffset(Code, Rng.start);
- Expected<size_t> End = positionToOffset(Code, Rng.end);
+int rangeLength(llvm::StringRef Code, const Range &Rng) {
+ llvm::Expected<size_t> Start = positionToOffset(Code, Rng.start);
+ llvm::Expected<size_t> End = positionToOffset(Code, Rng.end);
assert(Start);
assert(End);
return *End - *Start;
}
/// Send the changes one by one to updateDraft, verify the intermediate results.
-void stepByStep(ArrayRef<IncrementalTestStep> Steps) {
+void stepByStep(llvm::ArrayRef<IncrementalTestStep> Steps) {
DraftStore DS;
Annotations InitialSrc(Steps.front().Src);
- constexpr StringLiteral Path("/hello.cpp");
+ constexpr llvm::StringLiteral Path("/hello.cpp");
// Set the initial content.
DS.addDraft(Path, InitialSrc.code());
@@ -43,14 +41,14 @@ void stepByStep(ArrayRef<IncrementalTestStep> Steps) {
for (size_t i = 1; i < Steps.size(); i++) {
Annotations SrcBefore(Steps[i - 1].Src);
Annotations SrcAfter(Steps[i].Src);
- StringRef Contents = Steps[i - 1].Contents;
+ llvm::StringRef Contents = Steps[i - 1].Contents;
TextDocumentContentChangeEvent Event{
SrcBefore.range(),
rangeLength(SrcBefore.code(), SrcBefore.range()),
Contents.str(),
};
- Expected<std::string> Result = DS.updateDraft(Path, {Event});
+ llvm::Expected<std::string> Result = DS.updateDraft(Path, {Event});
ASSERT_TRUE(!!Result);
EXPECT_EQ(*Result, SrcAfter.code());
EXPECT_EQ(*DS.getDraft(Path), SrcAfter.code());
@@ -58,16 +56,16 @@ void stepByStep(ArrayRef<IncrementalTestStep> Steps) {
}
/// Send all the changes at once to updateDraft, check only the final result.
-void allAtOnce(ArrayRef<IncrementalTestStep> Steps) {
+void allAtOnce(llvm::ArrayRef<IncrementalTestStep> Steps) {
DraftStore DS;
Annotations InitialSrc(Steps.front().Src);
Annotations FinalSrc(Steps.back().Src);
- constexpr StringLiteral Path("/hello.cpp");
+ constexpr llvm::StringLiteral Path("/hello.cpp");
std::vector<TextDocumentContentChangeEvent> Changes;
for (size_t i = 0; i < Steps.size() - 1; i++) {
Annotations Src(Steps[i].Src);
- StringRef Contents = Steps[i].Contents;
+ llvm::StringRef Contents = Steps[i].Contents;
Changes.push_back({
Src.range(),
@@ -79,9 +77,9 @@ void allAtOnce(ArrayRef<IncrementalTestStep> Steps) {
// Set the initial content.
DS.addDraft(Path, InitialSrc.code());
- Expected<std::string> Result = DS.updateDraft(Path, Changes);
+ llvm::Expected<std::string> Result = DS.updateDraft(Path, Changes);
- ASSERT_TRUE(!!Result) << toString(Result.takeError());
+ ASSERT_TRUE(!!Result) << llvm::toString(Result.takeError());
EXPECT_EQ(*Result, FinalSrc.code());
EXPECT_EQ(*DS.getDraft(Path), FinalSrc.code());
}
diff --git a/unittests/clangd/ExpectedTypeTest.cpp b/unittests/clangd/ExpectedTypeTest.cpp
index e739869e..d109c790 100644
--- a/unittests/clangd/ExpectedTypeTest.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -17,8 +16,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace llvm;
-
namespace clang {
namespace clangd {
namespace {
@@ -30,21 +27,21 @@ using ::testing::UnorderedElementsAreArray;
class ExpectedTypeConversionTest : public ::testing::Test {
protected:
- void build(StringRef Code) {
+ void build(llvm::StringRef Code) {
assert(!AST && "AST built twice");
AST = TestTU::withCode(Code).build();
}
- const ValueDecl *decl(StringRef Name) {
+ const ValueDecl *decl(llvm::StringRef Name) {
return &cast<ValueDecl>(findDecl(*AST, Name));
}
- QualType typeOf(StringRef Name) {
+ QualType typeOf(llvm::StringRef Name) {
return decl(Name)->getType().getCanonicalType();
}
/// An overload for convenience.
- Optional<OpaqueType> fromCompletionResult(const ValueDecl *D) {
+ llvm::Optional<OpaqueType> fromCompletionResult(const ValueDecl *D) {
return OpaqueType::fromCompletionResult(
ASTCtx(), CodeCompletionResult(D, CCP_Declaration));
}
@@ -54,7 +51,7 @@ protected:
using EquivClass = std::set<std::string>;
Matcher<std::map<std::string, EquivClass>>
- ClassesAre(ArrayRef<EquivClass> Classes) {
+ ClassesAre(llvm::ArrayRef<EquivClass> Classes) {
using MapEntry = std::map<std::string, EquivClass>::value_type;
std::vector<Matcher<MapEntry>> Elements;
@@ -67,9 +64,9 @@ protected:
// Groups \p Decls into equivalence classes based on the result of
// 'OpaqueType::fromCompletionResult'.
std::map<std::string, EquivClass>
- buildEquivClasses(ArrayRef<StringRef> DeclNames) {
+ buildEquivClasses(llvm::ArrayRef<llvm::StringRef> DeclNames) {
std::map<std::string, EquivClass> Classes;
- for (StringRef Name : DeclNames) {
+ for (llvm::StringRef Name : DeclNames) {
auto Type = OpaqueType::fromType(ASTCtx(), typeOf(Name));
Classes[Type->raw()].insert(Name);
}
@@ -80,7 +77,7 @@ protected:
private:
// Set after calling build().
- Optional<ParsedAST> AST;
+ llvm::Optional<ParsedAST> AST;
};
TEST_F(ExpectedTypeConversionTest, BasicTypes) {
diff --git a/unittests/clangd/FSTests.cpp b/unittests/clangd/FSTests.cpp
index 74dde3b2..044452ca 100644
--- a/unittests/clangd/FSTests.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -12,13 +11,12 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
TEST(FSTests, PreambleStatusCache) {
- StringMap<std::string> Files;
+ llvm::StringMap<std::string> Files;
Files["x"] = "";
Files["y"] = "";
Files["main"] = "";
@@ -36,9 +34,10 @@ TEST(FSTests, PreambleStatusCache) {
// Main file is not cached.
EXPECT_FALSE(StatCache.lookup(testPath("main")).hasValue());
- vfs::Status S("fake", sys::fs::UniqueID(0, 0),
- std::chrono::system_clock::now(), 0, 0, 1024,
- sys::fs::file_type::regular_file, sys::fs::all_all);
+ llvm::vfs::Status S("fake", llvm::sys::fs::UniqueID(0, 0),
+ std::chrono::system_clock::now(), 0, 0, 1024,
+ llvm::sys::fs::file_type::regular_file,
+ llvm::sys::fs::all_all);
StatCache.update(*FS, S);
auto ConsumeFS = StatCache.getConsumingFS(FS);
auto Cached = ConsumeFS->status(testPath("fake"));
diff --git a/unittests/clangd/FileDistanceTests.cpp b/unittests/clangd/FileDistanceTests.cpp
index 6d7d4777..30035829 100644
--- a/unittests/clangd/FileDistanceTests.cpp
+++ b/unittests/clangd/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/unittests/clangd/FileIndexTests.cpp
index cc5d260c..5667cb8f 100644
--- a/unittests/clangd/FileIndexTests.cpp
+++ b/unittests/clangd/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,6 +12,7 @@
#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"
@@ -31,7 +31,6 @@ using testing::ElementsAre;
using testing::IsEmpty;
using testing::Pair;
using testing::UnorderedElementsAre;
-using namespace llvm;
MATCHER_P(RefRange, Range, "") {
return std::make_tuple(arg.Location.Start.line(), arg.Location.Start.column(),
@@ -39,11 +38,13 @@ MATCHER_P(RefRange, Range, "") {
std::make_tuple(Range.start.line, Range.start.character,
Range.end.line, Range.end.character);
}
-MATCHER_P(FileURI, F, "") { return StringRef(arg.Location.FileURI) == F; }
+MATCHER_P(FileURI, F, "") { return llvm::StringRef(arg.Location.FileURI) == F; }
MATCHER_P(DeclURI, U, "") {
- return StringRef(arg.CanonicalDeclaration.FileURI) == U;
+ return llvm::StringRef(arg.CanonicalDeclaration.FileURI) == U;
+}
+MATCHER_P(DefURI, U, "") {
+ return llvm::StringRef(arg.Definition.FileURI) == U;
}
-MATCHER_P(DefURI, U, "") { return StringRef(arg.Definition.FileURI) == U; }
MATCHER_P(QName, N, "") { return (arg.Scope + arg.Name).str() == N; }
namespace clang {
@@ -54,7 +55,7 @@ RefsAre(std::vector<testing::Matcher<Ref>> Matchers) {
return ElementsAre(testing::Pair(_, UnorderedElementsAreArray(Matchers)));
}
-Symbol symbol(StringRef ID) {
+Symbol symbol(llvm::StringRef ID) {
Symbol Sym;
Sym.ID = SymbolID(ID);
Sym.Name = ID;
@@ -103,7 +104,7 @@ TEST(FileSymbolsTest, MergeOverlap) {
auto OneSymboSlab = [](Symbol Sym) {
SymbolSlab::Builder S;
S.insert(Sym);
- return make_unique<SymbolSlab>(std::move(S).build());
+ return llvm::make_unique<SymbolSlab>(std::move(S).build());
};
auto X1 = symbol("x");
X1.CanonicalDeclaration.FileURI = "file:///x1";
@@ -141,14 +142,14 @@ TEST(FileSymbolsTest, SnapshotAliveAfterRemove) {
}
// Adds Basename.cpp, which includes Basename.h, which contains Code.
-void update(FileIndex &M, StringRef Basename, StringRef Code) {
+void update(FileIndex &M, llvm::StringRef Basename, llvm::StringRef Code) {
TestTU File;
File.Filename = (Basename + ".cpp").str();
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) {
@@ -199,13 +200,49 @@ 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) {
+ FileIndex Index;
+ const std::string Header = R"cpp(
+ class Foo {};
+ )cpp";
+ auto MainFile = testPath("foo.cpp");
+ auto HeaderFile = testPath("algorithm");
+ std::vector<const char *> Cmd = {"clang", "-xc++", MainFile.c_str(),
+ "-include", HeaderFile.c_str()};
+ // Preparse ParseInputs.
+ ParseInputs PI;
+ PI.CompileCommand.Directory = testRoot();
+ PI.CompileCommand.Filename = MainFile;
+ PI.CompileCommand.CommandLine = {Cmd.begin(), Cmd.end()};
+ PI.Contents = "";
+ PI.FS = buildTestFS({{MainFile, ""}, {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,
+ const CanonicalIncludes &Includes) {
+ Index.updatePreamble(MainFile, Ctx, PP, Includes);
+ });
+ auto Symbols = runFuzzyFind(Index, "");
+ EXPECT_THAT(Symbols, ElementsAre(_));
+ EXPECT_THAT(Symbols.begin()->IncludeHeaders.front().IncludeHeader,
+ "<algorithm>");
}
TEST(FileIndexTest, TemplateParamsInLabel) {
@@ -246,7 +283,7 @@ TEST(FileIndexTest, RebuildWithPreamble) {
PI.CompileCommand.Filename = FooCpp;
PI.CompileCommand.CommandLine = {"clang", "-xc++", FooCpp};
- StringMap<std::string> Files;
+ llvm::StringMap<std::string> Files;
Files[FooCpp] = "";
Files[FooH] = R"cpp(
namespace ns_in_header {
@@ -270,10 +307,11 @@ TEST(FileIndexTest, RebuildWithPreamble) {
buildPreamble(
FooCpp, *CI, /*OldPreamble=*/nullptr, tooling::CompileCommand(), PI,
std::make_shared<PCHContainerOperations>(), /*StoreInMemory=*/true,
- [&](ASTContext &Ctx, std::shared_ptr<Preprocessor> PP) {
+ [&](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);
@@ -343,7 +381,7 @@ TEST(FileIndexTest, ReferencesInMainFileWithPreamble) {
)cpp");
auto MainFile = testPath("foo.cpp");
auto HeaderFile = testPath("foo.h");
- std::vector<const char*> Cmd = {"clang", "-xc++", MainFile.c_str()};
+ std::vector<const char *> Cmd = {"clang", "-xc++", MainFile.c_str()};
// Preparse ParseInputs.
ParseInputs PI;
PI.CompileCommand.Directory = testRoot();
@@ -355,22 +393,22 @@ TEST(FileIndexTest, ReferencesInMainFileWithPreamble) {
// 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) {});
+ MainFile, *buildCompilerInvocation(PI), /*OldPreamble=*/nullptr,
+ tooling::CompileCommand(), PI, std::make_shared<PCHContainerOperations>(),
+ /*StoreInMemory=*/true,
+ [&](ASTContext &Ctx, std::shared_ptr<Preprocessor> PP,
+ const CanonicalIncludes &) {});
// Build AST for main file with preamble.
auto AST =
ParsedAST::build(createInvocationFromCommandLine(Cmd), PreambleData,
- MemoryBuffer::getMemBufferCopy(Main.code()),
- std::make_shared<PCHContainerOperations>(), PI.FS);
+ llvm::MemoryBuffer::getMemBufferCopy(Main.code()),
+ std::make_shared<PCHContainerOperations>(), PI.FS,
+ /*Index=*/nullptr, ParseOptions());
ASSERT_TRUE(AST);
FileIndex Index;
Index.updateMain(MainFile, *AST);
- auto Foo =
- findSymbol(TestTU::withHeaderCode(Header).headerSymbols(), "Foo");
+ auto Foo = findSymbol(TestTU::withHeaderCode(Header).headerSymbols(), "Foo");
RefsRequest Request;
Request.IDs.insert(Foo.ID);
diff --git a/unittests/clangd/FindSymbolsTests.cpp b/unittests/clangd/FindSymbolsTests.cpp
index ec7865ea..78447f35 100644
--- a/unittests/clangd/FindSymbolsTests.cpp
+++ b/unittests/clangd/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"
@@ -14,8 +13,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace llvm;
-
namespace clang {
namespace clangd {
@@ -64,6 +61,7 @@ public:
: Server(CDB, FSProvider, DiagConsumer, optsForTests()) {
// Make sure the test root directory is created.
FSProvider.Files[testPath("unused")] = "";
+ CDB.ExtraClangFlags = {"-xc++"};
}
protected:
@@ -73,14 +71,14 @@ protected:
ClangdServer Server;
int Limit = 0;
- std::vector<SymbolInformation> getSymbols(StringRef Query) {
+ std::vector<SymbolInformation> getSymbols(llvm::StringRef Query) {
EXPECT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for preamble";
auto SymbolInfos = runWorkspaceSymbols(Server, Query, Limit);
EXPECT_TRUE(bool(SymbolInfos)) << "workspaceSymbols returned an error";
return *SymbolInfos;
}
- void addFile(StringRef FileName, StringRef Contents) {
+ void addFile(llvm::StringRef FileName, llvm::StringRef Contents) {
auto Path = testPath(FileName);
FSProvider.Files[Path] = Contents;
Server.addDocument(Path, Contents);
@@ -89,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) {
@@ -143,10 +144,11 @@ TEST_F(WorkspaceSymbolsTest, Unnamed) {
TEST_F(WorkspaceSymbolsTest, InMainFile) {
addFile("foo.cpp", R"cpp(
- int test() {
- }
+ int test() {}
+ static test2() {}
)cpp");
- EXPECT_THAT(getSymbols("test"), IsEmpty());
+ EXPECT_THAT(getSymbols("test"),
+ ElementsAre(QName("test"), QName("test2")));
}
TEST_F(WorkspaceSymbolsTest, Namespaces) {
@@ -186,7 +188,7 @@ TEST_F(WorkspaceSymbolsTest, AnonymousNamespace) {
addFile("foo.cpp", R"cpp(
#include "foo.h"
)cpp");
- EXPECT_THAT(getSymbols("test"), IsEmpty());
+ EXPECT_THAT(getSymbols("test"), ElementsAre(QName("test")));
}
TEST_F(WorkspaceSymbolsTest, MultiFile) {
@@ -273,7 +275,7 @@ TEST_F(WorkspaceSymbolsTest, Enums) {
TEST_F(WorkspaceSymbolsTest, Ranking) {
addFile("foo.h", R"cpp(
namespace ns{}
- function func();
+ void func();
)cpp");
addFile("foo.cpp", R"cpp(
#include "foo.h"
@@ -318,7 +320,7 @@ protected:
return *SymbolInfos;
}
- void addFile(StringRef FilePath, StringRef Contents) {
+ void addFile(llvm::StringRef FilePath, llvm::StringRef Contents) {
FSProvider.Files[FilePath] = Contents;
Server.addDocument(FilePath, Contents);
}
@@ -439,7 +441,7 @@ TEST_F(DocumentSymbolsTest, DeclarationDefinition) {
TEST_F(DocumentSymbolsTest, ExternSymbol) {
std::string FilePath = testPath("foo.cpp");
addFile(testPath("foo.h"), R"cpp(
- extern int var = 2;
+ extern int var;
)cpp");
addFile(FilePath, R"cpp(
#include "foo.h"
diff --git a/unittests/clangd/FunctionTests.cpp b/unittests/clangd/FunctionTests.cpp
index 1311ee43..dc12186d 100644
--- a/unittests/clangd/FunctionTests.cpp
+++ b/unittests/clangd/FunctionTests.cpp
@@ -1,9 +1,8 @@
//===-- FunctionsTests.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
//
//===----------------------------------------------------------------------===//
@@ -11,7 +10,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
diff --git a/unittests/clangd/FuzzyMatchTests.cpp b/unittests/clangd/FuzzyMatchTests.cpp
index b1981a62..d2ddbdaf 100644
--- a/unittests/clangd/FuzzyMatchTests.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -13,7 +12,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -21,17 +19,18 @@ using testing::Not;
struct ExpectedMatch {
// Annotations are optional, and will not be asserted if absent.
- ExpectedMatch(StringRef Match) : Word(Match), Annotated(Match) {
+ ExpectedMatch(llvm::StringRef Match) : Word(Match), Annotated(Match) {
for (char C : "[]")
Word.erase(std::remove(Word.begin(), Word.end(), C), Word.end());
if (Word.size() == Annotated->size())
- Annotated = None;
+ Annotated = llvm::None;
}
- bool accepts(StringRef ActualAnnotated) const {
+ bool accepts(llvm::StringRef ActualAnnotated) const {
return !Annotated || ActualAnnotated == *Annotated;
}
- friend raw_ostream &operator<<(raw_ostream &OS, const ExpectedMatch &M) {
+ friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const ExpectedMatch &M) {
OS << "'" << M.Word;
if (M.Annotated)
OS << "' as " << *M.Annotated;
@@ -41,26 +40,27 @@ struct ExpectedMatch {
std::string Word;
private:
- Optional<StringRef> Annotated;
+ llvm::Optional<llvm::StringRef> Annotated;
};
-struct MatchesMatcher : public testing::MatcherInterface<StringRef> {
+struct MatchesMatcher : public testing::MatcherInterface<llvm::StringRef> {
ExpectedMatch Candidate;
- Optional<float> Score;
- MatchesMatcher(ExpectedMatch Candidate, Optional<float> Score)
+ llvm::Optional<float> Score;
+ MatchesMatcher(ExpectedMatch Candidate, llvm::Optional<float> Score)
: Candidate(std::move(Candidate)), Score(Score) {}
void DescribeTo(::std::ostream *OS) const override {
- raw_os_ostream(*OS) << "Matches " << Candidate;
+ llvm::raw_os_ostream(*OS) << "Matches " << Candidate;
if (Score)
*OS << " with score " << *Score;
}
- bool MatchAndExplain(StringRef Pattern,
+ bool MatchAndExplain(llvm::StringRef Pattern,
testing::MatchResultListener *L) const override {
- std::unique_ptr<raw_ostream> OS(
- L->stream() ? (raw_ostream *)(new raw_os_ostream(*L->stream()))
- : new raw_null_ostream());
+ std::unique_ptr<llvm::raw_ostream> OS(
+ L->stream()
+ ? (llvm::raw_ostream *)(new llvm::raw_os_ostream(*L->stream()))
+ : new llvm::raw_null_ostream());
FuzzyMatcher Matcher(Pattern);
auto Result = Matcher.match(Candidate.Word);
auto AnnotatedMatch = Matcher.dumpLast(*OS << "\n");
@@ -71,8 +71,9 @@ struct MatchesMatcher : public testing::MatcherInterface<StringRef> {
// Accepts patterns that match a given word, optionally requiring a score.
// Dumps the debug tables on match failure.
-testing::Matcher<StringRef> matches(StringRef M, Optional<float> Score = {}) {
- return testing::MakeMatcher<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) {
@@ -178,27 +179,28 @@ TEST(FuzzyMatch, Matches) {
EXPECT_THAT("std", Not(matches("pthread_condattr_setpshared")));
}
-struct RankMatcher : public testing::MatcherInterface<StringRef> {
+struct RankMatcher : public testing::MatcherInterface<llvm::StringRef> {
std::vector<ExpectedMatch> RankedStrings;
RankMatcher(std::initializer_list<ExpectedMatch> RankedStrings)
: RankedStrings(RankedStrings) {}
void DescribeTo(::std::ostream *OS) const override {
- raw_os_ostream O(*OS);
+ llvm::raw_os_ostream O(*OS);
O << "Ranks strings in order: [";
for (const auto &Str : RankedStrings)
O << "\n\t" << Str;
O << "\n]";
}
- bool MatchAndExplain(StringRef Pattern,
+ bool MatchAndExplain(llvm::StringRef Pattern,
testing::MatchResultListener *L) const override {
- std::unique_ptr<raw_ostream> OS(
- L->stream() ? (raw_ostream *)(new raw_os_ostream(*L->stream()))
- : new raw_null_ostream());
+ std::unique_ptr<llvm::raw_ostream> OS(
+ L->stream()
+ ? (llvm::raw_ostream *)(new llvm::raw_os_ostream(*L->stream()))
+ : new llvm::raw_null_ostream());
FuzzyMatcher Matcher(Pattern);
const ExpectedMatch *LastMatch;
- Optional<float> LastScore;
+ llvm::Optional<float> LastScore;
bool Ok = true;
for (const auto &Str : RankedStrings) {
auto Score = Matcher.match(Str.Word);
@@ -208,7 +210,7 @@ struct RankMatcher : public testing::MatcherInterface<StringRef> {
Ok = false;
} else {
std::string Buf;
- raw_string_ostream Info(Buf);
+ llvm::raw_string_ostream Info(Buf);
auto AnnotatedMatch = Matcher.dumpLast(Info);
if (!Str.accepts(AnnotatedMatch)) {
@@ -233,8 +235,9 @@ struct RankMatcher : public testing::MatcherInterface<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<StringRef> ranks(T... RankedStrings) {
- return testing::MakeMatcher<StringRef>(
+template <typename... T>
+testing::Matcher<llvm::StringRef> ranks(T... RankedStrings) {
+ return testing::MakeMatcher<llvm::StringRef>(
new RankMatcher{ExpectedMatch(RankedStrings)...});
}
@@ -275,7 +278,7 @@ TEST(FuzzyMatch, Scoring) {
// Returns pretty-printed segmentation of Text.
// e.g. std::basic_string --> +-- +---- +-----
-std::string segment(StringRef Text) {
+std::string segment(llvm::StringRef Text) {
std::vector<CharRole> Roles(Text.size());
calculateRoles(Text, Roles);
std::string Printed;
@@ -285,7 +288,7 @@ std::string segment(StringRef Text) {
}
// this is a no-op hack so clang-format will vertically align our testcases.
-StringRef returns(StringRef Text) { return Text; }
+llvm::StringRef returns(llvm::StringRef Text) { return Text; }
TEST(FuzzyMatch, Segmentation) {
EXPECT_THAT(segment("std::basic_string"), //
diff --git a/unittests/clangd/GlobalCompilationDatabaseTests.cpp b/unittests/clangd/GlobalCompilationDatabaseTests.cpp
index f3916108..a1b696f6 100644
--- a/unittests/clangd/GlobalCompilationDatabaseTests.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -14,34 +13,37 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
using ::testing::ElementsAre;
+using ::testing::EndsWith;
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("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++.
Cmd = DB.getFallbackCommand(testPath("foo/bar.h"));
- EXPECT_THAT(Cmd.CommandLine, ElementsAre("clang", "-xobjective-c++-header",
- testPath("foo/bar.h")));
+ EXPECT_THAT(Cmd.CommandLine,
+ ElementsAre(EndsWith("clang"), "-xobjective-c++-header",
+ testPath("foo/bar.h")));
}
-static tooling::CompileCommand cmd(StringRef File, StringRef Arg) {
+static tooling::CompileCommand cmd(llvm::StringRef File, llvm::StringRef Arg) {
return tooling::CompileCommand(testRoot(), File, {"clang", Arg, File}, "");
}
class OverlayCDBTest : public ::testing::Test {
class BaseCDB : public GlobalCompilationDatabase {
public:
- Optional<tooling::CompileCommand>
- getCompileCommand(StringRef File, ProjectInfo *Project) const override {
+ llvm::Optional<tooling::CompileCommand>
+ getCompileCommand(llvm::StringRef File,
+ ProjectInfo *Project) const override {
if (File == testPath("foo.cc")) {
if (Project)
Project->SourceRoot = testRoot();
@@ -50,7 +52,8 @@ class OverlayCDBTest : public ::testing::Test {
return None;
}
- tooling::CompileCommand getFallbackCommand(StringRef File) const override {
+ tooling::CompileCommand
+ getFallbackCommand(llvm::StringRef File) const override {
return cmd(File, "-DA=2");
}
};
@@ -61,7 +64,7 @@ protected:
};
TEST_F(OverlayCDBTest, GetCompileCommand) {
- OverlayCDB CDB(Base.get());
+ OverlayCDB CDB(Base.get(), {}, std::string(""));
EXPECT_EQ(CDB.getCompileCommand(testPath("foo.cc")),
Base->getCompileCommand(testPath("foo.cc")));
EXPECT_EQ(CDB.getCompileCommand(testPath("missing.cc")), llvm::None);
@@ -81,14 +84,14 @@ 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.getFallbackCommand(testPath("foo.cc")).CommandLine,
- ElementsAre("clang", testPath("foo.cc"), "-DA=6"));
+ ElementsAre(EndsWith("clang"), testPath("foo.cc"), "-DA=6"));
}
TEST_F(OverlayCDBTest, Watch) {
diff --git a/unittests/clangd/HeadersTests.cpp b/unittests/clangd/HeadersTests.cpp
index bd28f714..65bcb850 100644
--- a/unittests/clangd/HeadersTests.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -19,7 +18,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -53,7 +51,7 @@ private:
CI->getDiagnosticOpts().IgnoreWarnings = true;
auto Clang = prepareCompilerInstance(
std::move(CI), /*Preamble=*/nullptr,
- MemoryBuffer::getMemBuffer(FS.Files[MainFile], MainFile),
+ llvm::MemoryBuffer::getMemBuffer(FS.Files[MainFile], MainFile),
std::make_shared<PCHContainerOperations>(), VFS, IgnoreDiags);
EXPECT_FALSE(Clang->getFrontendOpts().Inputs.empty());
@@ -85,9 +83,9 @@ protected:
if (Preferred.empty())
Preferred = Original;
- auto ToHeaderFile = [](StringRef Header) {
+ auto ToHeaderFile = [](llvm::StringRef Header) {
return HeaderFile{Header,
- /*Verbatim=*/!sys::path::is_absolute(Header)};
+ /*Verbatim=*/!llvm::sys::path::is_absolute(Header)};
};
IncludeInserter Inserter(MainFile, /*Code=*/"", format::getLLVMStyle(),
@@ -104,7 +102,7 @@ protected:
return Path;
}
- Optional<TextEdit> insert(StringRef VerbatimHeader) {
+ llvm::Optional<TextEdit> insert(llvm::StringRef VerbatimHeader) {
auto Clang = setupClang();
PreprocessOnlyAction Action;
EXPECT_TRUE(
@@ -122,7 +120,7 @@ protected:
MockCompilationDatabase CDB;
std::string MainFile = testPath("main.cpp");
std::string Subdir = testPath("sub");
- std::string SearchDirArg = (Twine("-I") + Subdir).str();
+ std::string SearchDirArg = (llvm::Twine("-I") + Subdir).str();
IgnoringDiagConsumer IgnoreDiags;
};
diff --git a/unittests/clangd/IndexActionTests.cpp b/unittests/clangd/IndexActionTests.cpp
index 93f324b7..55ec4594 100644
--- a/unittests/clangd/IndexActionTests.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -68,7 +67,7 @@ public:
runIndexingAction(llvm::StringRef MainFilePath,
const std::vector<std::string> &ExtraArgs = {}) {
IndexFileIn IndexFile;
- IntrusiveRefCntPtr<FileManager> Files(
+ llvm::IntrusiveRefCntPtr<FileManager> Files(
new FileManager(FileSystemOptions(), InMemoryFileSystem));
auto Action = createStaticIndexingAction(
@@ -101,7 +100,7 @@ public:
protected:
std::vector<std::string> FilePaths;
- IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;
};
TEST_F(IndexActionTest, CollectIncludeGraph) {
diff --git a/unittests/clangd/IndexTests.cpp b/unittests/clangd/IndexTests.cpp
index 6bfdf6aa..7d60ede1 100644
--- a/unittests/clangd/IndexTests.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -19,12 +18,12 @@
using testing::_;
using testing::AllOf;
+using testing::AnyOf;
using testing::ElementsAre;
using testing::Pair;
using testing::Pointee;
using testing::UnorderedElementsAre;
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -219,6 +218,7 @@ TEST(MergeTest, Merge) {
R.Documentation = "--doc--";
L.Origin = SymbolOrigin::Dynamic;
R.Origin = SymbolOrigin::Static;
+ R.Type = "expectedType";
Symbol M = mergeSymbol(L, R);
EXPECT_EQ(M.Name, "Foo");
@@ -227,6 +227,7 @@ TEST(MergeTest, Merge) {
EXPECT_EQ(M.Signature, "()");
EXPECT_EQ(M.CompletionSnippetSuffix, "{$1:0}");
EXPECT_EQ(M.Documentation, "--doc--");
+ EXPECT_EQ(M.Type, "expectedType");
EXPECT_EQ(M.Origin,
SymbolOrigin::Dynamic | SymbolOrigin::Static | SymbolOrigin::Merge);
}
@@ -252,6 +253,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;
@@ -291,7 +308,6 @@ TEST(MergeIndexTest, Refs) {
Request.IDs = {Foo.ID};
RefSlab::Builder Results;
Merge.refs(Request, [&](const Ref &O) { Results.insert(Foo.ID, O); });
-
EXPECT_THAT(
std::move(Results).build(),
ElementsAre(Pair(
@@ -299,9 +315,17 @@ TEST(MergeIndexTest, Refs) {
FileURI("unittest:///test.cc")),
AllOf(RefRange(Test2Code.range("Foo")),
FileURI("unittest:///test2.cc"))))));
+
+ Request.Limit = 1;
+ RefSlab::Builder Results2;
+ Merge.refs(Request, [&](const Ref &O) { Results2.insert(Foo.ID, O); });
+ EXPECT_THAT(std::move(Results2).build(),
+ ElementsAre(Pair(
+ _, ElementsAre(AnyOf(FileURI("unittest:///test.cc"),
+ FileURI("unittest:///test2.cc"))))));
}
-MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
+MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
return (arg.IncludeHeader == IncludeHeader) && (arg.References == References);
}
diff --git a/unittests/clangd/JSONTransportTests.cpp b/unittests/clangd/JSONTransportTests.cpp
index bc5a9674..0498c813 100644
--- a/unittests/clangd/JSONTransportTests.cpp
+++ b/unittests/clangd/JSONTransportTests.cpp
@@ -1,32 +1,29 @@
//===-- 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"
#include "Transport.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include <stdio.h>
+#include <cstdio>
-using namespace llvm;
namespace clang {
namespace clangd {
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 {
std::string InBuf, OutBuf, MirrorBuf;
- raw_string_ostream Out, Mirror;
+ llvm::raw_string_ostream Out, Mirror;
std::unique_ptr<FILE, int (*)(FILE *)> In;
protected:
@@ -53,40 +50,43 @@ protected:
class Echo : public Transport::MessageHandler {
Transport &Target;
std::string LogBuf;
- raw_string_ostream Log;
+ llvm::raw_string_ostream Log;
public:
Echo(Transport &Target) : Target(Target), Log(LogBuf) {}
std::string log() { return Log.str(); }
- bool onNotify(StringRef Method, json::Value Params) override {
+ bool onNotify(llvm::StringRef Method, llvm::json::Value Params) override {
Log << "Notification " << Method << ": " << Params << "\n";
if (Method == "call")
Target.call("echo call", std::move(Params), 42);
return Method != "exit";
}
- bool onCall(StringRef Method, json::Value Params, json::Value ID) override {
+ bool onCall(llvm::StringRef Method, llvm::json::Value Params,
+ llvm::json::Value ID) override {
Log << "Call " << Method << "(" << ID << "): " << Params << "\n";
if (Method == "err")
- Target.reply(ID, make_error<LSPError>("trouble at mill", ErrorCode(88)));
+ Target.reply(
+ ID, llvm::make_error<LSPError>("trouble at mill", ErrorCode(88)));
else
Target.reply(ID, std::move(Params));
return true;
}
- bool onReply(json::Value ID, Expected<json::Value> Params) override {
+ bool onReply(llvm::json::Value ID,
+ llvm::Expected<llvm::json::Value> Params) override {
if (Params)
Log << "Reply(" << ID << "): " << *Params << "\n";
else
- Log << "Reply(" << ID << "): error = " << toString(Params.takeError())
- << "\n";
+ Log << "Reply(" << ID
+ << "): error = " << llvm::toString(Params.takeError()) << "\n";
return true;
}
};
-std::string trim(StringRef S) { return S.trim().str(); }
+std::string trim(llvm::StringRef S) { return S.trim().str(); }
// Runs an Echo session using the standard JSON-RPC format we use in production.
TEST_F(JSONTransportTest, StandardDense) {
diff --git a/unittests/clangd/Matchers.h b/unittests/clangd/Matchers.h
index d666de36..0ace9706 100644
--- a/unittests/clangd/Matchers.h
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
//
diff --git a/unittests/clangd/QualityTests.cpp b/unittests/clangd/QualityTests.cpp
index f1a1fdae..e2fe8f3a 100644
--- a/unittests/clangd/QualityTests.cpp
+++ b/unittests/clangd/QualityTests.cpp
@@ -1,9 +1,8 @@
//===-- SourceCodeTests.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,7 +29,6 @@
#include "gtest/gtest.h"
#include <vector>
-using namespace llvm;
namespace clang {
namespace clangd {
@@ -180,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?
@@ -253,7 +264,7 @@ TEST(QualityTests, SymbolRelevanceSignalsSanity) {
SymbolRelevanceSignals IndexProximate;
IndexProximate.SymbolURI = "unittest:/foo/bar.h";
- StringMap<SourceParams> ProxSources;
+ llvm::StringMap<SourceParams> ProxSources;
ProxSources.try_emplace(testPath("foo/baz.h"));
URIDistance Distance(ProxSources);
IndexProximate.FileProximityMatch = &Distance;
@@ -266,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());
@@ -371,7 +382,7 @@ TEST(QualityTests, IsInstanceMember) {
Rel.merge(BarSym);
EXPECT_TRUE(Rel.IsInstanceMember);
- Rel.IsInstanceMember =false;
+ Rel.IsInstanceMember = false;
const Symbol &TplSym = findSymbol(Symbols, "Foo::tpl");
Rel.merge(TplSym);
EXPECT_TRUE(Rel.IsInstanceMember);
@@ -429,7 +440,7 @@ TEST(QualityTests, Operator) {
auto Header = TestTU::withHeaderCode(R"cpp(
class Foo {
public:
- bool operator<(const Foo& f1, const Foo& f2);
+ bool operator<(const Foo& f1);
};
)cpp");
auto AST = Header.build();
diff --git a/unittests/clangd/RIFFTests.cpp b/unittests/clangd/RIFFTests.cpp
index 6c5cebc7..4cd54f40 100644
--- a/unittests/clangd/RIFFTests.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -11,7 +10,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -23,12 +21,12 @@ TEST(RIFFTest, File) {
{riff::fourCC("even"), "abcd"},
{riff::fourCC("oddd"), "abcde"},
}};
- StringRef Serialized = StringRef("RIFF\x1e\0\0\0test"
- "even\x04\0\0\0abcd"
- "oddd\x05\0\0\0abcde\0",
- 38);
+ llvm::StringRef Serialized = llvm::StringRef("RIFF\x1e\0\0\0test"
+ "even\x04\0\0\0abcd"
+ "oddd\x05\0\0\0abcde\0",
+ 38);
- EXPECT_EQ(to_string(File), Serialized);
+ EXPECT_EQ(llvm::to_string(File), Serialized);
auto Parsed = riff::readFile(Serialized);
ASSERT_TRUE(bool(Parsed)) << Parsed.takeError();
EXPECT_EQ(*Parsed, File);
diff --git a/unittests/clangd/SelectionTests.cpp b/unittests/clangd/SelectionTests.cpp
new file mode 100644
index 00000000..2322a0e6
--- /dev/null
+++ b/unittests/clangd/SelectionTests.cpp
@@ -0,0 +1,254 @@
+//===-- 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()) + 1)};
+}
+
+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",
+ };
+ 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/unittests/clangd/SerializationTests.cpp
index a30369b0..3260ac68 100644
--- a/unittests/clangd/SerializationTests.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -20,7 +19,6 @@ using testing::Pair;
using testing::UnorderedElementsAre;
using testing::UnorderedElementsAreArray;
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -92,6 +90,10 @@ MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
return (arg.IncludeHeader == IncludeHeader) && (arg.References == References);
}
+TEST(SerializationTest, NoCrashOnEmptyYAML) {
+ EXPECT_TRUE(bool(readIndexFile("")));
+}
+
TEST(SerializationTest, YAMLConversions) {
auto In = readIndexFile(YAML);
EXPECT_TRUE(bool(In)) << In.takeError();
@@ -99,9 +101,9 @@ TEST(SerializationTest, YAMLConversions) {
auto ParsedYAML = readIndexFile(YAML);
ASSERT_TRUE(bool(ParsedYAML)) << ParsedYAML.takeError();
ASSERT_TRUE(bool(ParsedYAML->Symbols));
- EXPECT_THAT(*ParsedYAML->Symbols,
- UnorderedElementsAre(ID("057557CEBF6E6B2D"),
- ID("057557CEBF6E6B2E")));
+ EXPECT_THAT(
+ *ParsedYAML->Symbols,
+ UnorderedElementsAre(ID("057557CEBF6E6B2D"), ID("057557CEBF6E6B2E")));
auto Sym1 = *ParsedYAML->Symbols->find(
cantFail(SymbolID::fromStr("057557CEBF6E6B2D")));
@@ -131,9 +133,8 @@ TEST(SerializationTest, YAMLConversions) {
ASSERT_TRUE(bool(ParsedYAML->Refs));
EXPECT_THAT(
*ParsedYAML->Refs,
- UnorderedElementsAre(
- Pair(cantFail(SymbolID::fromStr("057557CEBF6E6B2D")),
- testing::SizeIs(1))));
+ UnorderedElementsAre(Pair(cantFail(SymbolID::fromStr("057557CEBF6E6B2D")),
+ 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");
@@ -159,7 +160,7 @@ TEST(SerializationTest, BinaryConversions) {
// Write to binary format, and parse again.
IndexFileOut Out(*In);
Out.Format = IndexFileFormat::RIFF;
- std::string Serialized = to_string(Out);
+ std::string Serialized = llvm::to_string(Out);
auto In2 = readIndexFile(Serialized);
ASSERT_TRUE(bool(In2)) << In.takeError();
@@ -192,7 +193,7 @@ TEST(SerializationTest, SrcsTest) {
Out.Format = IndexFileFormat::RIFF;
Out.Sources = &Sources;
{
- std::string Serialized = to_string(Out);
+ std::string Serialized = llvm::to_string(Out);
auto In = readIndexFile(Serialized);
ASSERT_TRUE(bool(In)) << In.takeError();
diff --git a/unittests/clangd/SourceCodeTests.cpp b/unittests/clangd/SourceCodeTests.cpp
index 3148ccca..316a0d52 100644
--- a/unittests/clangd/SourceCodeTests.cpp
+++ b/unittests/clangd/SourceCodeTests.cpp
@@ -1,11 +1,11 @@
//===-- SourceCodeTests.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"
#include "SourceCode.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_os_ostream.h"
@@ -13,11 +13,13 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
+using llvm::Failed;
+using llvm::HasValue;
+
MATCHER_P2(Pos, Line, Col, "") {
return arg.line == Line && arg.character == Col;
}
@@ -54,63 +56,63 @@ TEST(SourceCodeTests, lspLength) {
TEST(SourceCodeTests, PositionToOffset) {
// line out of bounds
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), Failed());
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), llvm::Failed());
// first line
EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, -1)),
- Failed()); // out of range
+ llvm::Failed()); // out of range
EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 0)),
- HasValue(0)); // first character
+ llvm::HasValue(0)); // first character
EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 3)),
- HasValue(3)); // middle character
+ llvm::HasValue(3)); // middle character
EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 6)),
- HasValue(6)); // last character
+ llvm::HasValue(6)); // last character
EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7)),
- HasValue(7)); // the newline itself
+ llvm::HasValue(7)); // the newline itself
EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7), false),
- HasValue(7));
+ llvm::HasValue(7));
EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8)),
- HasValue(7)); // out of range
+ llvm::HasValue(7)); // out of range
EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8), false),
- Failed()); // out of range
+ llvm::Failed()); // out of range
// middle line
EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, -1)),
- Failed()); // out of range
+ llvm::Failed()); // out of range
EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 0)),
- HasValue(8)); // first character
+ llvm::HasValue(8)); // first character
EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3)),
- HasValue(11)); // middle character
+ llvm::HasValue(11)); // middle character
EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3), false),
- HasValue(11));
+ llvm::HasValue(11));
EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 6)),
- HasValue(16)); // last character
+ llvm::HasValue(16)); // last character
EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 7)),
- HasValue(17)); // the newline itself
+ llvm::HasValue(17)); // the newline itself
EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8)),
- HasValue(17)); // out of range
+ llvm::HasValue(17)); // out of range
EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8), false),
- Failed()); // out of range
+ llvm::Failed()); // out of range
// last line
EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, -1)),
- Failed()); // out of range
+ llvm::Failed()); // out of range
EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 0)),
- HasValue(18)); // first character
+ llvm::HasValue(18)); // first character
EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 3)),
- HasValue(21)); // middle character
+ llvm::HasValue(21)); // middle character
EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5), false),
- Failed()); // middle of surrogate pair
+ llvm::Failed()); // middle of surrogate pair
EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5)),
- HasValue(26)); // middle of surrogate pair
+ llvm::HasValue(26)); // middle of surrogate pair
EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 6), false),
- HasValue(26)); // end of surrogate pair
+ llvm::HasValue(26)); // end of surrogate pair
EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 8)),
- HasValue(28)); // last character
+ llvm::HasValue(28)); // last character
EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 9)),
- HasValue(29)); // EOF
+ llvm::HasValue(29)); // EOF
EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 10), false),
- Failed()); // out of range
+ llvm::Failed()); // out of range
// line out of bounds
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), Failed());
- EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 1)), Failed());
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), llvm::Failed());
+ EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 1)), llvm::Failed());
}
TEST(SourceCodeTests, OffsetToPosition) {
@@ -135,11 +137,43 @@ TEST(SourceCodeTests, OffsetToPosition) {
}
TEST(SourceCodeTests, IsRangeConsecutive) {
- EXPECT_TRUE(IsRangeConsecutive(range({2, 2}, {2, 3}), range({2, 3}, {2, 4})));
+ 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})));
+ isRangeConsecutive(range({0, 2}, {0, 3}), range({2, 3}, {2, 4})));
EXPECT_FALSE(
- IsRangeConsecutive(range({2, 2}, {2, 3}), range({2, 4}, {2, 5})));
+ 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)));
+ }
}
} // namespace
diff --git a/unittests/clangd/SymbolCollectorTests.cpp b/unittests/clangd/SymbolCollectorTests.cpp
index 952fcbef..258cfa9d 100644
--- a/unittests/clangd/SymbolCollectorTests.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -27,7 +26,6 @@
#include <memory>
#include <string>
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -61,7 +59,7 @@ MATCHER_P(IncludeHeader, P, "") {
return (arg.IncludeHeaders.size() == 1) &&
(arg.IncludeHeaders.begin()->IncludeHeader == P);
}
-MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
+MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
return (arg.IncludeHeader == IncludeHeader) && (arg.References == References);
}
MATCHER_P(DeclRange, Pos, "") {
@@ -88,6 +86,9 @@ MATCHER(Deprecated, "") { return arg.Flags & Symbol::Deprecated; }
MATCHER(ImplementationDetail, "") {
return arg.Flags & Symbol::ImplementationDetail;
}
+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);
@@ -103,7 +104,7 @@ HaveRanges(const std::vector<Range> Ranges) {
class ShouldCollectSymbolTest : public ::testing::Test {
public:
- void build(StringRef HeaderCode, StringRef Code = "") {
+ void build(llvm::StringRef HeaderCode, llvm::StringRef Code = "") {
File.HeaderFilename = HeaderName;
File.Filename = FileName;
File.HeaderCode = HeaderCode;
@@ -112,18 +113,22 @@ public:
}
// build() must have been called.
- bool shouldCollect(StringRef Name, bool Qualified = true) {
+ bool shouldCollect(llvm::StringRef Name, bool Qualified = true) {
assert(AST.hasValue());
+ 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()));
return SymbolCollector::shouldCollectSymbol(
- Qualified ? findDecl(*AST, Name) : findUnqualifiedDecl(*AST, Name),
- AST->getASTContext(), SymbolCollector::Options());
+ ND, Ctx, SymbolCollector::Options(), MainFile);
}
protected:
std::string HeaderName = "f.h";
std::string FileName = "f.cpp";
TestTU File;
- Optional<ParsedAST> AST; // Initialized after build.
+ llvm::Optional<ParsedAST> AST; // Initialized after build.
};
TEST_F(ShouldCollectSymbolTest, ShouldCollectSymbol) {
@@ -131,19 +136,23 @@ TEST_F(ShouldCollectSymbolTest, ShouldCollectSymbol) {
namespace nx {
class X{};
auto f() { int Local; } // auto ensures function body is parsed.
- struct { int x } var;
- namespace { class InAnonymous {}; }
+ struct { int x; } var;
}
)",
- "class InMain {};");
+ R"(
+ class InMain {};
+ namespace { class InAnonymous {}; }
+ static void g();
+ )");
auto AST = File.build();
EXPECT_TRUE(shouldCollect("nx"));
EXPECT_TRUE(shouldCollect("nx::X"));
EXPECT_TRUE(shouldCollect("nx::f"));
+ EXPECT_TRUE(shouldCollect("InMain"));
+ EXPECT_TRUE(shouldCollect("InAnonymous", /*Qualified=*/false));
+ EXPECT_TRUE(shouldCollect("g"));
- EXPECT_FALSE(shouldCollect("InMain"));
EXPECT_FALSE(shouldCollect("Local", /*Qualified=*/false));
- EXPECT_FALSE(shouldCollect("InAnonymous", /*Qualified=*/false));
}
TEST_F(ShouldCollectSymbolTest, NoPrivateProtoSymbol) {
@@ -197,7 +206,7 @@ public:
PragmaHandler(PragmaHandler) {}
std::unique_ptr<ASTConsumer>
- CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override {
+ CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) override {
if (PragmaHandler)
CI.getPreprocessor().addCommentHandler(PragmaHandler);
return WrapperFrontendAction::CreateASTConsumer(CI, InFile);
@@ -224,16 +233,16 @@ public:
class SymbolCollectorTest : public ::testing::Test {
public:
SymbolCollectorTest()
- : InMemoryFileSystem(new vfs::InMemoryFileSystem),
+ : InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem),
TestHeaderName(testPath("symbol.h")),
TestFileName(testPath("symbol.cc")) {
TestHeaderURI = URI::create(TestHeaderName).toString();
TestFileURI = URI::create(TestFileName).toString();
}
- bool runSymbolCollector(StringRef HeaderCode, StringRef MainCode,
+ bool runSymbolCollector(llvm::StringRef HeaderCode, llvm::StringRef MainCode,
const std::vector<std::string> &ExtraArgs = {}) {
- IntrusiveRefCntPtr<FileManager> Files(
+ llvm::IntrusiveRefCntPtr<FileManager> Files(
new FileManager(FileSystemOptions(), InMemoryFileSystem));
auto Factory = llvm::make_unique<SymbolIndexActionFactory>(
@@ -248,14 +257,13 @@ public:
Args.push_back(TestFileName);
tooling::ToolInvocation Invocation(
- Args,
- Factory->create(), Files.get(),
+ Args, Factory->create(), Files.get(),
std::make_shared<PCHContainerOperations>());
InMemoryFileSystem->addFile(TestHeaderName, 0,
- MemoryBuffer::getMemBuffer(HeaderCode));
+ llvm::MemoryBuffer::getMemBuffer(HeaderCode));
InMemoryFileSystem->addFile(TestFileName, 0,
- MemoryBuffer::getMemBuffer(MainCode));
+ llvm::MemoryBuffer::getMemBuffer(MainCode));
Invocation.run();
Symbols = Factory->Collector->takeSymbols();
Refs = Factory->Collector->takeRefs();
@@ -263,7 +271,7 @@ public:
}
protected:
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;
std::string TestHeaderName;
std::string TestHeaderURI;
std::string TestFileName;
@@ -349,6 +357,35 @@ TEST_F(SymbolCollectorTest, CollectSymbols) {
AllOf(QName("foo::baz"), ForCodeCompletion(true))}));
}
+TEST_F(SymbolCollectorTest, FileLocal) {
+ const std::string Header = R"(
+ class Foo {};
+ namespace {
+ class Ignored {};
+ }
+ void bar();
+ )";
+ const std::string Main = R"(
+ class ForwardDecl;
+ void bar() {}
+ static void a();
+ class B {};
+ namespace {
+ void c();
+ }
+ )";
+ runSymbolCollector(Header, Main);
+ EXPECT_THAT(Symbols,
+ UnorderedElementsAre(
+ AllOf(QName("Foo"), VisibleOutsideFile()),
+ AllOf(QName("bar"), VisibleOutsideFile()),
+ AllOf(QName("a"), Not(VisibleOutsideFile())),
+ AllOf(QName("B"), Not(VisibleOutsideFile())),
+ AllOf(QName("c"), Not(VisibleOutsideFile())),
+ // FIXME: ForwardDecl likely *is* visible outside.
+ AllOf(QName("ForwardDecl"), Not(VisibleOutsideFile()))));
+}
+
TEST_F(SymbolCollectorTest, Template) {
Annotations Header(R"(
// Template is indexed, specialization and instantiation is not.
@@ -400,6 +437,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.
@@ -419,21 +473,20 @@ o]]();
void $printdef[[print]]() {}
// Declared/defined in main only.
- int Y;
+ int $ydecl[[Y]];
)cpp");
runSymbolCollector(Header.code(), Main.code());
- EXPECT_THAT(
- Symbols,
- UnorderedElementsAre(
- AllOf(QName("X"), DeclRange(Header.range("xdecl")),
- DefRange(Main.range("xdef"))),
- AllOf(QName("Cls"), DeclRange(Header.range("clsdecl")),
- DefRange(Main.range("clsdef"))),
- AllOf(QName("print"), DeclRange(Header.range("printdecl")),
- DefRange(Main.range("printdef"))),
- AllOf(QName("Z"), DeclRange(Header.range("zdecl"))),
- AllOf(QName("foo"), DeclRange(Header.range("foodecl")))
- ));
+ EXPECT_THAT(Symbols,
+ UnorderedElementsAre(
+ AllOf(QName("X"), DeclRange(Header.range("xdecl")),
+ DefRange(Main.range("xdef"))),
+ AllOf(QName("Cls"), DeclRange(Header.range("clsdecl")),
+ DefRange(Main.range("clsdef"))),
+ AllOf(QName("print"), DeclRange(Header.range("printdecl")),
+ DefRange(Main.range("printdef"))),
+ AllOf(QName("Z"), DeclRange(Header.range("zdecl"))),
+ AllOf(QName("foo"), DeclRange(Header.range("foodecl"))),
+ AllOf(QName("Y"), DeclRange(Main.range("ydecl")))));
}
TEST_F(SymbolCollectorTest, Refs) {
@@ -512,17 +565,25 @@ TEST_F(SymbolCollectorTest, References) {
W* w2 = nullptr; // only one usage counts
X x();
class V;
- V* v = nullptr; // Used, but not eligible for indexing.
class Y{}; // definition doesn't count as a reference
+ V* v = nullptr;
GLOBAL_Z(z); // Not a reference to Z, we don't spell the type.
)";
CollectorOpts.CountReferences = true;
runSymbolCollector(Header, Main);
EXPECT_THAT(Symbols,
- UnorderedElementsAre(AllOf(QName("W"), RefCount(1)),
- AllOf(QName("X"), RefCount(1)),
- AllOf(QName("Y"), RefCount(0)),
- AllOf(QName("Z"), RefCount(0)), QName("y")));
+ 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) {
@@ -537,8 +598,8 @@ TEST_F(SymbolCollectorTest, SymbolRelativeWithFallback) {
TestHeaderURI = URI::create(testPath(TestHeaderName)).toString();
CollectorOpts.FallbackDir = testRoot();
runSymbolCollector("class Foo {};", /*Main=*/"");
- EXPECT_THAT(Symbols,
- UnorderedElementsAre(AllOf(QName("Foo"), DeclURI(TestHeaderURI))));
+ EXPECT_THAT(Symbols, UnorderedElementsAre(
+ AllOf(QName("Foo"), DeclURI(TestHeaderURI))));
}
TEST_F(SymbolCollectorTest, UnittestURIScheme) {
@@ -605,13 +666,12 @@ TEST_F(SymbolCollectorTest, SymbolFormedFromRegisteredSchemeFromMacro) {
)");
runSymbolCollector(Header.code(), /*Main=*/"");
- EXPECT_THAT(
- Symbols,
- UnorderedElementsAre(
- AllOf(QName("abc_Test"), DeclRange(Header.range("expansion")),
- DeclURI(TestHeaderURI)),
- AllOf(QName("Test"), DeclRange(Header.range("spelling")),
- DeclURI(TestHeaderURI))));
+ EXPECT_THAT(Symbols,
+ UnorderedElementsAre(
+ AllOf(QName("abc_Test"), DeclRange(Header.range("expansion")),
+ DeclURI(TestHeaderURI)),
+ AllOf(QName("Test"), DeclRange(Header.range("spelling")),
+ DeclURI(TestHeaderURI))));
}
TEST_F(SymbolCollectorTest, SymbolFormedByCLI) {
@@ -626,22 +686,28 @@ TEST_F(SymbolCollectorTest, SymbolFormedByCLI) {
DeclURI(TestHeaderURI))));
}
-TEST_F(SymbolCollectorTest, IgnoreSymbolsInMainFile) {
- const std::string Header = R"(
+TEST_F(SymbolCollectorTest, SymbolsInMainFile) {
+ const std::string Main = R"(
class Foo {};
void f1();
inline void f2() {}
- )";
- const std::string Main = R"(
+
namespace {
- void ff() {} // ignore
+ void ff() {}
+ }
+ namespace foo {
+ namespace {
+ class Bar {};
}
- void main_f() {} // ignore
+ }
+ void main_f() {}
void f1() {}
)";
- runSymbolCollector(Header, Main);
+ runSymbolCollector(/*Header=*/"", Main);
EXPECT_THAT(Symbols,
- UnorderedElementsAre(QName("Foo"), QName("f1"), QName("f2")));
+ UnorderedElementsAre(QName("Foo"), QName("f1"), QName("f2"),
+ QName("ff"), QName("foo"), QName("foo::Bar"),
+ QName("main_f")));
}
TEST_F(SymbolCollectorTest, ClassMembers) {
@@ -659,10 +725,15 @@ TEST_F(SymbolCollectorTest, ClassMembers) {
void Foo::ssf() {}
)";
runSymbolCollector(Header, Main);
- EXPECT_THAT(Symbols,
- UnorderedElementsAre(QName("Foo"), QName("Foo::f"),
- QName("Foo::g"), QName("Foo::sf"),
- QName("Foo::ssf"), QName("Foo::x")));
+ EXPECT_THAT(
+ Symbols,
+ UnorderedElementsAre(
+ QName("Foo"),
+ AllOf(QName("Foo::f"), ReturnType(""), ForCodeCompletion(false)),
+ AllOf(QName("Foo::g"), ReturnType(""), ForCodeCompletion(false)),
+ AllOf(QName("Foo::sf"), ReturnType(""), ForCodeCompletion(false)),
+ AllOf(QName("Foo::ssf"), ReturnType(""), ForCodeCompletion(false)),
+ AllOf(QName("Foo::x"), ReturnType(""), ForCodeCompletion(false))));
}
TEST_F(SymbolCollectorTest, Scopes) {
@@ -833,7 +904,7 @@ TEST_F(SymbolCollectorTest, SkipIncFileWhenCanonicalizeHeaders) {
auto IncFile = testPath("test.inc");
auto IncURI = URI::create(IncFile).toString();
InMemoryFileSystem->addFile(IncFile, 0,
- MemoryBuffer::getMemBuffer("class X {};"));
+ llvm::MemoryBuffer::getMemBuffer("class X {};"));
runSymbolCollector("#include \"test.inc\"\nclass Y {};", /*Main=*/"",
/*ExtraArgs=*/{"-I", testRoot()});
EXPECT_THAT(Symbols,
@@ -852,7 +923,7 @@ TEST_F(SymbolCollectorTest, MainFileIsHeaderWhenSkipIncFile) {
auto IncFile = testPath("test.inc");
auto IncURI = URI::create(IncFile).toString();
InMemoryFileSystem->addFile(IncFile, 0,
- MemoryBuffer::getMemBuffer("class X {};"));
+ llvm::MemoryBuffer::getMemBuffer("class X {};"));
runSymbolCollector("", /*Main=*/"#include \"test.inc\"",
/*ExtraArgs=*/{"-I", testRoot()});
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
@@ -868,7 +939,7 @@ TEST_F(SymbolCollectorTest, MainFileIsHeaderWithoutExtensionWhenSkipIncFile) {
auto IncFile = testPath("test.inc");
auto IncURI = URI::create(IncFile).toString();
InMemoryFileSystem->addFile(IncFile, 0,
- MemoryBuffer::getMemBuffer("class X {};"));
+ llvm::MemoryBuffer::getMemBuffer("class X {};"));
runSymbolCollector("", /*Main=*/"#include \"test.inc\"",
/*ExtraArgs=*/{"-I", testRoot()});
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
@@ -882,7 +953,7 @@ TEST_F(SymbolCollectorTest, FallbackToIncFileWhenIncludingFileIsCC) {
auto IncFile = testPath("test.inc");
auto IncURI = URI::create(IncFile).toString();
InMemoryFileSystem->addFile(IncFile, 0,
- MemoryBuffer::getMemBuffer("class X {};"));
+ llvm::MemoryBuffer::getMemBuffer("class X {};"));
runSymbolCollector("", /*Main=*/"#include \"test.inc\"",
/*ExtraArgs=*/{"-I", testRoot()});
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
@@ -978,7 +1049,8 @@ TEST_F(SymbolCollectorTest, ReferencesInFriendDecl) {
CollectorOpts.CountReferences = true;
runSymbolCollector(Header, Main);
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), RefCount(1)),
- AllOf(QName("Y"), RefCount(1))));
+ AllOf(QName("Y"), RefCount(1)),
+ AllOf(QName("C"), RefCount(0))));
}
TEST_F(SymbolCollectorTest, Origin) {
@@ -997,21 +1069,27 @@ TEST_F(SymbolCollectorTest, CollectMacros) {
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"),
- 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) {
diff --git a/unittests/clangd/SymbolInfoTests.cpp b/unittests/clangd/SymbolInfoTests.cpp
index 400a3aa5..ed34c036 100644
--- a/unittests/clangd/SymbolInfoTests.cpp
+++ b/unittests/clangd/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"
@@ -21,7 +20,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -37,26 +35,24 @@ auto CreateExpectedSymbolDetails = [](const std::string &name,
TEST(SymbolInfoTests, All) {
std::pair<const char *, std::vector<SymbolDetails>>
TestInputExpectedOutput[] = {
- {
- R"cpp( // Simple function reference - declaration
+ {
+ R"cpp( // Simple function reference - declaration
void foo();
int bar() {
fo^o();
}
)cpp",
- {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}
- },
- {
- R"cpp( // Simple function reference - definition
+ {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+ {
+ R"cpp( // Simple function reference - definition
void foo() {}
int bar() {
fo^o();
}
)cpp",
- {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}
- },
- {
- R"cpp( // Function in namespace reference
+ {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+ {
+ R"cpp( // Function in namespace reference
namespace bar {
void foo();
int baz() {
@@ -64,10 +60,9 @@ TEST(SymbolInfoTests, All) {
}
}
)cpp",
- {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}
- },
- {
- R"cpp( // Function in different namespace reference
+ {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+ {
+ R"cpp( // Function in different namespace reference
namespace bar {
void foo();
}
@@ -77,10 +72,9 @@ TEST(SymbolInfoTests, All) {
}
}
)cpp",
- {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}
- },
- {
- R"cpp( // Function in global namespace reference
+ {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+ {
+ R"cpp( // Function in global namespace reference
void foo();
namespace Nbar {
namespace Nbaz {
@@ -90,10 +84,9 @@ TEST(SymbolInfoTests, All) {
}
}
)cpp",
- {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}
- },
- {
- R"cpp( // Function in anonymous namespace reference
+ {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+ {
+ R"cpp( // Function in anonymous namespace reference
namespace {
void foo();
}
@@ -103,10 +96,10 @@ TEST(SymbolInfoTests, All) {
}
}
)cpp",
- {CreateExpectedSymbolDetails("foo", "(anonymous)", "c:TestTU.cpp@aN@F@foo#")}
- },
- {
- R"cpp( // Function reference - ADL
+ {CreateExpectedSymbolDetails("foo", "(anonymous)",
+ "c:TestTU.cpp@aN@F@foo#")}},
+ {
+ R"cpp( // Function reference - ADL
namespace bar {
struct BarType {};
void foo(const BarType&);
@@ -118,49 +111,53 @@ TEST(SymbolInfoTests, All) {
}
}
)cpp",
- {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#&1$@N@bar@S@BarType#")}
- },
- {
- R"cpp( // Global value reference
+ {CreateExpectedSymbolDetails(
+ "foo", "bar::", "c:@N@bar@F@foo#&1$@N@bar@S@BarType#")}},
+ {
+ R"cpp( // Global value reference
int value;
void foo(int) { }
void bar() {
foo(val^ue);
}
)cpp",
- {CreateExpectedSymbolDetails("value", "", "c:@value")}
- },
- {
- R"cpp( // Local value reference
+ {CreateExpectedSymbolDetails("value", "", "c:@value")}},
+ {
+ R"cpp( // Local value reference
void foo() { int aaa; int bbb = aa^a; }
)cpp",
- {CreateExpectedSymbolDetails("aaa", "foo", "c:TestTU.cpp@49@F@foo#@aaa")}
- },
- {
- R"cpp( // Function param
+ {CreateExpectedSymbolDetails("aaa", "foo",
+ "c:TestTU.cpp@49@F@foo#@aaa")}},
+ {
+ R"cpp( // Function param
void bar(int aaa) {
int bbb = a^aa;
}
)cpp",
- {CreateExpectedSymbolDetails("aaa", "bar", "c:TestTU.cpp@38@F@bar#I#@aaa")}
- },
- {
- R"cpp( // Lambda capture
+ {CreateExpectedSymbolDetails("aaa", "bar",
+ "c:TestTU.cpp@38@F@bar#I#@aaa")}},
+ {
+ R"cpp( // Lambda capture
int ii;
auto lam = [ii]() {
return i^i;
};
)cpp",
- {CreateExpectedSymbolDetails("ii", "", "c:@ii")}
- },
- {
- R"cpp( // Macro reference
+ {CreateExpectedSymbolDetails("ii", "", "c:@ii")}},
+ {
+ R"cpp( // Macro reference
#define MACRO 5\nint i = MAC^RO;
)cpp",
- {CreateExpectedSymbolDetails("MACRO", "", "c:TestTU.cpp@55@macro@MACRO")}
- },
- {
- R"cpp( // Multiple symbols returned - using overloaded function name
+ {CreateExpectedSymbolDetails("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() {}
void foo(bool) {}
void foo(int) {}
@@ -168,14 +165,11 @@ TEST(SymbolInfoTests, All) {
using ::fo^o;
}
)cpp",
- {
- CreateExpectedSymbolDetails("foo", "", "c:@F@foo#"),
- CreateExpectedSymbolDetails("foo", "", "c:@F@foo#b#"),
- CreateExpectedSymbolDetails("foo", "", "c:@F@foo#I#")
- }
- },
- {
- R"cpp( // Multiple symbols returned - implicit conversion
+ {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#"),
+ CreateExpectedSymbolDetails("foo", "", "c:@F@foo#b#"),
+ CreateExpectedSymbolDetails("foo", "", "c:@F@foo#I#")}},
+ {
+ R"cpp( // Multiple symbols returned - implicit conversion
struct foo {};
struct bar {
bar(const foo&) {}
@@ -186,53 +180,49 @@ 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#"),
- }
- },
- {
- R"cpp( // Type reference - declaration
+ {
+ CreateExpectedSymbolDetails(
+ "ff", "func_baz2", "c:TestTU.cpp@218@F@func_baz2#@ff"),
+ CreateExpectedSymbolDetails(
+ "bar", "bar::", "c:@S@bar@F@bar#&1$@S@foo#"),
+ }},
+ {
+ R"cpp( // Type reference - declaration
struct foo;
void bar(fo^o*);
)cpp",
- {CreateExpectedSymbolDetails("foo", "", "c:@S@foo")}
- },
- {
- R"cpp( // Type reference - definition
+ {CreateExpectedSymbolDetails("foo", "", "c:@S@foo")}},
+ {
+ R"cpp( // Type reference - definition
struct foo {};
void bar(fo^o*);
)cpp",
- {CreateExpectedSymbolDetails("foo", "", "c:@S@foo")}
- },
- {
- R"cpp( // Type Reference - template argumen
+ {CreateExpectedSymbolDetails("foo", "", "c:@S@foo")}},
+ {
+ R"cpp( // Type Reference - template argumen
struct foo {};
template<class T> struct bar {};
void baz() {
bar<fo^o> b;
}
)cpp",
- {CreateExpectedSymbolDetails("foo", "", "c:@S@foo")}
- },
- {
- R"cpp( // Template parameter reference - type param
+ {CreateExpectedSymbolDetails("foo", "", "c:@S@foo")}},
+ {
+ R"cpp( // Template parameter reference - type param
template<class TT> struct bar {
T^T t;
};
)cpp",
- { /* not implemented */ }
- },
- {
- R"cpp( // Template parameter reference - type param
+ {/* not implemented */}},
+ {
+ R"cpp( // Template parameter reference - type param
template<int NN> struct bar {
int a = N^N;
};
)cpp",
- { /* not implemented */ }
- },
- {
- R"cpp( // Class member reference - objec
+ {/* not implemented */}},
+ {
+ R"cpp( // Class member reference - objec
struct foo {
int aa;
};
@@ -241,10 +231,9 @@ TEST(SymbolInfoTests, All) {
f.a^a;
}
)cpp",
- {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@FI@aa")}
- },
- {
- R"cpp( // Class member reference - pointer
+ {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@FI@aa")}},
+ {
+ R"cpp( // Class member reference - pointer
struct foo {
int aa;
};
@@ -252,10 +241,9 @@ TEST(SymbolInfoTests, All) {
&foo::a^a;
}
)cpp",
- {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@FI@aa")}
- },
- {
- R"cpp( // Class method reference - objec
+ {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@FI@aa")}},
+ {
+ R"cpp( // Class method reference - objec
struct foo {
void aa() {}
};
@@ -264,10 +252,9 @@ TEST(SymbolInfoTests, All) {
f.a^a();
}
)cpp",
- {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@F@aa#")}
- },
- {
- R"cpp( // Class method reference - pointer
+ {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@F@aa#")}},
+ {
+ R"cpp( // Class method reference - pointer
struct foo {
void aa() {}
};
@@ -275,72 +262,70 @@ TEST(SymbolInfoTests, All) {
&foo::a^a;
}
)cpp",
- {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@F@aa#")}
- },
- {
- R"cpp( // Typedef
+ {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@F@aa#")}},
+ {
+ R"cpp( // Typedef
typedef int foo;
void bar() {
fo^o a;
}
)cpp",
- {CreateExpectedSymbolDetails("foo", "", "c:TestTU.cpp@T@foo")}
- },
- {
- R"cpp( // Type alias
+ {CreateExpectedSymbolDetails("foo", "", "c:TestTU.cpp@T@foo")}},
+ {
+ R"cpp( // Type alias
using foo = int;
void bar() {
fo^o a;
}
)cpp",
- {CreateExpectedSymbolDetails("foo", "", "c:@foo")}
- },
- {
- R"cpp( // Namespace reference
+ {CreateExpectedSymbolDetails("foo", "", "c:@foo")}},
+ {
+ R"cpp( // Namespace reference
namespace foo {}
using namespace fo^o;
)cpp",
- {CreateExpectedSymbolDetails("foo", "", "c:@N@foo")}
- },
- {
- R"cpp( // Enum value reference
+ {CreateExpectedSymbolDetails("foo", "", "c:@N@foo")}},
+ {
+ R"cpp( // Enum value reference
enum foo { bar, baz };
void f() {
foo fff = ba^r;
}
)cpp",
- {CreateExpectedSymbolDetails("bar", "foo", "c:@E@foo@bar")}
- },
- {
- R"cpp( // Enum class value reference
+ {CreateExpectedSymbolDetails("bar", "foo", "c:@E@foo@bar")}},
+ {
+ R"cpp( // Enum class value reference
enum class foo { bar, baz };
void f() {
foo fff = foo::ba^r;
}
)cpp",
- {CreateExpectedSymbolDetails("bar", "foo::", "c:@E@foo@bar")}
- },
- {
- R"cpp( // Type inferrence with auto keyword
+ {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{}; }
void f() {
au^to a = getfoo();
}
)cpp",
- {/* not implemented */}
- },
- {
- R"cpp( // decltype
+ {/* not implemented */}},
+ {
+ R"cpp( // decltype
struct foo {};
void f() {
foo f;
declt^ype(f);
}
)cpp",
- {/* not implemented */}
- },
- };
+ {/* not implemented */}},
+ };
for (const auto &T : TestInputExpectedOutput) {
Annotations TestInput(T.first);
diff --git a/unittests/clangd/SyncAPI.cpp b/unittests/clangd/SyncAPI.cpp
index cebff42d..91e7a919 100644
--- a/unittests/clangd/SyncAPI.cpp
+++ b/unittests/clangd/SyncAPI.cpp
@@ -1,21 +1,19 @@
//===--- 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
//
//===----------------------------------------------------------------------===//
#include "SyncAPI.h"
#include "index/Index.h"
-using namespace llvm;
namespace clang {
namespace clangd {
-void runAddDocument(ClangdServer &Server, PathRef File, StringRef Contents,
- WantDiagnostics WantDiags) {
+void runAddDocument(ClangdServer &Server, PathRef File,
+ llvm::StringRef Contents, WantDiagnostics WantDiags) {
Server.addDocument(File, Contents, WantDiags);
if (!Server.blockUntilIdleForTest())
llvm_unreachable("not idle after addDocument");
@@ -27,7 +25,7 @@ namespace {
/// T Result;
/// someAsyncFunc(Param1, Param2, /*Callback=*/capture(Result));
template <typename T> struct CaptureProxy {
- CaptureProxy(Optional<T> &Target) : Target(&Target) {
+ CaptureProxy(llvm::Optional<T> &Target) : Target(&Target) {
assert(!Target.hasValue());
}
@@ -39,7 +37,7 @@ template <typename T> struct CaptureProxy {
}
CaptureProxy &operator=(CaptureProxy &&) = delete;
- operator unique_function<void(T)>() && {
+ operator llvm::unique_function<void(T)>() && {
assert(!Future.valid() && "conversion to callback called multiple times");
Future = Promise.get_future();
return Bind(
@@ -58,7 +56,7 @@ template <typename T> struct CaptureProxy {
}
private:
- Optional<T> *Target;
+ llvm::Optional<T> *Target;
// Using shared_ptr to workaround compilation errors with MSVC.
// MSVC only allows default-construcitble and copyable objects as future<>
// arguments.
@@ -66,68 +64,69 @@ private:
std::future<std::shared_ptr<T>> Future;
};
-template <typename T> CaptureProxy<T> capture(Optional<T> &Target) {
+template <typename T> CaptureProxy<T> capture(llvm::Optional<T> &Target) {
return CaptureProxy<T>(Target);
}
} // namespace
-Expected<CodeCompleteResult> runCodeComplete(ClangdServer &Server, PathRef File,
- Position Pos,
- clangd::CodeCompleteOptions Opts) {
- Optional<Expected<CodeCompleteResult>> Result;
+llvm::Expected<CodeCompleteResult>
+runCodeComplete(ClangdServer &Server, PathRef File, Position Pos,
+ clangd::CodeCompleteOptions Opts) {
+ llvm::Optional<llvm::Expected<CodeCompleteResult>> Result;
Server.codeComplete(File, Pos, Opts, capture(Result));
return std::move(*Result);
}
-Expected<SignatureHelp> runSignatureHelp(ClangdServer &Server, PathRef File,
- Position Pos) {
- Optional<Expected<SignatureHelp>> Result;
+llvm::Expected<SignatureHelp> runSignatureHelp(ClangdServer &Server,
+ PathRef File, Position Pos) {
+ llvm::Optional<llvm::Expected<SignatureHelp>> Result;
Server.signatureHelp(File, Pos, capture(Result));
return std::move(*Result);
}
-Expected<std::vector<Location>> runFindDefinitions(ClangdServer &Server,
- PathRef File, Position Pos) {
- Optional<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);
}
-Expected<std::vector<DocumentHighlight>>
+llvm::Expected<std::vector<DocumentHighlight>>
runFindDocumentHighlights(ClangdServer &Server, PathRef File, Position Pos) {
- Optional<Expected<std::vector<DocumentHighlight>>> Result;
+ llvm::Optional<llvm::Expected<std::vector<DocumentHighlight>>> Result;
Server.findDocumentHighlights(File, Pos, capture(Result));
return std::move(*Result);
}
-Expected<std::vector<tooling::Replacement>>
-runRename(ClangdServer &Server, PathRef File, Position Pos, StringRef NewName) {
- Optional<Expected<std::vector<tooling::Replacement>>> 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;
Server.rename(File, Pos, NewName, capture(Result));
return std::move(*Result);
}
std::string runDumpAST(ClangdServer &Server, PathRef File) {
- Optional<std::string> Result;
+ llvm::Optional<std::string> Result;
Server.dumpAST(File, capture(Result));
return std::move(*Result);
}
-Expected<std::vector<SymbolInformation>>
-runWorkspaceSymbols(ClangdServer &Server, StringRef Query, int Limit) {
- Optional<Expected<std::vector<SymbolInformation>>> Result;
+llvm::Expected<std::vector<SymbolInformation>>
+runWorkspaceSymbols(ClangdServer &Server, llvm::StringRef Query, int Limit) {
+ llvm::Optional<llvm::Expected<std::vector<SymbolInformation>>> Result;
Server.workspaceSymbols(Query, Limit, capture(Result));
return std::move(*Result);
}
-Expected<std::vector<DocumentSymbol>> runDocumentSymbols(ClangdServer &Server,
- PathRef File) {
- Optional<Expected<std::vector<DocumentSymbol>>> Result;
+llvm::Expected<std::vector<DocumentSymbol>>
+runDocumentSymbols(ClangdServer &Server, PathRef File) {
+ llvm::Optional<llvm::Expected<std::vector<DocumentSymbol>>> Result;
Server.documentSymbols(File, capture(Result));
return std::move(*Result);
}
-SymbolSlab runFuzzyFind(const SymbolIndex &Index, StringRef Query) {
+SymbolSlab runFuzzyFind(const SymbolIndex &Index, llvm::StringRef Query) {
FuzzyFindRequest Req;
Req.Query = Query;
Req.AnyScope = true;
@@ -148,6 +147,5 @@ RefSlab getRefs(const SymbolIndex &Index, SymbolID ID) {
return std::move(Slab).build();
}
-
} // namespace clangd
} // namespace clang
diff --git a/unittests/clangd/SyncAPI.h b/unittests/clangd/SyncAPI.h
index f336e615..8de9c053 100644
--- a/unittests/clangd/SyncAPI.h
+++ b/unittests/clangd/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,8 +32,8 @@ 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);
diff --git a/unittests/clangd/TUSchedulerTests.cpp b/unittests/clangd/TUSchedulerTests.cpp
index b26a7dd0..6c71bf45 100644
--- a/unittests/clangd/TUSchedulerTests.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -12,13 +11,12 @@
#include "Matchers.h"
#include "TUScheduler.h"
#include "TestFS.h"
-#include "gmock/gmock.h"
#include "llvm/ADT/ScopeExit.h"
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <algorithm>
#include <utility>
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
@@ -28,7 +26,6 @@ using ::testing::AllOf;
using ::testing::AnyOf;
using ::testing::Each;
using ::testing::ElementsAre;
-using ::testing::Pair;
using ::testing::Pointee;
using ::testing::UnorderedElementsAre;
@@ -39,12 +36,16 @@ 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, StringRef Contents,
- WantDiagnostics WD,
+ void updateWithCallback(TUScheduler &S, PathRef File,
+ llvm::StringRef Contents, WantDiagnostics WD,
llvm::unique_function<void()> CB) {
WithContextValue Ctx(llvm::make_scope_exit(std::move(CB)));
S.update(File, getInputs(File, Contents), WD);
@@ -93,8 +94,8 @@ protected:
std::move(CB));
}
- StringMap<std::string> Files;
- StringMap<time_t> Timestamps;
+ llvm::StringMap<std::string> Files;
+ llvm::StringMap<time_t> Timestamps;
MockCompilationDatabase CDB;
};
@@ -389,22 +390,20 @@ TEST_F(TUSchedulerTests, ManyUpdates) {
}
{
WithContextValue WithNonce(NonceKey, ++Nonce);
- S.runWithAST("CheckAST", File,
- [File, Inputs, Nonce, &Mut,
- &TotalASTReads](Expected<InputsAndAST> AST) {
- EXPECT_THAT(Context::current().get(NonceKey),
- Pointee(Nonce));
-
- ASSERT_TRUE((bool)AST);
- EXPECT_EQ(AST->Inputs.FS, Inputs.FS);
- EXPECT_EQ(AST->Inputs.Contents, Inputs.Contents);
-
- std::lock_guard<std::mutex> Lock(Mut);
- ++TotalASTReads;
- EXPECT_EQ(
- File,
- *TUScheduler::getFileBeingProcessedInContext());
- });
+ S.runWithAST(
+ "CheckAST", File,
+ [File, Inputs, Nonce, &Mut,
+ &TotalASTReads](Expected<InputsAndAST> AST) {
+ EXPECT_THAT(Context::current().get(NonceKey), Pointee(Nonce));
+
+ ASSERT_TRUE((bool)AST);
+ EXPECT_EQ(AST->Inputs.FS, Inputs.FS);
+ EXPECT_EQ(AST->Inputs.Contents, Inputs.Contents);
+
+ std::lock_guard<std::mutex> Lock(Mut);
+ ++TotalASTReads;
+ EXPECT_EQ(File, *TUScheduler::getFileBeingProcessedInContext());
+ });
}
{
@@ -505,14 +504,14 @@ TEST_F(TUSchedulerTests, EmptyPreamble) {
)cpp";
auto WithEmptyPreamble = R"cpp(int main() {})cpp";
S.update(Foo, getInputs(Foo, WithPreamble), WantDiagnostics::Auto);
- S.runWithPreamble("getNonEmptyPreamble", Foo, TUScheduler::Stale,
- [&](Expected<InputsAndPreamble> Preamble) {
- // We expect to get a non-empty preamble.
- EXPECT_GT(cantFail(std::move(Preamble))
- .Preamble->Preamble.getBounds()
- .Size,
- 0u);
- });
+ S.runWithPreamble(
+ "getNonEmptyPreamble", Foo, TUScheduler::Stale,
+ [&](Expected<InputsAndPreamble> Preamble) {
+ // We expect to get a non-empty preamble.
+ EXPECT_GT(
+ cantFail(std::move(Preamble)).Preamble->Preamble.getBounds().Size,
+ 0u);
+ });
// Wait for the preamble is being built.
ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(10)));
@@ -520,14 +519,14 @@ TEST_F(TUSchedulerTests, EmptyPreamble) {
S.update(Foo, getInputs(Foo, WithEmptyPreamble), WantDiagnostics::Auto);
// Wait for the preamble is being built.
ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(10)));
- S.runWithPreamble("getEmptyPreamble", Foo, TUScheduler::Stale,
- [&](Expected<InputsAndPreamble> Preamble) {
- // We expect to get an empty preamble.
- EXPECT_EQ(cantFail(std::move(Preamble))
- .Preamble->Preamble.getBounds()
- .Size,
- 0u);
- });
+ S.runWithPreamble(
+ "getEmptyPreamble", Foo, TUScheduler::Stale,
+ [&](Expected<InputsAndPreamble> Preamble) {
+ // We expect to get an empty preamble.
+ EXPECT_EQ(
+ cantFail(std::move(Preamble)).Preamble->Preamble.getBounds().Size,
+ 0u);
+ });
}
TEST_F(TUSchedulerTests, RunWaitsForPreamble) {
@@ -688,10 +687,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/unittests/clangd/TestFS.cpp
index 1c845b99..c5b2613f 100644
--- a/unittests/clangd/TestFS.cpp
+++ b/unittests/clangd/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"
@@ -14,37 +13,36 @@
namespace clang {
namespace clangd {
-using namespace llvm;
-IntrusiveRefCntPtr<vfs::FileSystem>
-buildTestFS(StringMap<std::string> const &Files,
- StringMap<time_t> const &Timestamps) {
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem> MemFS(
- new vfs::InMemoryFileSystem);
+llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+buildTestFS(llvm::StringMap<std::string> const &Files,
+ llvm::StringMap<time_t> const &Timestamps) {
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> MemFS(
+ new llvm::vfs::InMemoryFileSystem);
MemFS->setCurrentWorkingDirectory(testRoot());
for (auto &FileAndContents : Files) {
- StringRef File = FileAndContents.first();
+ llvm::StringRef File = FileAndContents.first();
MemFS->addFile(
File, Timestamps.lookup(File),
- MemoryBuffer::getMemBufferCopy(FileAndContents.second, File));
+ llvm::MemoryBuffer::getMemBufferCopy(FileAndContents.second, File));
}
return MemFS;
}
-MockCompilationDatabase::MockCompilationDatabase(StringRef Directory,
- StringRef RelPathPrefix)
+MockCompilationDatabase::MockCompilationDatabase(llvm::StringRef Directory,
+ llvm::StringRef RelPathPrefix)
: ExtraClangFlags({"-ffreestanding"}), Directory(Directory),
RelPathPrefix(RelPathPrefix) {
// -ffreestanding avoids implicit stdc-predef.h.
}
-Optional<tooling::CompileCommand>
+llvm::Optional<tooling::CompileCommand>
MockCompilationDatabase::getCompileCommand(PathRef File,
ProjectInfo *Project) const {
if (ExtraClangFlags.empty())
return None;
- auto FileName = sys::path::filename(File);
+ auto FileName = llvm::sys::path::filename(File);
// Build the compile command.
auto CommandLine = ExtraClangFlags;
@@ -54,16 +52,17 @@ MockCompilationDatabase::getCompileCommand(PathRef File,
CommandLine.push_back(File);
} else {
// Build a relative path using RelPathPrefix.
- SmallString<32> RelativeFilePath(RelPathPrefix);
- sys::path::append(RelativeFilePath, FileName);
+ llvm::SmallString<32> RelativeFilePath(RelPathPrefix);
+ llvm::sys::path::append(RelativeFilePath, FileName);
CommandLine.push_back(RelativeFilePath.str());
}
if (Project)
Project->SourceRoot = Directory;
- return {tooling::CompileCommand(
- Directory != StringRef() ? Directory : sys::path::parent_path(File),
- FileName, std::move(CommandLine), "")};
+ return {tooling::CompileCommand(Directory != llvm::StringRef()
+ ? Directory
+ : llvm::sys::path::parent_path(File),
+ FileName, std::move(CommandLine), "")};
}
const char *testRoot() {
@@ -75,12 +74,12 @@ const char *testRoot() {
}
std::string testPath(PathRef File) {
- assert(sys::path::is_relative(File) && "FileName should be relative");
+ assert(llvm::sys::path::is_relative(File) && "FileName should be relative");
- SmallString<32> NativeFile = File;
- sys::path::native(NativeFile);
- SmallString<32> Path;
- sys::path::append(Path, testRoot(), NativeFile);
+ llvm::SmallString<32> NativeFile = File;
+ llvm::sys::path::native(NativeFile);
+ llvm::SmallString<32> Path;
+ llvm::sys::path::append(Path, testRoot(), NativeFile);
return Path.str();
}
@@ -91,29 +90,32 @@ class TestScheme : public URIScheme {
public:
static const char *Scheme;
- Expected<std::string> getAbsolutePath(StringRef /*Authority*/, StringRef Body,
- StringRef HintPath) const override {
+ llvm::Expected<std::string>
+ getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body,
+ llvm::StringRef HintPath) const override {
if (!HintPath.startswith(testRoot()))
- return make_error<StringError>(
+ return llvm::make_error<llvm::StringError>(
"Hint path doesn't start with test root: " + HintPath,
- inconvertibleErrorCode());
+ llvm::inconvertibleErrorCode());
if (!Body.consume_front("/"))
- return make_error<StringError>(
+ return llvm::make_error<llvm::StringError>(
"Body of an unittest: URI must start with '/'",
- inconvertibleErrorCode());
- SmallString<16> Path(Body.begin(), Body.end());
- sys::path::native(Path);
+ llvm::inconvertibleErrorCode());
+ llvm::SmallString<16> Path(Body.begin(), Body.end());
+ llvm::sys::path::native(Path);
return testPath(Path);
}
- Expected<URI> uriFromAbsolutePath(StringRef AbsolutePath) const override {
- StringRef Body = AbsolutePath;
+ llvm::Expected<URI>
+ uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override {
+ llvm::StringRef Body = AbsolutePath;
if (!Body.consume_front(testRoot()))
- return make_error<StringError>(AbsolutePath + "does not start with " +
- testRoot(),
- inconvertibleErrorCode());
+ return llvm::make_error<llvm::StringError>(
+ AbsolutePath + "does not start with " + testRoot(),
+ llvm::inconvertibleErrorCode());
- return URI(Scheme, /*Authority=*/"", sys::path::convert_to_slash(Body));
+ return URI(Scheme, /*Authority=*/"",
+ llvm::sys::path::convert_to_slash(Body));
}
};
diff --git a/unittests/clangd/TestFS.h b/unittests/clangd/TestFS.h
index 0226fc3d..eabdddf7 100644
--- a/unittests/clangd/TestFS.h
+++ b/unittests/clangd/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/unittests/clangd/TestIndex.cpp b/unittests/clangd/TestIndex.cpp
index 2043f61e..877bb75e 100644
--- a/unittests/clangd/TestIndex.cpp
+++ b/unittests/clangd/TestIndex.cpp
@@ -1,35 +1,87 @@
//===-- IndexHelpers.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 "TestIndex.h"
+#include "clang/Index/IndexSymbol.h"
+#include "llvm/Support/Regex.h"
-using namespace llvm;
namespace clang {
namespace clangd {
-Symbol symbol(StringRef QName) {
+Symbol symbol(llvm::StringRef QName) {
Symbol Sym;
Sym.ID = SymbolID(QName.str());
size_t Pos = QName.rfind("::");
- if (Pos == StringRef::npos) {
+ 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) {
+ 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
}
+ 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 (StringRef QName : QualifiedNames)
+ for (llvm::StringRef QName : QualifiedNames)
Slab.insert(symbol(QName));
return std::move(Slab).build();
}
@@ -57,7 +109,8 @@ std::vector<std::string> match(const SymbolIndex &I,
}
// Returns qualified names of symbols with any of IDs in the index.
-std::vector<std::string> lookup(const SymbolIndex &I, ArrayRef<SymbolID> IDs) {
+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;
diff --git a/unittests/clangd/TestIndex.h b/unittests/clangd/TestIndex.h
index 01dcc086..01de089e 100644
--- a/unittests/clangd/TestIndex.h
+++ b/unittests/clangd/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/TestTU.cpp b/unittests/clangd/TestTU.cpp
index 4e14262e..c2f0d897 100644
--- a/unittests/clangd/TestTU.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -16,7 +15,6 @@
#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Frontend/Utils.h"
-using namespace llvm;
namespace clang {
namespace clangd {
@@ -37,6 +35,11 @@ ParsedAST TestTU::build() const {
Inputs.CompileCommand.Directory = testRoot();
Inputs.Contents = Code;
Inputs.FS = buildTestFS({{FullFilename, Code}, {FullHeaderName, HeaderCode}});
+ Inputs.Opts = ParseOptions();
+ Inputs.Opts.ClangTidyOpts.Checks = ClangTidyChecks;
+ Inputs.Index = ExternalIndex;
+ if (Inputs.Index)
+ Inputs.Opts.SuggestMissingIncludes = true;
auto PCHs = std::make_shared<PCHContainerOperations>();
auto CI = buildCompilerInvocation(Inputs);
assert(CI && "Failed to build compilation invocation.");
@@ -56,18 +59,20 @@ 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);
}
-const Symbol &findSymbol(const SymbolSlab &Slab, StringRef QName) {
+const Symbol &findSymbol(const SymbolSlab &Slab, llvm::StringRef QName) {
const Symbol *Result = nullptr;
for (const Symbol &S : Slab) {
if (QName != (S.Scope + S.Name).str())
@@ -88,13 +93,13 @@ const Symbol &findSymbol(const SymbolSlab &Slab, StringRef QName) {
return *Result;
}
-const NamedDecl &findDecl(ParsedAST &AST, StringRef QName) {
- SmallVector<StringRef, 4> Components;
+const NamedDecl &findDecl(ParsedAST &AST, llvm::StringRef QName) {
+ llvm::SmallVector<llvm::StringRef, 4> Components;
QName.split(Components, "::");
auto &Ctx = AST.getASTContext();
auto LookupDecl = [&Ctx](const DeclContext &Scope,
- StringRef Name) -> const NamedDecl & {
+ llvm::StringRef Name) -> const NamedDecl & {
auto LookupRes = Scope.lookup(DeclarationName(&Ctx.Idents.get(Name)));
assert(!LookupRes.empty() && "Lookup failed");
assert(LookupRes.size() == 1 && "Lookup returned multiple results");
@@ -113,7 +118,7 @@ const NamedDecl &findDecl(ParsedAST &AST,
std::function<bool(const NamedDecl &)> Filter) {
struct Visitor : RecursiveASTVisitor<Visitor> {
decltype(Filter) F;
- SmallVector<const NamedDecl *, 1> Decls;
+ llvm::SmallVector<const NamedDecl *, 1> Decls;
bool VisitNamedDecl(const NamedDecl *ND) {
if (F(*ND))
Decls.push_back(ND);
@@ -129,7 +134,7 @@ const NamedDecl &findDecl(ParsedAST &AST,
return *Visitor.Decls.front();
}
-const NamedDecl &findUnqualifiedDecl(ParsedAST &AST, StringRef Name) {
+const NamedDecl &findUnqualifiedDecl(ParsedAST &AST, llvm::StringRef Name) {
return findDecl(AST, [Name](const NamedDecl &ND) {
if (auto *ID = ND.getIdentifier())
if (ID->getName() == Name)
diff --git a/unittests/clangd/TestTU.h b/unittests/clangd/TestTU.h
index ced612fa..beed124c 100644
--- a/unittests/clangd/TestTU.h
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
//
@@ -49,6 +48,10 @@ struct TestTU {
// 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;
+
ParsedAST build() const;
SymbolSlab headerSymbols() const;
std::unique_ptr<SymbolIndex> index() const;
diff --git a/unittests/clangd/ThreadingTests.cpp b/unittests/clangd/ThreadingTests.cpp
index dd27dcce..18b9146e 100644
--- a/unittests/clangd/ThreadingTests.cpp
+++ b/unittests/clangd/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/unittests/clangd/TraceTests.cpp
index 0a2697ff..1871e6ac 100644
--- a/unittests/clangd/TraceTests.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -17,32 +16,32 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
MATCHER_P(StringNode, Val, "") {
- if (arg->getType() != yaml::Node::NK_Scalar) {
+ if (arg->getType() != llvm::yaml::Node::NK_Scalar) {
*result_listener << "is a " << arg->getVerbatimTag();
return false;
}
- SmallString<32> S;
- return Val == static_cast<yaml::ScalarNode *>(arg)->getValue(S);
+ llvm::SmallString<32> S;
+ return Val == static_cast<llvm::yaml::ScalarNode *>(arg)->getValue(S);
}
// Checks that N is a Mapping (JS object) with the expected scalar properties.
// The object must have all the Expected properties, but may have others.
-bool VerifyObject(yaml::Node &N, std::map<std::string, std::string> Expected) {
- auto *M = dyn_cast<yaml::MappingNode>(&N);
+bool VerifyObject(llvm::yaml::Node &N,
+ std::map<std::string, std::string> Expected) {
+ auto *M = llvm::dyn_cast<llvm::yaml::MappingNode>(&N);
if (!M) {
ADD_FAILURE() << "Not an object";
return false;
}
bool Match = true;
- SmallString<32> Tmp;
+ llvm::SmallString<32> Tmp;
for (auto &Prop : *M) {
- auto *K = dyn_cast_or_null<yaml::ScalarNode>(Prop.getKey());
+ auto *K = llvm::dyn_cast_or_null<llvm::yaml::ScalarNode>(Prop.getKey());
if (!K)
continue;
std::string KS = K->getValue(Tmp).str();
@@ -50,7 +49,7 @@ bool VerifyObject(yaml::Node &N, std::map<std::string, std::string> Expected) {
if (I == Expected.end())
continue; // Ignore properties with no assertion.
- auto *V = dyn_cast_or_null<yaml::ScalarNode>(Prop.getValue());
+ auto *V = llvm::dyn_cast_or_null<llvm::yaml::ScalarNode>(Prop.getValue());
if (!V) {
ADD_FAILURE() << KS << " is not a string";
Match = false;
@@ -73,7 +72,7 @@ TEST(TraceTest, SmokeTest) {
// Capture some events.
std::string JSON;
{
- raw_string_ostream OS(JSON);
+ llvm::raw_string_ostream OS(JSON);
auto JSONTracer = trace::createJSONTracer(OS);
trace::Session Session(*JSONTracer);
{
@@ -83,15 +82,15 @@ TEST(TraceTest, SmokeTest) {
}
// Get the root JSON object using the YAML parser.
- SourceMgr SM;
- yaml::Stream Stream(JSON, SM);
+ llvm::SourceMgr SM;
+ llvm::yaml::Stream Stream(JSON, SM);
auto Doc = Stream.begin();
ASSERT_NE(Doc, Stream.end());
- auto *Root = dyn_cast_or_null<yaml::MappingNode>(Doc->getRoot());
+ auto *Root = llvm::dyn_cast_or_null<llvm::yaml::MappingNode>(Doc->getRoot());
ASSERT_NE(Root, nullptr) << "Root should be an object";
// Check whether we expect thread name events on this platform.
- SmallString<32> ThreadName;
+ llvm::SmallString<32> ThreadName;
get_thread_name(ThreadName);
bool ThreadsHaveNames = !ThreadName.empty();
@@ -105,7 +104,8 @@ TEST(TraceTest, SmokeTest) {
EXPECT_THAT(Prop->getValue(), StringNode("ns"));
ASSERT_NE(++Prop, Root->end()) << "Expected traceEvents property";
EXPECT_THAT(Prop->getKey(), StringNode("traceEvents"));
- auto *Events = dyn_cast_or_null<yaml::SequenceNode>(Prop->getValue());
+ auto *Events =
+ llvm::dyn_cast_or_null<llvm::yaml::SequenceNode>(Prop->getValue());
ASSERT_NE(Events, nullptr) << "traceEvents should be an array";
auto Event = Events->begin();
ASSERT_NE(Event, Events->end()) << "Expected process name";
diff --git a/unittests/clangd/TweakTests.cpp b/unittests/clangd/TweakTests.cpp
new file mode 100644
index 00000000..baa60292
--- /dev/null
+++ b/unittests/clangd/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/unittests/clangd/URITests.cpp b/unittests/clangd/URITests.cpp
index 302affd2..52ca7b44 100644
--- a/unittests/clangd/URITests.cpp
+++ b/unittests/clangd/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
//
//===----------------------------------------------------------------------===//
@@ -13,7 +12,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-using namespace llvm;
namespace clang {
namespace clangd {
@@ -29,14 +27,15 @@ MATCHER_P(Scheme, S, "") { return arg.scheme() == S; }
MATCHER_P(Authority, A, "") { return arg.authority() == A; }
MATCHER_P(Body, B, "") { return arg.body() == B; }
-std::string createOrDie(StringRef AbsolutePath, StringRef Scheme = "file") {
+std::string createOrDie(llvm::StringRef AbsolutePath,
+ llvm::StringRef Scheme = "file") {
auto Uri = URI::create(AbsolutePath, Scheme);
if (!Uri)
llvm_unreachable(toString(Uri.takeError()).c_str());
return Uri->toString();
}
-URI parseOrDie(StringRef Uri) {
+URI parseOrDie(llvm::StringRef Uri) {
auto U = URI::parse(Uri);
if (!U)
llvm_unreachable(toString(U.takeError()).c_str());
@@ -61,7 +60,7 @@ TEST(PercentEncodingTest, Decode) {
EXPECT_EQ(parseOrDie("x:a:b%3bc").body(), "a:b;c");
}
-std::string resolveOrDie(const URI &U, StringRef HintPath = "") {
+std::string resolveOrDie(const URI &U, llvm::StringRef HintPath = "") {
auto Path = URI::resolve(U, HintPath);
if (!Path)
llvm_unreachable(toString(Path.takeError()).c_str());
@@ -137,7 +136,8 @@ TEST(URITest, Resolve) {
testPath("a"));
}
-std::string resolvePathOrDie(StringRef AbsPath, StringRef HintPath = "") {
+std::string resolvePathOrDie(llvm::StringRef AbsPath,
+ llvm::StringRef HintPath = "") {
auto Path = URI::resolvePath(AbsPath, HintPath);
if (!Path)
llvm_unreachable(toString(Path.takeError()).c_str());
diff --git a/unittests/clangd/XRefsTests.cpp b/unittests/clangd/XRefsTests.cpp
index ffb0d051..fea90137 100644
--- a/unittests/clangd/XRefsTests.cpp
+++ b/unittests/clangd/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,16 +17,15 @@
#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"
-using namespace llvm;
namespace clang {
namespace clangd {
namespace {
using testing::ElementsAre;
-using testing::Field;
using testing::IsEmpty;
using testing::Matcher;
using testing::UnorderedElementsAreArray;
@@ -88,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);
@@ -97,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]] {};
@@ -117,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.
@@ -128,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]]() {}
@@ -138,29 +165,50 @@ 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 $[[Proto]] {};
+ )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]];
+ P^roto* create();
+ )cpp");
+
+ auto AST = TestTU::withCode(Test.code()).build();
+ auto Locs = clangd::locateSymbolAt(AST, Test.point(), Index.get());
+ EXPECT_THAT(Locs, ElementsAre(Sym("Proto", SymbolHeader.range())));
}
-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 +235,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 +271,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,7 +279,7 @@ TEST(GoToDefinition, All) {
)cpp",
R"cpp(// Typedef
- typedef int [[Foo]];
+ typedef int $decl[[Foo]];
int main() {
^Foo bar;
}
@@ -244,7 +292,7 @@ TEST(GoToDefinition, All) {
)cpp", */
R"cpp(// Namespace
- namespace [[ns]] {
+ namespace $decl[[ns]] {
struct Foo { static void bar(); }
} // namespace ns
int main() { ^ns::Foo::bar(); }
@@ -305,30 +353,45 @@ TEST(GoToDefinition, All) {
};
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();
@@ -337,26 +400,20 @@ TEST(GoToDefinition, Rank) {
}
)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"), Sym("Foo")));
+ EXPECT_THAT(locateSymbolAt(AST, T.point("2")), ElementsAre(Sym("str")));
+ EXPECT_THAT(locateSymbolAt(AST, T.point("3")),
+ ElementsAre(Sym("f"), Sym("Foo")));
+ EXPECT_THAT(locateSymbolAt(AST, T.point("4")), ElementsAre(Sym("g")));
+ EXPECT_THAT(locateSymbolAt(AST, T.point("5")),
+ ElementsAre(Sym("f"), Sym("Foo")));
+ EXPECT_THAT(locateSymbolAt(AST, T.point("6")),
+ ElementsAre(Sym("str"), Sym("Foo"), Sym("Foo")));
}
-TEST(GoToDefinition, RelPathsInCompileCommand) {
+TEST(LocateSymbol, RelPathsInCompileCommand) {
// The source is in "/clangd-test/src".
// We build in "/clangd-test/build".
@@ -378,7 +435,7 @@ int [[bar_not_preamble]];
// Make the compilation paths appear as ../src/foo.cpp in the compile
// commands.
SmallString<32> RelPathPrefix("..");
- sys::path::append(RelPathPrefix, "src");
+ llvm::sys::path::append(RelPathPrefix, "src");
std::string BuildDir = testPath("build");
MockCompilationDatabase CDB(BuildDir, RelPathPrefix);
@@ -398,24 +455,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) {
@@ -1062,46 +1118,39 @@ 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 = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("5"));
+ ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
+ EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", 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("7"));
+ 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 +1170,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 +1189,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) {
@@ -1219,7 +1268,7 @@ TEST(FindReferences, WithinAST) {
std::vector<Matcher<Location>> ExpectedLocations;
for (const auto &R : T.ranges())
ExpectedLocations.push_back(RangeIs(R));
- EXPECT_THAT(findReferences(AST, T.point()),
+ EXPECT_THAT(findReferences(AST, T.point(), 0),
ElementsAreArray(ExpectedLocations))
<< Test;
}
@@ -1266,7 +1315,7 @@ TEST(FindReferences, ExplicitSymbols) {
std::vector<Matcher<Location>> ExpectedLocations;
for (const auto &R : T.ranges())
ExpectedLocations.push_back(RangeIs(R));
- EXPECT_THAT(findReferences(AST, T.point()),
+ EXPECT_THAT(findReferences(AST, T.point(), 0),
ElementsAreArray(ExpectedLocations))
<< Test;
}
@@ -1281,7 +1330,7 @@ TEST(FindReferences, NeedsIndex) {
auto AST = TU.build();
// References in main file are returned without index.
- EXPECT_THAT(findReferences(AST, Main.point(), /*Index=*/nullptr),
+ EXPECT_THAT(findReferences(AST, Main.point(), 0, /*Index=*/nullptr),
ElementsAre(RangeIs(Main.range())));
Annotations IndexedMain(R"cpp(
int main() { [[f^oo]](); }
@@ -1292,21 +1341,25 @@ TEST(FindReferences, NeedsIndex) {
IndexedTU.Code = IndexedMain.code();
IndexedTU.Filename = "Indexed.cpp";
IndexedTU.HeaderCode = Header;
- EXPECT_THAT(findReferences(AST, Main.point(), IndexedTU.index().get()),
+ EXPECT_THAT(findReferences(AST, Main.point(), 0, IndexedTU.index().get()),
ElementsAre(RangeIs(Main.range()), RangeIs(IndexedMain.range())));
+ EXPECT_EQ(1u, findReferences(AST, Main.point(), /*Limit*/ 1,
+ IndexedTU.index().get())
+ .size());
+
// If the main file is in the index, we don't return duplicates.
// (even if the references are in a different location)
TU.Code = ("\n\n" + Main.code()).str();
- EXPECT_THAT(findReferences(AST, Main.point(), TU.index().get()),
+ EXPECT_THAT(findReferences(AST, Main.point(), 0, TU.index().get()),
ElementsAre(RangeIs(Main.range())));
}
TEST(FindReferences, NoQueryForLocalSymbols) {
struct RecordingIndex : public MemIndex {
- mutable Optional<DenseSet<SymbolID>> RefIDs;
+ mutable Optional<llvm::DenseSet<SymbolID>> RefIDs;
void refs(const RefsRequest &Req,
- function_ref<void(const Ref &)>) const override {
+ llvm::function_ref<void(const Ref &)>) const override {
RefIDs = Req.IDs;
}
};
@@ -1328,7 +1381,7 @@ TEST(FindReferences, NoQueryForLocalSymbols) {
Annotations File(T.AnnotatedCode);
RecordingIndex Rec;
auto AST = TestTU::withCode(File.code()).build();
- findReferences(AST, File.point(), &Rec);
+ findReferences(AST, File.point(), 0, &Rec);
if (T.WantQuery)
EXPECT_NE(Rec.RefIDs, None) << T.AnnotatedCode;
else
diff --git a/unittests/clangd/xpc/CMakeLists.txt b/unittests/clangd/xpc/CMakeLists.txt
new file mode 100644
index 00000000..229ad5af
--- /dev/null
+++ b/unittests/clangd/xpc/CMakeLists.txt
@@ -0,0 +1,21 @@
+set(LLVM_LINK_COMPONENTS
+ support
+ )
+
+get_filename_component(CLANGD_SOURCE_DIR
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../clangd REALPATH)
+include_directories(
+ ${CLANGD_SOURCE_DIR}
+ )
+
+add_extra_unittest(ClangdXpcTests
+ ConversionTests.cpp
+ )
+
+target_link_libraries(ClangdXpcTests
+ PRIVATE
+ clangdXpcJsonConversions
+ clangDaemon
+ LLVMSupport
+ LLVMTestingSupport
+ )
diff --git a/unittests/clangd/xpc/ConversionTests.cpp b/unittests/clangd/xpc/ConversionTests.cpp
new file mode 100644
index 00000000..5d0efd83
--- /dev/null
+++ b/unittests/clangd/xpc/ConversionTests.cpp
@@ -0,0 +1,35 @@
+//===-- ConversionTests.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 "gtest/gtest.h"
+
+#include <limits>
+
+namespace clang {
+namespace clangd {
+namespace {
+
+using namespace llvm;
+
+TEST(JsonXpcConversionTest, JsonToXpcToJson) {
+
+ for (auto &testcase :
+ {json::Value(false), json::Value(3.14), json::Value(42),
+ json::Value(-100), json::Value("foo"), json::Value(""),
+ json::Value("123"), json::Value(" "),
+ json::Value{true, "foo", nullptr, 42},
+ json::Value(json::Object{
+ {"a", true}, {"b", "foo"}, {"c", nullptr}, {"d", 42}})}) {
+ EXPECT_TRUE(testcase == xpcToJson(jsonToXpc(testcase))) << testcase;
+ }
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
diff --git a/unittests/include-fixer/FuzzySymbolIndexTests.cpp b/unittests/include-fixer/FuzzySymbolIndexTests.cpp
index 17679c5d..3886269f 100644
--- a/unittests/include-fixer/FuzzySymbolIndexTests.cpp
+++ b/unittests/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/include-fixer/IncludeFixerTest.cpp
index 519c0837..9b187485 100644
--- a/unittests/include-fixer/IncludeFixerTest.cpp
+++ b/unittests/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
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp b/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
index 1ad9e7f0..179ad258 100644
--- a/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
+++ b/unittests/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/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
//
//===----------------------------------------------------------------------===//
///